From f934ae27cc76c20f8e701bf2503e3ea521a9bb88 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 27 Jan 2023 08:44:24 +0100 Subject: [PATCH 001/354] [issue-449] fix parsing of package supplier and package originator Signed-off-by: Meret Behrens --- spdx/package.py | 8 +++++--- spdx/parsers/jsonyamlxml.py | 6 +++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/spdx/package.py b/spdx/package.py index 75c50dbe6..93b62e2cd 100644 --- a/spdx/package.py +++ b/spdx/package.py @@ -12,14 +12,16 @@ from datetime import datetime from enum import Enum from functools import reduce -from typing import Optional +from typing import Optional, Union from spdx import creationinfo from spdx import license from spdx import utils from spdx.checksum import Checksum, ChecksumAlgorithm +from spdx.creationinfo import Creator from spdx.parsers.builderexceptions import SPDXValueError from spdx.parsers.loggers import ErrorMessages +from spdx.utils import NoAssert class PackagePurpose(Enum): @@ -95,8 +97,8 @@ def __init__( self.spdx_id = spdx_id self.version = version self.file_name = file_name - self.supplier = supplier - self.originator = originator + self.supplier: Optional[Union[Creator, NoAssert]] = supplier + self.originator: Optional[Union[Creator, NoAssert]] = originator self.download_location = download_location self.files_analyzed = None self.homepage = None diff --git a/spdx/parsers/jsonyamlxml.py b/spdx/parsers/jsonyamlxml.py index 5469376b0..ab384a017 100644 --- a/spdx/parsers/jsonyamlxml.py +++ b/spdx/parsers/jsonyamlxml.py @@ -20,7 +20,7 @@ from spdx.parsers.builderexceptions import SPDXValueError, CardinalityError, OrderError from spdx.parsers.loggers import ErrorMessages from spdx.snippet import Snippet -from spdx.utils import UnKnown +from spdx.utils import UnKnown, NoAssert ERROR_MESSAGES = rdf.ERROR_MESSAGES @@ -1243,6 +1243,8 @@ def parse_pkg_supplier(self, pkg_supplier): - pkg_supplier: Python str/unicode """ if isinstance(pkg_supplier, str): + if pkg_supplier == "NOASSERTION": + return self.builder.set_pkg_supplier(self.document, NoAssert()) entity = self.builder.create_entity(self.document, pkg_supplier) try: return self.builder.set_pkg_supplier(self.document, entity) @@ -1261,6 +1263,8 @@ def parse_pkg_originator(self, pkg_originator): - pkg_originator: Python str/unicode """ if isinstance(pkg_originator, str): + if pkg_originator == "NOASSERTION": + return self.builder.set_pkg_originator(self.document, NoAssert()) entity = self.builder.create_entity(self.document, pkg_originator) try: return self.builder.set_pkg_originator(self.document, entity) From 7256a75491082ceee6addf0be1180f60f60fd426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 30 Jan 2023 11:12:19 +0100 Subject: [PATCH 002/354] [issue-451] use uritools.isabsuri for namespace validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- pyproject.toml | 2 +- spdx/parsers/validations.py | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6c44a244f..64b45b806 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ classifiers = [ ] urls = {Homepage = "https://github.com/spdx/tools-python"} requires-python = ">=3.7" -dependencies = ["ply", "rdflib", "click", "pyyaml", "xmltodict"] +dependencies = ["ply", "rdflib", "click", "pyyaml", "xmltodict", "uritools"] dynamic = ["version"] [project.optional-dependencies] diff --git a/spdx/parsers/validations.py b/spdx/parsers/validations.py index d8a8b4cf9..34d05c19c 100644 --- a/spdx/parsers/validations.py +++ b/spdx/parsers/validations.py @@ -12,6 +12,7 @@ import re import rdflib +import uritools from spdx import creationinfo from spdx import license @@ -151,11 +152,7 @@ def validate_doc_spdx_id(value, optional=False): def validate_doc_namespace(value, optional=False): if value is None: return optional - elif ( - value.startswith("http://") - or value.startswith("https://") - or value.startswith("ftp://") - ) and ("#" not in value): + elif uritools.isabsuri(value) and ("#" not in value): return True else: return False From ae9e826030148d306bc4f70b6c4fffdfeaf980c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 30 Jan 2023 11:52:45 +0100 Subject: [PATCH 003/354] [refactor] shorten validation logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- spdx/parsers/validations.py | 82 +++++++++---------------------------- 1 file changed, 20 insertions(+), 62 deletions(-) diff --git a/spdx/parsers/validations.py b/spdx/parsers/validations.py index 34d05c19c..f93112306 100644 --- a/spdx/parsers/validations.py +++ b/spdx/parsers/validations.py @@ -34,10 +34,7 @@ def validate_is_free_form_text_or_str(value, optional=False) -> bool: def validate_tool_name(value, optional=False): striped_value = value.strip() if optional: - if len(striped_value) == 0: - return True - else: - return False + return len(striped_value) == 0 else: return not (len(striped_value) == 0) @@ -61,12 +58,9 @@ def validate_doc_name(value, optional=False): def validate_pkg_supplier(value, optional=False): if optional and value is None: return True - elif isinstance( + return isinstance( value, (utils.NoAssert, creationinfo.Person, creationinfo.Organization) - ): - return True - else: - return False + ) def validate_pkg_originator(value, optional=False): @@ -76,10 +70,8 @@ def validate_pkg_originator(value, optional=False): def validate_pkg_homepage(value, optional=False): if value is None: return optional - elif isinstance(value, (str, utils.NoAssert, utils.SPDXNone)): - return True - else: - return False + + return isinstance(value, (str, utils.NoAssert, utils.SPDXNone)) def validate_pkg_cr_text(value, optional=False): @@ -119,17 +111,11 @@ def validate_snippet_attribution_text(value, optional=False): def validate_pkg_ext_ref_category(value, optional=False): # PACKAGE_MANAGER is used in the json schema for 2.2. For now, we simply allow both versions - if value.upper() in ["SECURITY", "OTHER", "PACKAGE-MANAGER", "PACKAGE_MANAGER"]: - return True - else: - return False + return value.upper() in ["SECURITY", "OTHER", "PACKAGE-MANAGER", "PACKAGE_MANAGER"] def validate_pkg_ext_ref_type(value, optional=False): - if re.match(r"^\S+$", value) is not None: - return True - else: - return False + return re.match(r"^\S+$", value) is not None def validate_pkg_ext_ref_comment(value, optional=False): @@ -143,19 +129,15 @@ def validate_doc_comment(value, optional=False): def validate_doc_spdx_id(value, optional=False): if value is None: return optional - elif value.endswith("#SPDXRef-DOCUMENT"): - return True - else: - return False + + return value.endswith("#SPDXRef-DOCUMENT") def validate_doc_namespace(value, optional=False): if value is None: return optional - elif uritools.isabsuri(value) and ("#" not in value): - return True - else: - return False + + return uritools.isabsuri(value) and ("#" not in value) def validate_creator(value, optional=False): @@ -187,10 +169,7 @@ def validate_annotation_comment(value, optional=False): def validate_annotation_type(value, optional=False): value = value.strip() - if value == "REVIEW" or value == "OTHER": - return True - else: - return False + return value == "REVIEW" or value == "OTHER" def validate_relationship_comment(value, optional=False): @@ -241,19 +220,13 @@ def validate_file_lics_comment(value, optional=False): def validate_file_cpyright(value, optional=False): if isinstance(value, (utils.NoAssert, utils.SPDXNone)): return True - elif validate_is_free_form_text_or_str(value, optional): - return True - else: - return False + return validate_is_free_form_text_or_str(value, optional) def validate_lics_from_file(value, optional=False): if value is None: return optional - elif isinstance(value, (license.License, utils.SPDXNone, utils.NoAssert)): - return True - else: - return False + return isinstance(value, (license.License, utils.SPDXNone, utils.NoAssert)) def validate_file_notice(value, optional=False): @@ -263,19 +236,13 @@ def validate_file_notice(value, optional=False): def validate_lics_conc(value, optional=False): if value is None: return optional - elif isinstance(value, (utils.NoAssert, utils.SPDXNone, license.License)): - return True - else: - return False + return isinstance(value, (utils.NoAssert, utils.SPDXNone, license.License)) def validate_file_lics_in_file(value, optional=False): if value is None: return optional - elif isinstance(value, (utils.NoAssert, utils.SPDXNone, license.License)): - return True - else: - return False + return isinstance(value, (utils.NoAssert, utils.SPDXNone, license.License)) def validate_extracted_lic_id(value, optional=False): @@ -296,10 +263,7 @@ def validate_snippet_spdx_id(value, optional=False): if value is None: return optional value = value.split("#")[-1] - if re.match(r"^SPDXRef[A-Za-z0-9.\-]+$", value) is not None: - return True - else: - return False + return re.match(r"^SPDXRef[A-Za-z0-9.\-]+$", value) is not None def validate_snip_comment(value, optional=False): @@ -324,19 +288,13 @@ def validate_snip_lic_comment(value, optional=False): def validate_snip_file_spdxid(value, optional=False): if value is None: return optional - if ( + return ( re.match(r"(DocumentRef[A-Za-z0-9.\-]+:){0,1}SPDXRef[A-Za-z0-9.\-]+", value) is not None - ): - return True - else: - return False + ) def validate_snip_lics_info(value, optional=False): if value is None: return optional - elif isinstance(value, (utils.NoAssert, utils.SPDXNone, license.License)): - return True - else: - return False + return isinstance(value, (utils.NoAssert, utils.SPDXNone, license.License)) From cdf1787ec3e6570fb88412489a02e600f8991cbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 30 Jan 2023 10:44:36 +0100 Subject: [PATCH 004/354] [issue-451] make checksum validation lowercase only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit also add tests for it Signed-off-by: Armin Tänzer --- spdx/checksum.py | 2 +- spdx/parsers/lexers/tagvalue.py | 2 +- tests/test_checksum.py | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/spdx/checksum.py b/spdx/checksum.py index 315814269..634a59ad5 100644 --- a/spdx/checksum.py +++ b/spdx/checksum.py @@ -71,7 +71,7 @@ def __eq__(self, other) -> bool: @classmethod def checksum_from_string(cls, value: str) -> 'Checksum': CHECKSUM_RE = re.compile("(ADLER32|BLAKE2b-256|BLAKE2b-384|BLAKE2b-512|BLAKE3|MD2|MD4|MD5|MD6|" \ - "SHA1|SHA224|SHA256|SHA384|SHA512|SHA3-256|SHA3-384|SHA3-512):\\s*([a-fA-F0-9]*)") + "SHA1|SHA224|SHA256|SHA384|SHA512|SHA3-256|SHA3-384|SHA3-512):\\s*([a-f0-9]+)") match = CHECKSUM_RE.match(value) if match is None or match.group(1) is None or match.group(2) is None: raise ValueError(f"Invalid checksum: {value}") diff --git a/spdx/parsers/lexers/tagvalue.py b/spdx/parsers/lexers/tagvalue.py index 83c709a0d..ba7aa62a9 100644 --- a/spdx/parsers/lexers/tagvalue.py +++ b/spdx/parsers/lexers/tagvalue.py @@ -166,7 +166,7 @@ def t_text_error(self, t): def t_CHKSUM(self, t): r":\s*(ADLER32|BLAKE2b-256|BLAKE2b-384|BLAKE2b-512|BLAKE3|MD2|MD4|MD5|MD6|" \ - "SHA1|SHA224|SHA256|SHA384|SHA512|SHA3-256|SHA3-384|SHA3-512):\s*([a-fA-F0-9]*)" + "SHA1|SHA224|SHA256|SHA384|SHA512|SHA3-256|SHA3-384|SHA3-512):\s*([a-f0-9]*)" t.value = t.value[1:].strip() return t diff --git a/tests/test_checksum.py b/tests/test_checksum.py index 03ff16b03..befba2033 100644 --- a/tests/test_checksum.py +++ b/tests/test_checksum.py @@ -47,7 +47,7 @@ def test_checksum_from_wrong_rdf(rdf_algorithm): assert str(error.value).startswith("Invalid algorithm for checksum") -CHECKSUM_VALUE = "123Abc" +CHECKSUM_VALUE = "123abc" @pytest.mark.parametrize("checksum_string,expected", @@ -62,6 +62,12 @@ def test_checksum_from_string(checksum_string: str, expected: Checksum): assert checksum == expected +@pytest.mark.parametrize("checksum_string", ["SHA1: ABC", "SHA1000: abc"]) +def test_wrong_checksum_from_string(checksum_string: str): + with pytest.raises(ValueError, match=f"Invalid checksum: {checksum_string}"): + Checksum.checksum_from_string(checksum_string) + + @pytest.mark.parametrize("checksum, expected", [(Checksum(ChecksumAlgorithm.SHA1, CHECKSUM_VALUE), "SHA1: " + CHECKSUM_VALUE), (Checksum(ChecksumAlgorithm.SHA3_256, CHECKSUM_VALUE), "SHA3-256: " + CHECKSUM_VALUE), From 088725bae0346bb28c40ed3ad67b5bbc8e8b3b99 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 9 Feb 2023 15:10:17 +0100 Subject: [PATCH 005/354] make it possibile to set encoding Signed-off-by: Christian Decker --- spdx/writers/write_anything.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spdx/writers/write_anything.py b/spdx/writers/write_anything.py index 5e479ef6e..d7fdea19d 100644 --- a/spdx/writers/write_anything.py +++ b/spdx/writers/write_anything.py @@ -18,7 +18,7 @@ from spdx.parsers.builderexceptions import FileTypeError -def write_file(doc, fn, validate=True): +def write_file(doc, fn, validate=True, encoding="utf-8"): out_mode = "w" if fn.endswith(".rdf") or fn.endswith(".rdf.xml"): writer_module = rdf @@ -34,5 +34,5 @@ def write_file(doc, fn, validate=True): else: raise FileTypeError("FileType Not Supported") - with open(fn, out_mode) as out: + with open(fn, out_mode, encoding=encoding) as out: p = writer_module.write_document(doc, out, validate) From 830960459f480074d07cb120a8e8b3e79e584262 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Fri, 10 Feb 2023 10:51:29 +0100 Subject: [PATCH 006/354] add requirements.txt Signed-off-by: Christian Decker --- CONTRIBUTING.md | 5 ++++- requirements.txt | 7 +++++++ spdx/parsers/parse_anything.py | 7 +++++-- spdx/writers/write_anything.py | 1 + 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 requirements.txt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 03e43d245..45d32261f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,9 +26,12 @@ Here's the process to make changes to the codebase: 2. Review [open pull requests](https://github.com/spdx/tools-python/pulls) before committing time to a substantial revision. Work along similar lines may already be in progress. -3. Create a new branch: +3. Create a new branch and set up environment: ```sh git checkout -b fix-or-improve-something + python -m venv ./venv + ./venv/bin/activate + pip install -r requirements.txt ``` 4. Make some changes and commit them to the branch: ```sh diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..c7161f6e2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +click +ply +pytest +pyyaml +rdflib +uritools +xmltodict \ No newline at end of file diff --git a/spdx/parsers/parse_anything.py b/spdx/parsers/parse_anything.py index 329ea6944..d7c4ccdee 100644 --- a/spdx/parsers/parse_anything.py +++ b/spdx/parsers/parse_anything.py @@ -21,10 +21,13 @@ from spdx.parsers.builderexceptions import FileTypeError -def parse_file(fn): +def parse_file(fn, encoding="utf-8"): + in_mode = "r" builder_module = jsonyamlxmlbuilders read_data = False if fn.endswith(".rdf") or fn.endswith(".rdf.xml"): + in_mode = "rb" + encoding = None parsing_module = rdf builder_module = rdfbuilders elif fn.endswith(".tag") or fn.endswith(".spdx"): @@ -43,7 +46,7 @@ def parse_file(fn): p = parsing_module.Parser(builder_module.Builder(), StandardLogger()) if hasattr(p, "build"): p.build() - with open(fn) as f: + with open(fn, in_mode, encoding=encoding) as f: if read_data: data = f.read() return p.parse(data) diff --git a/spdx/writers/write_anything.py b/spdx/writers/write_anything.py index d7fdea19d..63a4f4c3b 100644 --- a/spdx/writers/write_anything.py +++ b/spdx/writers/write_anything.py @@ -23,6 +23,7 @@ def write_file(doc, fn, validate=True, encoding="utf-8"): if fn.endswith(".rdf") or fn.endswith(".rdf.xml"): writer_module = rdf out_mode = "wb" + encoding = None elif fn.endswith(".tag") or fn.endswith(".spdx"): writer_module = tagvalue elif fn.endswith(".json"): From d6932e2d295a53c619deffd949ec30622a248765 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Fri, 10 Feb 2023 13:38:22 +0100 Subject: [PATCH 007/354] use pip install -e . Signed-off-by: Christian Decker --- CONTRIBUTING.md | 2 +- requirements.txt | 7 ------- spdx/parsers/parse_anything.py | 4 +--- 3 files changed, 2 insertions(+), 11 deletions(-) delete mode 100644 requirements.txt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 45d32261f..4f5fc4ea0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,7 +31,7 @@ Here's the process to make changes to the codebase: git checkout -b fix-or-improve-something python -m venv ./venv ./venv/bin/activate - pip install -r requirements.txt + pip install -e . ``` 4. Make some changes and commit them to the branch: ```sh diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index c7161f6e2..000000000 --- a/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -click -ply -pytest -pyyaml -rdflib -uritools -xmltodict \ No newline at end of file diff --git a/spdx/parsers/parse_anything.py b/spdx/parsers/parse_anything.py index d7c4ccdee..906337fff 100644 --- a/spdx/parsers/parse_anything.py +++ b/spdx/parsers/parse_anything.py @@ -22,11 +22,9 @@ def parse_file(fn, encoding="utf-8"): - in_mode = "r" builder_module = jsonyamlxmlbuilders read_data = False if fn.endswith(".rdf") or fn.endswith(".rdf.xml"): - in_mode = "rb" encoding = None parsing_module = rdf builder_module = rdfbuilders @@ -46,7 +44,7 @@ def parse_file(fn, encoding="utf-8"): p = parsing_module.Parser(builder_module.Builder(), StandardLogger()) if hasattr(p, "build"): p.build() - with open(fn, in_mode, encoding=encoding) as f: + with open(fn, "r", encoding=encoding) as f: if read_data: data = f.read() return p.parse(data) From ccd0758e550b4b94acee50724b89d9845d125200 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Tue, 14 Feb 2023 10:35:28 +0100 Subject: [PATCH 008/354] allow empty arrays for hasFiles and licenseInfoFromFiles Signed-off-by: Christian Decker --- spdx/parsers/jsonyamlxml.py | 12 ++-- .../formats/SPDXJsonExampleEmptyArrays.json | 63 +++++++++++++++++++ tests/test_parse_anything.py | 1 + tests/test_write_anything.py | 5 +- 4 files changed, 74 insertions(+), 7 deletions(-) create mode 100644 tests/data/formats/SPDXJsonExampleEmptyArrays.json diff --git a/spdx/parsers/jsonyamlxml.py b/spdx/parsers/jsonyamlxml.py index ab384a017..5d27ae9a9 100644 --- a/spdx/parsers/jsonyamlxml.py +++ b/spdx/parsers/jsonyamlxml.py @@ -1440,9 +1440,9 @@ def parse_pkg_license_info_from_files(self, license_info_from_files): - license_info_from_files: Python list of licenses information from files (str/unicode) """ if not self.package.are_files_analyzed: - if license_info_from_files is not None: - self.value_error("PKG_LIC_FRM_FILES", license_info_from_files) - return + if not license_info_from_files: + return + self.value_error("PKG_LIC_FRM_FILES", license_info_from_files) if isinstance(license_info_from_files, list): for license_info_from_file in license_info_from_files: if isinstance(license_info_from_file, str): @@ -1591,9 +1591,9 @@ def parse_pkg_files(self, pkg_has_files: List[str], method_to_parse_relationship - pkg_has_files: Python list of spdx_ids """ if not self.package.are_files_analyzed: - if pkg_has_files is not None: - self.value_error("PKG_FILES", pkg_has_files) - return + if not pkg_has_files: + return + self.value_error("PKG_FILES", pkg_has_files) if isinstance(pkg_has_files, list): for pkg_file_spdx_id in pkg_has_files: diff --git a/tests/data/formats/SPDXJsonExampleEmptyArrays.json b/tests/data/formats/SPDXJsonExampleEmptyArrays.json new file mode 100644 index 000000000..261c31e8f --- /dev/null +++ b/tests/data/formats/SPDXJsonExampleEmptyArrays.json @@ -0,0 +1,63 @@ +{ + "comment": "This is a sample spreadsheet", + "name": "Sample_Document-V2.1", + "documentDescribes": [ + "SPDXRef-Package" + ], + "packages": [ + { + "SPDXID" : "SPDXRef-2269-coverlet.collector.3.2.0.nupkg", + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "0cf7564fcbdee13f6313edd8bc261ca0564a4bf7" + } ], + "copyrightText" : "NOASSERTION", + "description" : "Coverlet is a cross platform code coverage library for .NET, with support for line, branch and method coverage.", + "downloadLocation" : "https://api.nuget.org/packages/coverlet.collector.3.2.0.nupkg", + "filesAnalyzed" : false, + "hasFiles" : [ ], + "homepage" : "https://github.com/coverlet-coverage/coverlet", + "licenseConcluded" : "(MIT)", + "licenseDeclared" : "(MIT)", + "licenseInfoFromFiles" : [ ], + "name" : "coverlet.collector.3.2.0.nupkg", + "originator" : "Organization: tonerdo", + "packageFileName" : "coverlet.collector.3.2.0.nupkg", + "supplier" : "Organization: tonerdo", + "versionInfo" : "3.2.0" + }, + { + "SPDXID" : "SPDXRef-2269-coverlet.collector.3.2.0.nupkg", + "checksums" : [ { + "algorithm" : "SHA1", + "checksumValue" : "0cf7564fcbdee13f6313edd8bc261ca0564a4bf7" + } ], + "copyrightText" : "NOASSERTION", + "description" : "Coverlet is a cross platform code coverage library for .NET, with support for line, branch and method coverage.", + "downloadLocation" : "https://api.nuget.org/packages/coverlet.collector.3.2.0.nupkg", + "filesAnalyzed" : false, + "homepage" : "https://github.com/coverlet-coverage/coverlet", + "licenseConcluded" : "(MIT)", + "licenseDeclared" : "(MIT)", + "name" : "coverlet.collector.3.2.0.nupkg", + "originator" : "Organization: tonerdo", + "packageFileName" : "coverlet.collector.3.2.0.nupkg", + "supplier" : "Organization: tonerdo", + "versionInfo" : "3.2.0" + } + ], + "creationInfo": { + "comment": "This is an example of an SPDX spreadsheet format", + "creators": [ + "Tool: SourceAuditor-V1.2", + "Person: Gary O'Neall", + "Organization: Source Auditor Inc." + ], + "licenseListVersion": "3.6", + "created": "2010-02-03T00:00:00Z" + }, + "documentNamespace": "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", + "dataLicense": "CC0-1.0", + "spdxVersion": "SPDX-2.1", + "SPDXID": "SPDXRef-DOCUMENT" +} diff --git a/tests/test_parse_anything.py b/tests/test_parse_anything.py index 6342153ec..c133f9b0b 100644 --- a/tests/test_parse_anything.py +++ b/tests/test_parse_anything.py @@ -30,3 +30,4 @@ def test_parse_anything(test_file): assert doc.name in ('Sample_Document-V2.1', 'xyz-0.1.0', 'SPDX-Tools-v2.0') assert doc.comment in (None, 'This is a sample spreadsheet', 'Sample Comment', 'This document was created using SPDX 2.0 using licenses from the web site.') + assert len(doc.packages) in (1, 2, 3, 4) diff --git a/tests/test_write_anything.py b/tests/test_write_anything.py index 5f3c8b915..5fe034dd9 100644 --- a/tests/test_write_anything.py +++ b/tests/test_write_anything.py @@ -35,7 +35,10 @@ "SPDXXMLExample-v2.2.spdx.xml-tag", "SPDXYAMLExample-2.3.spdx.yaml-tag", "SPDXJSONExample-v2.3.spdx.json-tag", - "SPDXXMLExample-v2.3.spdx.xml-tag" + "SPDXXMLExample-v2.3.spdx.xml-tag", + "SPDXJsonExampleEmptyArrays.json-json", + "SPDXJsonExampleEmptyArrays.json-xml", + "SPDXJsonExampleEmptyArrays.json-yaml" } From b7294172d36425718c98876810fe727c224272d3 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 9 Feb 2023 16:19:56 +0100 Subject: [PATCH 009/354] [issue-468] add a step to fork the repository Signed-off-by: Meret Behrens --- CONTRIBUTING.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f5fc4ea0..6352e3894 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,14 +26,17 @@ Here's the process to make changes to the codebase: 2. Review [open pull requests](https://github.com/spdx/tools-python/pulls) before committing time to a substantial revision. Work along similar lines may already be in progress. -3. Create a new branch and set up environment: +3. Fork the repository as described [here](https://docs.github.com/en/get-started/quickstart/fork-a-repo#forking-a-repository) + and optionally follow the further steps described to sync your fork and the original repository. + +4. Create a new branch in your fork and set up environment: ```sh git checkout -b fix-or-improve-something python -m venv ./venv ./venv/bin/activate pip install -e . ``` -4. Make some changes and commit them to the branch: +5. Make some changes and commit them to the branch: ```sh git commit --signoff -m 'description of my changes' ``` @@ -45,22 +48,22 @@ Here's the process to make changes to the codebase: commits: `git commit -s` or `--signoff` signs a current commit, and `git rebase --signoff ` retroactively signs a range of past commits. -5. Test your changes: +6. Test your changes: ```sh python setup.py test # in the repo root ``` You may use other test runners, such as `pytest` or `nose` at your preference. -6. Push the branch to your fork on GitHub: +7. Push the branch to your fork on GitHub: ```sh git push origin fix-or-improve-something ``` -7. Make a pull request on GitHub. -8. Continue making more changes and commits on the branch, with `git commit --signoff` and `git push`. -9. When done, write a comment on the PR asking for a code review. -10. Some other developer will review your changes and accept your PR. The merge should be done with `rebase`, if +8. Make a pull request on GitHub. +9. Continue making more changes and commits on the branch, with `git commit --signoff` and `git push`. +10. When done, write a comment on the PR asking for a code review. +11. Some other developer will review your changes and accept your PR. The merge should be done with `rebase`, if possible, or with `squash`. -11. The temporary branch on GitHub should be deleted (there is a button for deleting it). -12. Delete the local branch as well: +12. The temporary branch on GitHub should be deleted (there is a button for deleting it). +13. Delete the local branch as well: ```sh git checkout master git pull -p From 58e691ea48b91fe6aaa52ae93a80994a82b4da31 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 14 Feb 2023 09:37:44 +0100 Subject: [PATCH 010/354] [issue-479] fix parsing of snippet ranges The previous regular expressions for ranges would prevent lines with ":" to be parsed as LINE and instead be parsed as RANGE, the remainder after ":\d+" would be truncated and ignored, this lead to problems when parsing a package version like "1:2.36.1-8+deb11u1". Instead of defining a separate lexer function for RANGE we check if a LINE token matches the RANGE-pattern. This allows LINEs to include the RANGE pattern without getting the token RANGE. Signed-off-by: Meret Behrens --- spdx/parsers/lexers/tagvalue.py | 9 +++++---- tests/test_tag_value_parser.py | 12 ++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/spdx/parsers/lexers/tagvalue.py b/spdx/parsers/lexers/tagvalue.py index ba7aa62a9..61a99adff 100644 --- a/spdx/parsers/lexers/tagvalue.py +++ b/spdx/parsers/lexers/tagvalue.py @@ -8,6 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import re from ply import lex @@ -170,10 +171,6 @@ def t_CHKSUM(self, t): t.value = t.value[1:].strip() return t - def t_RANGE(self, t): - r":\s*\d+:\d+" - t.value = t.value[1:].strip() - return t def t_DOC_REF_ID(self, t): r":\s*DocumentRef-([A-Za-z0-9\+\.\-]+)" @@ -221,6 +218,10 @@ def t_LINE_OR_KEYWORD_VALUE(self, t): t.value = t.value[1:].strip() if t.value in self.reserved.keys(): t.type = self.reserved[t.value] + return t + range_pattern = re.compile("\d+:\d(?!\D)") + if range_pattern.match(t.value): + t.type = "RANGE" else: t.type = "LINE" return t diff --git a/tests/test_tag_value_parser.py b/tests/test_tag_value_parser.py index 4008c3090..6ce4af7c9 100644 --- a/tests/test_tag_value_parser.py +++ b/tests/test_tag_value_parser.py @@ -50,7 +50,7 @@ package_str = '\n'.join([ 'PackageName: Test', 'SPDXID: SPDXRef-Package', - 'PackageVersion: Version 0.9.2', + 'PackageVersion: 1:2.36.1-8+deb11u1', 'PackageDownloadLocation: http://example.com/test', 'FilesAnalyzed: True', 'PackageSummary: Test package', @@ -104,7 +104,7 @@ 'SnippetLicenseConcluded: Apache-2.0', 'LicenseInfoInSnippet: Apache-2.0', 'SnippetByteRange: 310:420', - 'SnippetLineRange: 5:23', + 'SnippetLineRange: 5:7', ]) annotation_str = '\n'.join([ @@ -195,7 +195,7 @@ def test_package(self): self.token_assert_helper(self.l.token(), 'SPDX_ID', 'SPDXID', 2) self.token_assert_helper(self.l.token(), 'LINE', 'SPDXRef-Package', 2) self.token_assert_helper(self.l.token(), 'PKG_VERSION', 'PackageVersion', 3) - self.token_assert_helper(self.l.token(), 'LINE', 'Version 0.9.2', 3) + self.token_assert_helper(self.l.token(), 'LINE', '1:2.36.1-8+deb11u1', 3) self.token_assert_helper(self.l.token(), 'PKG_DOWN', 'PackageDownloadLocation', 4) self.token_assert_helper(self.l.token(), 'LINE', 'http://example.com/test', 4) self.token_assert_helper(self.l.token(), 'PKG_FILES_ANALYZED', 'FilesAnalyzed', 5) @@ -275,7 +275,7 @@ def test_snippet(self): self.token_assert_helper(self.l.token(), 'SNIPPET_BYTE_RANGE', 'SnippetByteRange', 9) self.token_assert_helper(self.l.token(), 'RANGE', '310:420', 9) self.token_assert_helper(self.l.token(), 'SNIPPET_LINE_RANGE', 'SnippetLineRange', 10) - self.token_assert_helper(self.l.token(), 'RANGE', '5:23', 10) + self.token_assert_helper(self.l.token(), 'RANGE', '5:7', 10) def test_annotation(self): data = annotation_str @@ -337,7 +337,7 @@ def test_package(self): assert not error assert document.package.name == 'Test' assert document.package.spdx_id == 'SPDXRef-Package' - assert document.package.version == 'Version 0.9.2' + assert document.package.version == '1:2.36.1-8+deb11u1' assert len(document.package.licenses_from_files) == 2 assert (document.package.conc_lics.identifier == 'LicenseRef-2.0 AND Apache-2.0') assert document.package.files_analyzed is True @@ -408,4 +408,4 @@ def test_snippet(self): assert document.snippet[-1].byte_range[0] == 310 assert document.snippet[-1].byte_range[1] == 420 assert document.snippet[-1].line_range[0] == 5 - assert document.snippet[-1].line_range[1] == 23 + assert document.snippet[-1].line_range[1] == 7 From 49fb24bf0a393efe6206e3b6a97548e7e0d0ffa1 Mon Sep 17 00:00:00 2001 From: Marc-Etienne Vargenau Date: Thu, 23 Feb 2023 11:53:12 +0100 Subject: [PATCH 011/354] Update licenseListVersion to 3.20 Signed-off-by: Marc-Etienne Vargenau --- spdx/exceptions.json | 654 +- spdx/licenses.json | 7410 ++++++++++------- .../doc_write/json-simple-multi-package.json | 2 +- tests/data/doc_write/json-simple-plus.json | 2 +- tests/data/doc_write/json-simple.json | 2 +- tests/data/doc_write/tv-mini.tv | 2 +- tests/data/doc_write/tv-simple-plus.tv | 2 +- tests/data/doc_write/tv-simple.tv | 2 +- .../doc_write/xml-simple-multi-package.xml | 2 +- .../doc_write/yaml-simple-multi-package.yaml | 4 +- tests/data/doc_write/yaml-simple-plus.yaml | 2 +- tests/data/doc_write/yaml-simple.yaml | 2 +- tests/data/formats/SPDXJsonExample.json | 2 +- .../formats/SPDXJsonExampleEmptyArrays.json | 2 +- tests/data/formats/SPDXXmlExample.xml | 2 +- tests/data/formats/SPDXYamlExample.yaml | 2 +- tests/test_config.py | 6 +- 17 files changed, 5010 insertions(+), 3090 deletions(-) diff --git a/spdx/exceptions.json b/spdx/exceptions.json index 0f77cd372..3c72dc74b 100644 --- a/spdx/exceptions.json +++ b/spdx/exceptions.json @@ -1,408 +1,558 @@ { - "licenseListVersion": "3.6", - "releaseDate": "2019-07-10", + "licenseListVersion": "3.20", "exceptions": [ { - "reference": "./Libtool-exception.html", + "reference": "./WxWindows-exception-3.1.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Libtool-exception.json", - "referenceNumber": "1", - "name": "Libtool Exception", + "detailsUrl": "./WxWindows-exception-3.1.html", + "referenceNumber": 1, + "name": "WxWindows Library Exception 3.1", + "licenseExceptionId": "WxWindows-exception-3.1", "seeAlso": [ - "http://git.savannah.gnu.org/cgit/libtool.git/tree/m4/libtool.m4" - ], - "licenseExceptionId": "Libtool-exception" + "http://www.opensource.org/licenses/WXwindows" + ] }, { - "reference": "./Linux-syscall-note.html", + "reference": "./i2p-gpl-java-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Linux-syscall-note.json", - "referenceNumber": "2", - "name": "Linux Syscall Note", + "detailsUrl": "./i2p-gpl-java-exception.html", + "referenceNumber": 2, + "name": "i2p GPL+Java Exception", + "licenseExceptionId": "i2p-gpl-java-exception", "seeAlso": [ - "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/COPYING" - ], - "licenseExceptionId": "Linux-syscall-note" + "http://geti2p.net/en/get-involved/develop/licenses#java_exception" + ] + }, + { + "reference": "./Swift-exception.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./Swift-exception.html", + "referenceNumber": 3, + "name": "Swift Exception", + "licenseExceptionId": "Swift-exception", + "seeAlso": [ + "https://swift.org/LICENSE.txt", + "https://github.com/apple/swift-package-manager/blob/7ab2275f447a5eb37497ed63a9340f8a6d1e488b/LICENSE.txt#L205" + ] + }, + { + "reference": "./SWI-exception.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./SWI-exception.html", + "referenceNumber": 4, + "name": "SWI exception", + "licenseExceptionId": "SWI-exception", + "seeAlso": [ + "https://github.com/SWI-Prolog/packages-clpqr/blob/bfa80b9270274f0800120d5b8e6fef42ac2dc6a5/clpqr/class.pl" + ] }, { - "reference": "./Autoconf-exception-3.0.html", + "reference": "./CLISP-exception-2.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Autoconf-exception-3.0.json", - "referenceNumber": "3", + "detailsUrl": "./CLISP-exception-2.0.html", + "referenceNumber": 5, + "name": "CLISP exception 2.0", + "licenseExceptionId": "CLISP-exception-2.0", + "seeAlso": [ + "http://sourceforge.net/p/clisp/clisp/ci/default/tree/COPYRIGHT" + ] + }, + { + "reference": "./GPL-3.0-linking-exception.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./GPL-3.0-linking-exception.html", + "referenceNumber": 6, + "name": "GPL-3.0 Linking Exception", + "licenseExceptionId": "GPL-3.0-linking-exception", + "seeAlso": [ + "https://www.gnu.org/licenses/gpl-faq.en.html#GPLIncompatibleLibs" + ] + }, + { + "reference": "./LGPL-3.0-linking-exception.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./LGPL-3.0-linking-exception.html", + "referenceNumber": 7, + "name": "LGPL-3.0 Linking Exception", + "licenseExceptionId": "LGPL-3.0-linking-exception", + "seeAlso": [ + "https://raw.githubusercontent.com/go-xmlpath/xmlpath/v2/LICENSE", + "https://github.com/goamz/goamz/blob/master/LICENSE", + "https://github.com/juju/errors/blob/master/LICENSE" + ] + }, + { + "reference": "./Autoconf-exception-3.0.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./Autoconf-exception-3.0.html", + "referenceNumber": 8, "name": "Autoconf exception 3.0", + "licenseExceptionId": "Autoconf-exception-3.0", "seeAlso": [ "http://www.gnu.org/licenses/autoconf-exception-3.0.html" - ], - "licenseExceptionId": "Autoconf-exception-3.0" + ] }, { - "reference": "./OCCT-exception-1.0.html", + "reference": "./Autoconf-exception-2.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OCCT-exception-1.0.json", - "referenceNumber": "4", - "name": "Open CASCADE Exception 1.0", + "detailsUrl": "./Autoconf-exception-2.0.html", + "referenceNumber": 9, + "name": "Autoconf exception 2.0", + "licenseExceptionId": "Autoconf-exception-2.0", "seeAlso": [ - "http://www.opencascade.com/content/licensing" - ], - "licenseExceptionId": "OCCT-exception-1.0" + "http://ac-archive.sourceforge.net/doc/copyright.html", + "http://ftp.gnu.org/gnu/autoconf/autoconf-2.59.tar.gz" + ] + }, + { + "reference": "./LZMA-exception.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./LZMA-exception.html", + "referenceNumber": 10, + "name": "LZMA exception", + "licenseExceptionId": "LZMA-exception", + "seeAlso": [ + "http://nsis.sourceforge.net/Docs/AppendixI.html#I.6" + ] + }, + { + "reference": "./GCC-exception-3.1.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./GCC-exception-3.1.html", + "referenceNumber": 11, + "name": "GCC Runtime Library exception 3.1", + "licenseExceptionId": "GCC-exception-3.1", + "seeAlso": [ + "http://www.gnu.org/licenses/gcc-exception-3.1.html" + ] + }, + { + "reference": "./QPL-1.0-INRIA-2004-exception.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./QPL-1.0-INRIA-2004-exception.html", + "referenceNumber": 12, + "name": "INRIA QPL 1.0 2004 variant exception", + "licenseExceptionId": "QPL-1.0-INRIA-2004-exception", + "seeAlso": [ + "https://git.frama-c.com/pub/frama-c/-/blob/master/licenses/Q_MODIFIED_LICENSE", + "https://github.com/maranget/hevea/blob/master/LICENSE" + ] }, { - "reference": "./openvpn-openssl-exception.html", + "reference": "./openvpn-openssl-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/openvpn-openssl-exception.json", - "referenceNumber": "5", + "detailsUrl": "./openvpn-openssl-exception.html", + "referenceNumber": 13, "name": "OpenVPN OpenSSL Exception", + "licenseExceptionId": "openvpn-openssl-exception", "seeAlso": [ "http://openvpn.net/index.php/license.html" - ], - "licenseExceptionId": "openvpn-openssl-exception" + ] }, { - "reference": "./gnu-javamail-exception.html", + "reference": "./u-boot-exception-2.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/gnu-javamail-exception.json", - "referenceNumber": "6", - "name": "GNU JavaMail exception", + "detailsUrl": "./u-boot-exception-2.0.html", + "referenceNumber": 14, + "name": "U-Boot exception 2.0", + "licenseExceptionId": "u-boot-exception-2.0", "seeAlso": [ - "http://www.gnu.org/software/classpathx/javamail/javamail.html" - ], - "licenseExceptionId": "gnu-javamail-exception" + "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003dLicenses/Exceptions" + ] }, { - "reference": "./OpenJDK-assembly-exception-1.0.html", + "reference": "./Linux-syscall-note.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OpenJDK-assembly-exception-1.0.json", - "referenceNumber": "7", - "name": "OpenJDK Assembly exception 1.0", + "detailsUrl": "./Linux-syscall-note.html", + "referenceNumber": 15, + "name": "Linux Syscall Note", + "licenseExceptionId": "Linux-syscall-note", "seeAlso": [ - "http://openjdk.java.net/legal/assembly-exception.html" - ], - "licenseExceptionId": "OpenJDK-assembly-exception-1.0" + "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/COPYING" + ] }, { - "reference": "./Bison-exception-2.2.html", + "reference": "./GNAT-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Bison-exception-2.2.json", - "referenceNumber": "8", - "name": "Bison exception 2.2", + "detailsUrl": "./GNAT-exception.html", + "referenceNumber": 16, + "name": "GNAT exception", + "licenseExceptionId": "GNAT-exception", "seeAlso": [ - "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141" - ], - "licenseExceptionId": "Bison-exception-2.2" + "https://github.com/AdaCore/florist/blob/master/libsrc/posix-configurable_file_limits.adb" + ] }, { - "reference": "./i2p-gpl-java-exception.html", + "reference": "./LLVM-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/i2p-gpl-java-exception.json", - "referenceNumber": "9", - "name": "i2p GPL+Java Exception", + "detailsUrl": "./LLVM-exception.html", + "referenceNumber": 17, + "name": "LLVM Exception", + "licenseExceptionId": "LLVM-exception", "seeAlso": [ - "http://geti2p.net/en/get-involved/develop/licenses#java_exception" - ], - "licenseExceptionId": "i2p-gpl-java-exception" + "http://llvm.org/foundation/relicensing/LICENSE.txt" + ] }, { - "reference": "./Universal-FOSS-exception-1.0.html", + "reference": "./PS-or-PDF-font-exception-20170817.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Universal-FOSS-exception-1.0.json", - "referenceNumber": "10", - "name": "Universal FOSS Exception, Version 1.0", + "detailsUrl": "./PS-or-PDF-font-exception-20170817.html", + "referenceNumber": 18, + "name": "PS/PDF font exception (2017-08-17)", + "licenseExceptionId": "PS-or-PDF-font-exception-20170817", "seeAlso": [ - "https://oss.oracle.com/licenses/universal-foss-exception/" - ], - "licenseExceptionId": "Universal-FOSS-exception-1.0" + "https://github.com/ArtifexSoftware/urw-base35-fonts/blob/65962e27febc3883a17e651cdb23e783668c996f/LICENSE" + ] }, { - "reference": "./Qt-LGPL-exception-1.1.html", + "reference": "./SHL-2.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Qt-LGPL-exception-1.1.json", - "referenceNumber": "11", - "name": "Qt LGPL exception 1.1", + "detailsUrl": "./SHL-2.0.html", + "referenceNumber": 19, + "name": "Solderpad Hardware License v2.0", + "licenseExceptionId": "SHL-2.0", "seeAlso": [ - "http://code.qt.io/cgit/qt/qtbase.git/tree/LGPL_EXCEPTION.txt" - ], - "licenseExceptionId": "Qt-LGPL-exception-1.1" + "https://solderpad.org/licenses/SHL-2.0/" + ] }, { - "reference": "./389-exception.html", + "reference": "./Bootloader-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/389-exception.json", - "referenceNumber": "12", - "name": "389 Directory Server Exception", + "detailsUrl": "./Bootloader-exception.html", + "referenceNumber": 20, + "name": "Bootloader Distribution Exception", + "licenseExceptionId": "Bootloader-exception", "seeAlso": [ - "http://directory.fedoraproject.org/wiki/GPL_Exception_License_Text" - ], - "licenseExceptionId": "389-exception" + "https://github.com/pyinstaller/pyinstaller/blob/develop/COPYING.txt" + ] }, { - "reference": "./Classpath-exception-2.0.html", + "reference": "./SHL-2.1.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Classpath-exception-2.0.json", - "referenceNumber": "13", - "name": "Classpath exception 2.0", + "detailsUrl": "./SHL-2.1.html", + "referenceNumber": 21, + "name": "Solderpad Hardware License v2.1", + "licenseExceptionId": "SHL-2.1", "seeAlso": [ - "http://www.gnu.org/software/classpath/license.html", - "https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception" - ], - "licenseExceptionId": "Classpath-exception-2.0" + "https://solderpad.org/licenses/SHL-2.1/" + ] }, { - "reference": "./Fawkes-Runtime-exception.html", + "reference": "./Fawkes-Runtime-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Fawkes-Runtime-exception.json", - "referenceNumber": "14", + "detailsUrl": "./Fawkes-Runtime-exception.html", + "referenceNumber": 22, "name": "Fawkes Runtime Exception", + "licenseExceptionId": "Fawkes-Runtime-exception", "seeAlso": [ "http://www.fawkesrobotics.org/about/license/" - ], - "licenseExceptionId": "Fawkes-Runtime-exception" + ] }, { - "reference": "./PS-or-PDF-font-exception-20170817.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/PS-or-PDF-font-exception-20170817.json", - "referenceNumber": "15", - "name": "PS/PDF font exception (2017-08-17)", + "reference": "./Nokia-Qt-exception-1.1.json", + "isDeprecatedLicenseId": true, + "detailsUrl": "./Nokia-Qt-exception-1.1.html", + "referenceNumber": 23, + "name": "Nokia Qt LGPL exception 1.1", + "licenseExceptionId": "Nokia-Qt-exception-1.1", "seeAlso": [ - "https://github.com/ArtifexSoftware/urw-base35-fonts/blob/65962e27febc3883a17e651cdb23e783668c996f/LICENSE" - ], - "licenseExceptionId": "PS-or-PDF-font-exception-20170817" + "https://www.keepassx.org/dev/projects/keepassx/repository/revisions/b8dfb9cc4d5133e0f09cd7533d15a4f1c19a40f2/entry/LICENSE.NOKIA-LGPL-EXCEPTION" + ] }, { - "reference": "./Qt-GPL-exception-1.0.html", + "reference": "./GCC-exception-2.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Qt-GPL-exception-1.0.json", - "referenceNumber": "16", - "name": "Qt GPL exception 1.0", + "detailsUrl": "./GCC-exception-2.0.html", + "referenceNumber": 24, + "name": "GCC Runtime Library exception 2.0", + "licenseExceptionId": "GCC-exception-2.0", "seeAlso": [ - "http://code.qt.io/cgit/qt/qtbase.git/tree/LICENSE.GPL3-EXCEPT" - ], - "licenseExceptionId": "Qt-GPL-exception-1.0" + "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10" + ] }, { - "reference": "./LZMA-exception.html", + "reference": "./freertos-exception-2.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LZMA-exception.json", - "referenceNumber": "17", - "name": "LZMA exception", + "detailsUrl": "./freertos-exception-2.0.html", + "referenceNumber": 25, + "name": "FreeRTOS Exception 2.0", + "licenseExceptionId": "freertos-exception-2.0", "seeAlso": [ - "http://nsis.sourceforge.net/Docs/AppendixI.html#I.6" - ], - "licenseExceptionId": "LZMA-exception" + "https://web.archive.org/web/20060809182744/http://www.freertos.org/a00114.html" + ] }, { - "reference": "./freertos-exception-2.0.html", + "reference": "./gnu-javamail-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/freertos-exception-2.0.json", - "referenceNumber": "18", - "name": "FreeRTOS Exception 2.0", + "detailsUrl": "./gnu-javamail-exception.html", + "referenceNumber": 26, + "name": "GNU JavaMail exception", + "licenseExceptionId": "gnu-javamail-exception", "seeAlso": [ - "https://web.archive.org/web/20060809182744/http://www.freertos.org/a00114.html" - ], - "licenseExceptionId": "freertos-exception-2.0" + "http://www.gnu.org/software/classpathx/javamail/javamail.html" + ] }, { - "reference": "./Qwt-exception-1.0.html", + "reference": "./GStreamer-exception-2008.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Qwt-exception-1.0.json", - "referenceNumber": "19", - "name": "Qwt exception 1.0", + "detailsUrl": "./GStreamer-exception-2008.html", + "referenceNumber": 27, + "name": "GStreamer Exception (2008)", + "licenseExceptionId": "GStreamer-exception-2008", "seeAlso": [ - "http://qwt.sourceforge.net/qwtlicense.html" - ], - "licenseExceptionId": "Qwt-exception-1.0" + "https://gstreamer.freedesktop.org/documentation/frequently-asked-questions/licensing.html?gi-language\u003dc#licensing-of-applications-using-gstreamer" + ] }, { - "reference": "./CLISP-exception-2.0.html", + "reference": "./OCaml-LGPL-linking-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CLISP-exception-2.0.json", - "referenceNumber": "20", - "name": "CLISP exception 2.0", + "detailsUrl": "./OCaml-LGPL-linking-exception.html", + "referenceNumber": 28, + "name": "OCaml LGPL Linking Exception", + "licenseExceptionId": "OCaml-LGPL-linking-exception", "seeAlso": [ - "http://sourceforge.net/p/clisp/clisp/ci/default/tree/COPYRIGHT" - ], - "licenseExceptionId": "CLISP-exception-2.0" + "https://caml.inria.fr/ocaml/license.en.html" + ] }, { - "reference": "./FLTK-exception.html", + "reference": "./Font-exception-2.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/FLTK-exception.json", - "referenceNumber": "21", - "name": "FLTK exception", + "detailsUrl": "./Font-exception-2.0.html", + "referenceNumber": 29, + "name": "Font exception 2.0", + "licenseExceptionId": "Font-exception-2.0", "seeAlso": [ - "http://www.fltk.org/COPYING.php" - ], - "licenseExceptionId": "FLTK-exception" + "http://www.gnu.org/licenses/gpl-faq.html#FontException" + ] }, { - "reference": "./Bootloader-exception.html", + "reference": "./Qwt-exception-1.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Bootloader-exception.json", - "referenceNumber": "22", - "name": "Bootloader Distribution Exception", + "detailsUrl": "./Qwt-exception-1.0.html", + "referenceNumber": 30, + "name": "Qwt exception 1.0", + "licenseExceptionId": "Qwt-exception-1.0", "seeAlso": [ - "https://github.com/pyinstaller/pyinstaller/blob/develop/COPYING.txt" - ], - "licenseExceptionId": "Bootloader-exception" + "http://qwt.sourceforge.net/qwtlicense.html" + ] }, { - "reference": "./Nokia-Qt-exception-1.1.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/Nokia-Qt-exception-1.1.json", - "referenceNumber": "23", - "name": "Nokia Qt LGPL exception 1.1", + "reference": "./eCos-exception-2.0.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./eCos-exception-2.0.html", + "referenceNumber": 31, + "name": "eCos exception 2.0", + "licenseExceptionId": "eCos-exception-2.0", "seeAlso": [ - "https://www.keepassx.org/dev/projects/keepassx/repository/revisions/b8dfb9cc4d5133e0f09cd7533d15a4f1c19a40f2/entry/LICENSE.NOKIA-LGPL-EXCEPTION" - ], - "licenseExceptionId": "Nokia-Qt-exception-1.1" + "http://ecos.sourceware.org/license-overview.html" + ] }, { - "reference": "./LLVM-exception.html", + "reference": "./GPL-3.0-linking-source-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LLVM-exception.json", - "referenceNumber": "24", - "name": "LLVM Exception", + "detailsUrl": "./GPL-3.0-linking-source-exception.html", + "referenceNumber": 32, + "name": "GPL-3.0 Linking Exception (with Corresponding Source)", + "licenseExceptionId": "GPL-3.0-linking-source-exception", "seeAlso": [ - "http://llvm.org/foundation/relicensing/LICENSE.txt" - ], - "licenseExceptionId": "LLVM-exception" + "https://www.gnu.org/licenses/gpl-faq.en.html#GPLIncompatibleLibs", + "https://github.com/mirror/wget/blob/master/src/http.c#L20" + ] }, { - "reference": "./WxWindows-exception-3.1.html", + "reference": "./GStreamer-exception-2005.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/WxWindows-exception-3.1.json", - "referenceNumber": "25", - "name": "WxWindows Library Exception 3.1", + "detailsUrl": "./GStreamer-exception-2005.html", + "referenceNumber": 33, + "name": "GStreamer Exception (2005)", + "licenseExceptionId": "GStreamer-exception-2005", "seeAlso": [ - "http://www.opensource.org/licenses/WXwindows" - ], - "licenseExceptionId": "WxWindows-exception-3.1" + "https://gstreamer.freedesktop.org/documentation/frequently-asked-questions/licensing.html?gi-language\u003dc#licensing-of-applications-using-gstreamer" + ] }, { - "reference": "./DigiRule-FOSS-exception.html", + "reference": "./DigiRule-FOSS-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/DigiRule-FOSS-exception.json", - "referenceNumber": "26", + "detailsUrl": "./DigiRule-FOSS-exception.html", + "referenceNumber": 34, "name": "DigiRule FOSS License Exception", + "licenseExceptionId": "DigiRule-FOSS-exception", "seeAlso": [ "http://www.digirulesolutions.com/drupal/foss" - ], - "licenseExceptionId": "DigiRule-FOSS-exception" + ] }, { - "reference": "./Swift-exception.html", + "reference": "./389-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Swift-exception.json", - "referenceNumber": "27", - "name": "Swift Exception", + "detailsUrl": "./389-exception.html", + "referenceNumber": 35, + "name": "389 Directory Server Exception", + "licenseExceptionId": "389-exception", "seeAlso": [ - "https://swift.org/LICENSE.txt", - "https://github.com/apple/swift-package-manager/blob/7ab2275f447a5eb37497ed63a9340f8a6d1e488b/LICENSE.txt#L205" - ], - "licenseExceptionId": "Swift-exception" + "http://directory.fedoraproject.org/wiki/GPL_Exception_License_Text", + "https://web.archive.org/web/20080828121337/http://directory.fedoraproject.org/wiki/GPL_Exception_License_Text" + ] }, { - "reference": "./GCC-exception-3.1.html", + "reference": "./Classpath-exception-2.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/GCC-exception-3.1.json", - "referenceNumber": "28", - "name": "GCC Runtime Library exception 3.1", + "detailsUrl": "./Classpath-exception-2.0.html", + "referenceNumber": 36, + "name": "Classpath exception 2.0", + "licenseExceptionId": "Classpath-exception-2.0", "seeAlso": [ - "http://www.gnu.org/licenses/gcc-exception-3.1.html" - ], - "licenseExceptionId": "GCC-exception-3.1" + "http://www.gnu.org/software/classpath/license.html", + "https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception" + ] }, { - "reference": "./eCos-exception-2.0.html", + "reference": "./Bison-exception-2.2.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/eCos-exception-2.0.json", - "referenceNumber": "29", - "name": "eCos exception 2.0", + "detailsUrl": "./Bison-exception-2.2.html", + "referenceNumber": 37, + "name": "Bison exception 2.2", + "licenseExceptionId": "Bison-exception-2.2", "seeAlso": [ - "http://ecos.sourceware.org/license-overview.html" - ], - "licenseExceptionId": "eCos-exception-2.0" + "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141" + ] }, { - "reference": "./Autoconf-exception-2.0.html", + "reference": "./Libtool-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Autoconf-exception-2.0.json", - "referenceNumber": "30", - "name": "Autoconf exception 2.0", + "detailsUrl": "./Libtool-exception.html", + "referenceNumber": 38, + "name": "Libtool Exception", + "licenseExceptionId": "Libtool-exception", "seeAlso": [ - "http://ac-archive.sourceforge.net/doc/copyright.html", - "http://ftp.gnu.org/gnu/autoconf/autoconf-2.59.tar.gz" - ], - "licenseExceptionId": "Autoconf-exception-2.0" + "http://git.savannah.gnu.org/cgit/libtool.git/tree/m4/libtool.m4" + ] + }, + { + "reference": "./Autoconf-exception-generic.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./Autoconf-exception-generic.html", + "referenceNumber": 39, + "name": "Autoconf generic exception", + "licenseExceptionId": "Autoconf-exception-generic", + "seeAlso": [ + "https://launchpad.net/ubuntu/precise/+source/xmltooling/+copyright", + "https://tracker.debian.org/media/packages/s/sipwitch/copyright-1.9.15-3", + "https://opensource.apple.com/source/launchd/launchd-258.1/launchd/compile.auto.html" + ] + }, + { + "reference": "./Universal-FOSS-exception-1.0.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./Universal-FOSS-exception-1.0.html", + "referenceNumber": 40, + "name": "Universal FOSS Exception, Version 1.0", + "licenseExceptionId": "Universal-FOSS-exception-1.0", + "seeAlso": [ + "https://oss.oracle.com/licenses/universal-foss-exception/" + ] }, { - "reference": "./GPL-CC-1.0.html", + "reference": "./GPL-CC-1.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/GPL-CC-1.0.json", - "referenceNumber": "31", + "detailsUrl": "./GPL-CC-1.0.html", + "referenceNumber": 41, "name": "GPL Cooperation Commitment 1.0", + "licenseExceptionId": "GPL-CC-1.0", "seeAlso": [ "https://github.com/gplcc/gplcc/blob/master/Project/COMMITMENT", "https://gplcc.github.io/gplcc/Project/README-PROJECT.html" - ], - "licenseExceptionId": "GPL-CC-1.0" + ] }, { - "reference": "./Font-exception-2.0.html", + "reference": "./FLTK-exception.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Font-exception-2.0.json", - "referenceNumber": "32", - "name": "Font exception 2.0", + "detailsUrl": "./FLTK-exception.html", + "referenceNumber": 42, + "name": "FLTK exception", + "licenseExceptionId": "FLTK-exception", "seeAlso": [ - "http://www.gnu.org/licenses/gpl-faq.html#FontException" - ], - "licenseExceptionId": "Font-exception-2.0" + "http://www.fltk.org/COPYING.php" + ] }, { - "reference": "./u-boot-exception-2.0.html", + "reference": "./OCCT-exception-1.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/u-boot-exception-2.0.json", - "referenceNumber": "33", - "name": "U-Boot exception 2.0", + "detailsUrl": "./OCCT-exception-1.0.html", + "referenceNumber": 43, + "name": "Open CASCADE Exception 1.0", + "licenseExceptionId": "OCCT-exception-1.0", "seeAlso": [ - "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003dLicenses/Exceptions" - ], - "licenseExceptionId": "u-boot-exception-2.0" + "http://www.opencascade.com/content/licensing" + ] }, { - "reference": "./GCC-exception-2.0.html", + "reference": "./OpenJDK-assembly-exception-1.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/GCC-exception-2.0.json", - "referenceNumber": "34", - "name": "GCC Runtime Library exception 2.0", + "detailsUrl": "./OpenJDK-assembly-exception-1.0.html", + "referenceNumber": 44, + "name": "OpenJDK Assembly exception 1.0", + "licenseExceptionId": "OpenJDK-assembly-exception-1.0", "seeAlso": [ - "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10" - ], - "licenseExceptionId": "GCC-exception-2.0" + "http://openjdk.java.net/legal/assembly-exception.html" + ] }, { - "reference": "./mif-exception.html", + "reference": "./Qt-LGPL-exception-1.1.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/mif-exception.json", - "referenceNumber": "35", - "name": "Macros and Inline Functions Exception", + "detailsUrl": "./Qt-LGPL-exception-1.1.html", + "referenceNumber": 45, + "name": "Qt LGPL exception 1.1", + "licenseExceptionId": "Qt-LGPL-exception-1.1", "seeAlso": [ - "http://www.scs.stanford.edu/histar/src/lib/cppsup/exception", - "http://dev.bertos.org/doxygen/", - "https://www.threadingbuildingblocks.org/licensing" - ], - "licenseExceptionId": "mif-exception" + "http://code.qt.io/cgit/qt/qtbase.git/tree/LGPL_EXCEPTION.txt" + ] }, { - "reference": "./OCaml-LGPL-linking-exception.html", + "reference": "./Qt-GPL-exception-1.0.json", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OCaml-LGPL-linking-exception.json", - "referenceNumber": "36", - "name": "OCaml LGPL Linking Exception", + "detailsUrl": "./Qt-GPL-exception-1.0.html", + "referenceNumber": 46, + "name": "Qt GPL exception 1.0", + "licenseExceptionId": "Qt-GPL-exception-1.0", "seeAlso": [ - "https://caml.inria.fr/ocaml/license.en.html" - ], - "licenseExceptionId": "OCaml-LGPL-linking-exception" + "http://code.qt.io/cgit/qt/qtbase.git/tree/LICENSE.GPL3-EXCEPT" + ] + }, + { + "reference": "./KiCad-libraries-exception.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./KiCad-libraries-exception.html", + "referenceNumber": 47, + "name": "KiCad Libraries Exception", + "licenseExceptionId": "KiCad-libraries-exception", + "seeAlso": [ + "https://www.kicad.org/libraries/license/" + ] + }, + { + "reference": "./x11vnc-openssl-exception.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./x11vnc-openssl-exception.html", + "referenceNumber": 48, + "name": "x11vnc OpenSSL Exception", + "licenseExceptionId": "x11vnc-openssl-exception", + "seeAlso": [ + "https://github.com/LibVNC/x11vnc/blob/master/src/8to24.c#L22" + ] + }, + { + "reference": "./mif-exception.json", + "isDeprecatedLicenseId": false, + "detailsUrl": "./mif-exception.html", + "referenceNumber": 49, + "name": "Macros and Inline Functions Exception", + "licenseExceptionId": "mif-exception", + "seeAlso": [ + "http://www.scs.stanford.edu/histar/src/lib/cppsup/exception", + "http://dev.bertos.org/doxygen/", + "https://www.threadingbuildingblocks.org/licensing" + ] } - ] + ], + "releaseDate": "2023-02-17" } \ No newline at end of file diff --git a/spdx/licenses.json b/spdx/licenses.json index 10550cbd4..b398c963c 100644 --- a/spdx/licenses.json +++ b/spdx/licenses.json @@ -1,3425 +1,5150 @@ { - "licenseListVersion": "3.6", + "licenseListVersion": "3.20", "licenses": [ { - "reference": "./0BSD.html", + "reference": "https://spdx.org/licenses/SCEA.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/0BSD.json", - "referenceNumber": "319", - "name": "BSD Zero Clause License", - "licenseId": "0BSD", + "detailsUrl": "https://spdx.org/licenses/SCEA.json", + "referenceNumber": 0, + "name": "SCEA Shared Source License", + "licenseId": "SCEA", "seeAlso": [ - "http://landley.net/toybox/license.html" + "http://research.scea.com/scea_shared_source_license.html" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./AAL.html", + "reference": "https://spdx.org/licenses/RSA-MD.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/AAL.json", - "referenceNumber": "21", - "name": "Attribution Assurance License", - "licenseId": "AAL", + "detailsUrl": "https://spdx.org/licenses/RSA-MD.json", + "referenceNumber": 1, + "name": "RSA Message-Digest License", + "licenseId": "RSA-MD", "seeAlso": [ - "https://opensource.org/licenses/attribution" + "http://www.faqs.org/rfcs/rfc1321.html" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./ADSL.html", + "reference": "https://spdx.org/licenses/Leptonica.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ADSL.json", - "referenceNumber": "19", - "name": "Amazon Digital Services License", - "licenseId": "ADSL", + "detailsUrl": "https://spdx.org/licenses/Leptonica.json", + "referenceNumber": 2, + "name": "Leptonica License", + "licenseId": "Leptonica", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/AmazonDigitalServicesLicense" + "https://fedoraproject.org/wiki/Licensing/Leptonica" ], "isOsiApproved": false }, { - "reference": "./AFL-1.1.html", + "reference": "https://spdx.org/licenses/Ruby.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AFL-1.1.json", - "referenceNumber": "118", - "name": "Academic Free License v1.1", - "licenseId": "AFL-1.1", + "detailsUrl": "https://spdx.org/licenses/Ruby.json", + "referenceNumber": 3, + "name": "Ruby License", + "licenseId": "Ruby", "seeAlso": [ - "http://opensource.linux-mirror.org/licenses/afl-1.1.txt", - "http://wayback.archive.org/web/20021004124254/http://www.opensource.org/licenses/academic.php" + "http://www.ruby-lang.org/en/LICENSE.txt" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./AFL-1.2.html", + "reference": "https://spdx.org/licenses/Zlib.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AFL-1.2.json", - "referenceNumber": "136", - "name": "Academic Free License v1.2", - "licenseId": "AFL-1.2", + "detailsUrl": "https://spdx.org/licenses/Zlib.json", + "referenceNumber": 4, + "name": "zlib License", + "licenseId": "Zlib", "seeAlso": [ - "http://opensource.linux-mirror.org/licenses/afl-1.2.txt", - "http://wayback.archive.org/web/20021204204652/http://www.opensource.org/licenses/academic.php" + "http://www.zlib.net/zlib_license.html", + "https://opensource.org/licenses/Zlib" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./AFL-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AFL-2.0.json", - "referenceNumber": "115", - "name": "Academic Free License v2.0", - "licenseId": "AFL-2.0", + "reference": "https://spdx.org/licenses/GFDL-1.2.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2.json", + "referenceNumber": 5, + "name": "GNU Free Documentation License v1.2", + "licenseId": "GFDL-1.2", "seeAlso": [ - "http://wayback.archive.org/web/20060924134533/http://www.opensource.org/licenses/afl-2.0.txt" + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./AFL-2.1.html", + "reference": "https://spdx.org/licenses/Unicode-DFS-2016.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AFL-2.1.json", - "referenceNumber": "251", - "name": "Academic Free License v2.1", - "licenseId": "AFL-2.1", + "detailsUrl": "https://spdx.org/licenses/Unicode-DFS-2016.json", + "referenceNumber": 6, + "name": "Unicode License Agreement - Data Files and Software (2016)", + "licenseId": "Unicode-DFS-2016", "seeAlso": [ - "http://opensource.linux-mirror.org/licenses/afl-2.1.txt" + "http://www.unicode.org/copyright.html" ], "isOsiApproved": true }, { - "reference": "./AFL-3.0.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-2.5.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AFL-3.0.json", - "referenceNumber": "216", - "name": "Academic Free License v3.0", - "licenseId": "AFL-3.0", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-2.5.json", + "referenceNumber": 7, + "name": "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic", + "licenseId": "CC-BY-NC-ND-2.5", "seeAlso": [ - "http://www.rosenlaw.com/AFL3.0.htm", - "https://opensource.org/licenses/afl-3.0" + "https://creativecommons.org/licenses/by-nc-nd/2.5/legalcode" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./AGPL-1.0.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AGPL-1.0.json", - "referenceNumber": "335", - "name": "Affero General Public License v1.0", - "licenseId": "AGPL-1.0", + "reference": "https://spdx.org/licenses/FSFULLRWD.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FSFULLRWD.json", + "referenceNumber": 8, + "name": "FSF Unlimited License (With License Retention and Warranty Disclaimer)", + "licenseId": "FSFULLRWD", "seeAlso": [ - "http://www.affero.org/oagpl.html" + "https://lists.gnu.org/archive/html/autoconf/2012-04/msg00061.html" ], "isOsiApproved": false }, { - "reference": "./AGPL-1.0-only.html", + "reference": "https://spdx.org/licenses/QPL-1.0-INRIA-2004.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/AGPL-1.0-only.json", - "referenceNumber": "384", - "name": "Affero General Public License v1.0 only", - "licenseId": "AGPL-1.0-only", + "detailsUrl": "https://spdx.org/licenses/QPL-1.0-INRIA-2004.json", + "referenceNumber": 9, + "name": "Q Public License 1.0 - INRIA 2004 variant", + "licenseId": "QPL-1.0-INRIA-2004", "seeAlso": [ - "http://www.affero.org/oagpl.html" + "https://github.com/maranget/hevea/blob/master/LICENSE" ], "isOsiApproved": false }, { - "reference": "./AGPL-1.0-or-later.html", + "reference": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/AGPL-1.0-or-later.json", - "referenceNumber": "332", - "name": "Affero General Public License v1.0 or later", - "licenseId": "AGPL-1.0-or-later", + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.json", + "referenceNumber": 10, + "name": "BSD 3-Clause No Nuclear Warranty", + "licenseId": "BSD-3-Clause-No-Nuclear-Warranty", "seeAlso": [ - "http://www.affero.org/oagpl.html" + "https://jogamp.org/git/?p\u003dgluegen.git;a\u003dblob_plain;f\u003dLICENSE.txt" ], "isOsiApproved": false }, { - "reference": "./AGPL-3.0.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AGPL-3.0.json", - "referenceNumber": "229", - "name": "GNU Affero General Public License v3.0", - "licenseId": "AGPL-3.0", + "reference": "https://spdx.org/licenses/OSL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OSL-2.0.json", + "referenceNumber": 11, + "name": "Open Software License 2.0", + "licenseId": "OSL-2.0", "seeAlso": [ - "https://www.gnu.org/licenses/agpl.txt", - "https://opensource.org/licenses/AGPL-3.0" + "http://web.archive.org/web/20041020171434/http://www.rosenlaw.com/osl2.0.html" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./AGPL-3.0-only.html", + "reference": "https://spdx.org/licenses/mpi-permissive.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AGPL-3.0-only.json", - "referenceNumber": "95", - "name": "GNU Affero General Public License v3.0 only", - "licenseId": "AGPL-3.0-only", + "detailsUrl": "https://spdx.org/licenses/mpi-permissive.json", + "referenceNumber": 12, + "name": "mpi Permissive License", + "licenseId": "mpi-permissive", "seeAlso": [ - "https://www.gnu.org/licenses/agpl.txt", - "https://opensource.org/licenses/AGPL-3.0" + "https://sources.debian.org/src/openmpi/4.1.0-10/ompi/debuggers/msgq_interface.h/?hl\u003d19#L19" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./AGPL-3.0-or-later.html", + "reference": "https://spdx.org/licenses/CUA-OPL-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/AGPL-3.0-or-later.json", - "referenceNumber": "155", - "name": "GNU Affero General Public License v3.0 or later", - "licenseId": "AGPL-3.0-or-later", + "detailsUrl": "https://spdx.org/licenses/CUA-OPL-1.0.json", + "referenceNumber": 13, + "name": "CUA Office Public License v1.0", + "licenseId": "CUA-OPL-1.0", "seeAlso": [ - "https://www.gnu.org/licenses/agpl.txt", - "https://opensource.org/licenses/AGPL-3.0" + "https://opensource.org/licenses/CUA-OPL-1.0" ], "isOsiApproved": true }, { - "reference": "./AMDPLPA.html", + "reference": "https://spdx.org/licenses/CC-BY-3.0-AT.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/AMDPLPA.json", - "referenceNumber": "33", - "name": "AMD\u0027s plpa_map.c License", - "licenseId": "AMDPLPA", + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-AT.json", + "referenceNumber": 14, + "name": "Creative Commons Attribution 3.0 Austria", + "licenseId": "CC-BY-3.0-AT", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/AMD_plpa_map_License" + "https://creativecommons.org/licenses/by/3.0/at/legalcode" ], "isOsiApproved": false }, { - "reference": "./AML.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/AML.json", - "referenceNumber": "148", - "name": "Apple MIT License", - "licenseId": "AML", + "reference": "https://spdx.org/licenses/GFDL-1.3.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3.json", + "referenceNumber": 15, + "name": "GNU Free Documentation License v1.3", + "licenseId": "GFDL-1.3", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Apple_MIT_License" + "https://www.gnu.org/licenses/fdl-1.3.txt" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./AMPAS.html", + "reference": "https://spdx.org/licenses/GFDL-1.3-only.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/AMPAS.json", - "referenceNumber": "191", - "name": "Academy of Motion Picture Arts and Sciences BSD", - "licenseId": "AMPAS", + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-only.json", + "referenceNumber": 16, + "name": "GNU Free Documentation License v1.3 only", + "licenseId": "GFDL-1.3-only", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/BSD#AMPASBSD" + "https://www.gnu.org/licenses/fdl-1.3.txt" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./ANTLR-PD.html", + "reference": "https://spdx.org/licenses/OLDAP-2.2.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ANTLR-PD.json", - "referenceNumber": "395", - "name": "ANTLR Software Rights Notice", - "licenseId": "ANTLR-PD", + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.2.json", + "referenceNumber": 17, + "name": "Open LDAP Public License v2.2", + "licenseId": "OLDAP-2.2", "seeAlso": [ - "http://www.antlr2.org/license.html" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d470b0c18ec67621c85881b2733057fecf4a1acc3" ], "isOsiApproved": false }, { - "reference": "./APAFML.html", + "reference": "https://spdx.org/licenses/NCSA.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/APAFML.json", - "referenceNumber": "195", - "name": "Adobe Postscript AFM License", - "licenseId": "APAFML", + "detailsUrl": "https://spdx.org/licenses/NCSA.json", + "referenceNumber": 18, + "name": "University of Illinois/NCSA Open Source License", + "licenseId": "NCSA", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/AdobePostscriptAFM" + "http://otm.illinois.edu/uiuc_openSource", + "https://opensource.org/licenses/NCSA" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./APL-1.0.html", + "reference": "https://spdx.org/licenses/LPPL-1.3c.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/APL-1.0.json", - "referenceNumber": "252", - "name": "Adaptive Public License 1.0", - "licenseId": "APL-1.0", + "detailsUrl": "https://spdx.org/licenses/LPPL-1.3c.json", + "referenceNumber": 19, + "name": "LaTeX Project Public License v1.3c", + "licenseId": "LPPL-1.3c", "seeAlso": [ - "https://opensource.org/licenses/APL-1.0" + "http://www.latex-project.org/lppl/lppl-1-3c.txt", + "https://opensource.org/licenses/LPPL-1.3c" ], "isOsiApproved": true }, { - "reference": "./APSL-1.0.html", + "reference": "https://spdx.org/licenses/OpenPBS-2.3.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/APSL-1.0.json", - "referenceNumber": "354", - "name": "Apple Public Source License 1.0", - "licenseId": "APSL-1.0", + "detailsUrl": "https://spdx.org/licenses/OpenPBS-2.3.json", + "referenceNumber": 20, + "name": "OpenPBS v2.3 Software License", + "licenseId": "OpenPBS-2.3", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Apple_Public_Source_License_1.0" + "https://github.com/adaptivecomputing/torque/blob/master/PBS_License.txt", + "https://www.mcs.anl.gov/research/projects/openpbs/PBS_License.txt" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./APSL-1.1.html", + "reference": "https://spdx.org/licenses/LiLiQ-R-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/APSL-1.1.json", - "referenceNumber": "324", - "name": "Apple Public Source License 1.1", - "licenseId": "APSL-1.1", + "detailsUrl": "https://spdx.org/licenses/LiLiQ-R-1.1.json", + "referenceNumber": 21, + "name": "Licence Libre du Québec – Réciprocité version 1.1", + "licenseId": "LiLiQ-R-1.1", "seeAlso": [ - "http://www.opensource.apple.com/source/IOSerialFamily/IOSerialFamily-7/APPLE_LICENSE" + "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-liliq-r-v1-1/", + "http://opensource.org/licenses/LiLiQ-R-1.1" ], "isOsiApproved": true }, { - "reference": "./APSL-1.2.html", + "reference": "https://spdx.org/licenses/W3C-20150513.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/APSL-1.2.json", - "referenceNumber": "34", - "name": "Apple Public Source License 1.2", - "licenseId": "APSL-1.2", + "detailsUrl": "https://spdx.org/licenses/W3C-20150513.json", + "referenceNumber": 22, + "name": "W3C Software Notice and Document License (2015-05-13)", + "licenseId": "W3C-20150513", "seeAlso": [ - "http://www.samurajdata.se/opensource/mirror/licenses/apsl.php" + "https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./APSL-2.0.html", + "reference": "https://spdx.org/licenses/OGDL-Taiwan-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/APSL-2.0.json", - "referenceNumber": "109", - "name": "Apple Public Source License 2.0", - "licenseId": "APSL-2.0", + "detailsUrl": "https://spdx.org/licenses/OGDL-Taiwan-1.0.json", + "referenceNumber": 23, + "name": "Taiwan Open Government Data License, version 1.0", + "licenseId": "OGDL-Taiwan-1.0", "seeAlso": [ - "http://www.opensource.apple.com/license/apsl/" + "https://data.gov.tw/license" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./Abstyles.html", + "reference": "https://spdx.org/licenses/O-UDA-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Abstyles.json", - "referenceNumber": "80", - "name": "Abstyles License", - "licenseId": "Abstyles", + "detailsUrl": "https://spdx.org/licenses/O-UDA-1.0.json", + "referenceNumber": 24, + "name": "Open Use of Data Agreement v1.0", + "licenseId": "O-UDA-1.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Abstyles" + "https://github.com/microsoft/Open-Use-of-Data-Agreement/blob/v1.0/O-UDA-1.0.md", + "https://cdla.dev/open-use-of-data-agreement-v1-0/" ], "isOsiApproved": false }, { - "reference": "./Adobe-2006.html", + "reference": "https://spdx.org/licenses/CDLA-Permissive-2.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Adobe-2006.json", - "referenceNumber": "285", - "name": "Adobe Systems Incorporated Source Code License Agreement", - "licenseId": "Adobe-2006", + "detailsUrl": "https://spdx.org/licenses/CDLA-Permissive-2.0.json", + "referenceNumber": 25, + "name": "Community Data License Agreement Permissive 2.0", + "licenseId": "CDLA-Permissive-2.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/AdobeLicense" + "https://cdla.dev/permissive-2-0" ], "isOsiApproved": false }, { - "reference": "./Adobe-Glyph.html", + "reference": "https://spdx.org/licenses/Graphics-Gems.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Adobe-Glyph.json", - "referenceNumber": "107", - "name": "Adobe Glyph List License", - "licenseId": "Adobe-Glyph", + "detailsUrl": "https://spdx.org/licenses/Graphics-Gems.json", + "referenceNumber": 26, + "name": "Graphics Gems License", + "licenseId": "Graphics-Gems", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT#AdobeGlyph" + "https://github.com/erich666/GraphicsGems/blob/master/LICENSE.md" ], "isOsiApproved": false }, { - "reference": "./Afmparse.html", + "reference": "https://spdx.org/licenses/PHP-3.01.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Afmparse.json", - "referenceNumber": "42", - "name": "Afmparse License", - "licenseId": "Afmparse", + "detailsUrl": "https://spdx.org/licenses/PHP-3.01.json", + "referenceNumber": 27, + "name": "PHP License v3.01", + "licenseId": "PHP-3.01", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Afmparse" + "http://www.php.net/license/3_01.txt" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CC-BY-3.0-DE.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-DE.json", + "referenceNumber": 28, + "name": "Creative Commons Attribution 3.0 Germany", + "licenseId": "CC-BY-3.0-DE", + "seeAlso": [ + "https://creativecommons.org/licenses/by/3.0/de/legalcode" ], "isOsiApproved": false }, { - "reference": "./Aladdin.html", + "reference": "https://spdx.org/licenses/Cube.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Aladdin.json", - "referenceNumber": "258", - "name": "Aladdin Free Public License", - "licenseId": "Aladdin", + "detailsUrl": "https://spdx.org/licenses/Cube.json", + "referenceNumber": 29, + "name": "Cube License", + "licenseId": "Cube", "seeAlso": [ - "http://pages.cs.wisc.edu/~ghost/doc/AFPL/6.01/Public.htm" + "https://fedoraproject.org/wiki/Licensing/Cube" ], "isOsiApproved": false }, { - "reference": "./Apache-1.0.html", + "reference": "https://spdx.org/licenses/MTLL.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Apache-1.0.json", - "referenceNumber": "237", - "name": "Apache License 1.0", - "licenseId": "Apache-1.0", + "detailsUrl": "https://spdx.org/licenses/MTLL.json", + "referenceNumber": 30, + "name": "Matrix Template Library License", + "licenseId": "MTLL", "seeAlso": [ - "http://www.apache.org/licenses/LICENSE-1.0" + "https://fedoraproject.org/wiki/Licensing/Matrix_Template_Library_License" ], "isOsiApproved": false }, { - "reference": "./Apache-1.1.html", + "reference": "https://spdx.org/licenses/MIT-0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Apache-1.1.json", - "referenceNumber": "84", - "name": "Apache License 1.1", - "licenseId": "Apache-1.1", + "detailsUrl": "https://spdx.org/licenses/MIT-0.json", + "referenceNumber": 31, + "name": "MIT No Attribution", + "licenseId": "MIT-0", "seeAlso": [ - "http://apache.org/licenses/LICENSE-1.1", - "https://opensource.org/licenses/Apache-1.1" + "https://github.com/aws/mit-0", + "https://romanrm.net/mit-zero", + "https://github.com/awsdocs/aws-cloud9-user-guide/blob/master/LICENSE-SAMPLECODE" ], "isOsiApproved": true }, { - "reference": "./Apache-2.0.html", + "reference": "https://spdx.org/licenses/WTFPL.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Apache-2.0.json", - "referenceNumber": "26", - "name": "Apache License 2.0", - "licenseId": "Apache-2.0", + "detailsUrl": "https://spdx.org/licenses/WTFPL.json", + "referenceNumber": 32, + "name": "Do What The F*ck You Want To Public License", + "licenseId": "WTFPL", "seeAlso": [ - "http://www.apache.org/licenses/LICENSE-2.0", - "https://opensource.org/licenses/Apache-2.0" + "http://www.wtfpl.net/about/", + "http://sam.zoy.org/wtfpl/COPYING" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./Artistic-1.0.html", + "reference": "https://spdx.org/licenses/EUDatagrid.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Artistic-1.0.json", - "referenceNumber": "165", - "name": "Artistic License 1.0", - "licenseId": "Artistic-1.0", + "detailsUrl": "https://spdx.org/licenses/EUDatagrid.json", + "referenceNumber": 33, + "name": "EU DataGrid Software License", + "licenseId": "EUDatagrid", "seeAlso": [ - "https://opensource.org/licenses/Artistic-1.0" + "http://eu-datagrid.web.cern.ch/eu-datagrid/license.html", + "https://opensource.org/licenses/EUDatagrid" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./Artistic-1.0-Perl.html", + "reference": "https://spdx.org/licenses/RSCPL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Artistic-1.0-Perl.json", - "referenceNumber": "377", - "name": "Artistic License 1.0 (Perl)", - "licenseId": "Artistic-1.0-Perl", + "detailsUrl": "https://spdx.org/licenses/RSCPL.json", + "referenceNumber": 34, + "name": "Ricoh Source Code Public License", + "licenseId": "RSCPL", "seeAlso": [ - "http://dev.perl.org/licenses/artistic.html" + "http://wayback.archive.org/web/20060715140826/http://www.risource.org/RPL/RPL-1.0A.shtml", + "https://opensource.org/licenses/RSCPL" ], "isOsiApproved": true }, { - "reference": "./Artistic-1.0-cl8.html", + "reference": "https://spdx.org/licenses/Vim.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Artistic-1.0-cl8.json", - "referenceNumber": "13", - "name": "Artistic License 1.0 w/clause 8", - "licenseId": "Artistic-1.0-cl8", + "detailsUrl": "https://spdx.org/licenses/Vim.json", + "referenceNumber": 35, + "name": "Vim License", + "licenseId": "Vim", "seeAlso": [ - "https://opensource.org/licenses/Artistic-1.0" + "http://vimdoc.sourceforge.net/htmldoc/uganda.html" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./Artistic-2.0.html", + "reference": "https://spdx.org/licenses/gnuplot.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Artistic-2.0.json", - "referenceNumber": "189", - "name": "Artistic License 2.0", - "licenseId": "Artistic-2.0", + "detailsUrl": "https://spdx.org/licenses/gnuplot.json", + "referenceNumber": 36, + "name": "gnuplot License", + "licenseId": "gnuplot", "seeAlso": [ - "http://www.perlfoundation.org/artistic_license_2_0", - "https://opensource.org/licenses/artistic-license-2.0" + "https://fedoraproject.org/wiki/Licensing/Gnuplot" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./BSD-1-Clause.html", + "reference": "https://spdx.org/licenses/diffmark.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-1-Clause.json", - "referenceNumber": "358", - "name": "BSD 1-Clause License", - "licenseId": "BSD-1-Clause", + "detailsUrl": "https://spdx.org/licenses/diffmark.json", + "referenceNumber": 37, + "name": "diffmark license", + "licenseId": "diffmark", "seeAlso": [ - "https://svnweb.freebsd.org/base/head/include/ifaddrs.h?revision\u003d326823" + "https://fedoraproject.org/wiki/Licensing/diffmark" ], "isOsiApproved": false }, { - "reference": "./BSD-2-Clause.html", + "reference": "https://spdx.org/licenses/OFL-1.1-no-RFN.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause.json", - "referenceNumber": "325", - "name": "BSD 2-Clause \"Simplified\" License", - "licenseId": "BSD-2-Clause", + "detailsUrl": "https://spdx.org/licenses/OFL-1.1-no-RFN.json", + "referenceNumber": 38, + "name": "SIL Open Font License 1.1 with no Reserved Font Name", + "licenseId": "OFL-1.1-no-RFN", "seeAlso": [ - "https://opensource.org/licenses/BSD-2-Clause" + "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web", + "https://opensource.org/licenses/OFL-1.1" ], "isOsiApproved": true }, { - "reference": "./BSD-2-Clause-FreeBSD.html", + "reference": "https://spdx.org/licenses/CDDL-1.1.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-FreeBSD.json", - "referenceNumber": "121", - "name": "BSD 2-Clause FreeBSD License", - "licenseId": "BSD-2-Clause-FreeBSD", + "detailsUrl": "https://spdx.org/licenses/CDDL-1.1.json", + "referenceNumber": 39, + "name": "Common Development and Distribution License 1.1", + "licenseId": "CDDL-1.1", "seeAlso": [ - "http://www.freebsd.org/copyright/freebsd-license.html" + "http://glassfish.java.net/public/CDDL+GPL_1_1.html", + "https://javaee.github.io/glassfish/LICENSE" ], "isOsiApproved": false }, { - "reference": "./BSD-2-Clause-NetBSD.html", + "reference": "https://spdx.org/licenses/SugarCRM-1.1.3.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-NetBSD.json", - "referenceNumber": "381", - "name": "BSD 2-Clause NetBSD License", - "licenseId": "BSD-2-Clause-NetBSD", + "detailsUrl": "https://spdx.org/licenses/SugarCRM-1.1.3.json", + "referenceNumber": 40, + "name": "SugarCRM Public License v1.1.3", + "licenseId": "SugarCRM-1.1.3", "seeAlso": [ - "http://www.netbsd.org/about/redistribution.html#default" + "http://www.sugarcrm.com/crm/SPL" ], "isOsiApproved": false }, { - "reference": "./BSD-2-Clause-Patent.html", + "reference": "https://spdx.org/licenses/BSD-4.3TAHOE.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-2-Clause-Patent.json", - "referenceNumber": "169", - "name": "BSD-2-Clause Plus Patent License", - "licenseId": "BSD-2-Clause-Patent", + "detailsUrl": "https://spdx.org/licenses/BSD-4.3TAHOE.json", + "referenceNumber": 41, + "name": "BSD 4.3 TAHOE License", + "licenseId": "BSD-4.3TAHOE", "seeAlso": [ - "https://opensource.org/licenses/BSDplusPatent" + "https://github.com/389ds/389-ds-base/blob/main/ldap/include/sysexits-compat.h#L15" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./BSD-3-Clause.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause.json", - "referenceNumber": "270", - "name": "BSD 3-Clause \"New\" or \"Revised\" License", - "licenseId": "BSD-3-Clause", + "reference": "https://spdx.org/licenses/GPL-2.0-with-bison-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-bison-exception.json", + "referenceNumber": 42, + "name": "GNU General Public License v2.0 w/Bison exception", + "licenseId": "GPL-2.0-with-bison-exception", "seeAlso": [ - "https://opensource.org/licenses/BSD-3-Clause" + "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./BSD-3-Clause-Attribution.html", + "reference": "https://spdx.org/licenses/OFFIS.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Attribution.json", - "referenceNumber": "39", - "name": "BSD with attribution", - "licenseId": "BSD-3-Clause-Attribution", + "detailsUrl": "https://spdx.org/licenses/OFFIS.json", + "referenceNumber": 43, + "name": "OFFIS License", + "licenseId": "OFFIS", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/BSD_with_Attribution" + "https://sourceforge.net/p/xmedcon/code/ci/master/tree/libs/dicom/README" ], "isOsiApproved": false }, { - "reference": "./BSD-3-Clause-Clear.html", + "reference": "https://spdx.org/licenses/OFL-1.1-RFN.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Clear.json", - "referenceNumber": "212", - "name": "BSD 3-Clause Clear License", - "licenseId": "BSD-3-Clause-Clear", + "detailsUrl": "https://spdx.org/licenses/OFL-1.1-RFN.json", + "referenceNumber": 44, + "name": "SIL Open Font License 1.1 with Reserved Font Name", + "licenseId": "OFL-1.1-RFN", "seeAlso": [ - "http://labs.metacarta.com/license-explanation.html#license" + "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web", + "https://opensource.org/licenses/OFL-1.1" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./BSD-3-Clause-LBNL.html", + "reference": "https://spdx.org/licenses/Nokia.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-LBNL.json", - "referenceNumber": "337", - "name": "Lawrence Berkeley National Labs BSD variant license", - "licenseId": "BSD-3-Clause-LBNL", + "detailsUrl": "https://spdx.org/licenses/Nokia.json", + "referenceNumber": 45, + "name": "Nokia Open Source License", + "licenseId": "Nokia", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/LBNLBSD" + "https://opensource.org/licenses/nokia" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./BSD-3-Clause-No-Nuclear-License.html", + "reference": "https://spdx.org/licenses/DSDP.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.json", - "referenceNumber": "12", - "name": "BSD 3-Clause No Nuclear License", - "licenseId": "BSD-3-Clause-No-Nuclear-License", + "detailsUrl": "https://spdx.org/licenses/DSDP.json", + "referenceNumber": 46, + "name": "DSDP License", + "licenseId": "DSDP", "seeAlso": [ - "http://download.oracle.com/otn-pub/java/licenses/bsd.txt?AuthParam\u003d1467140197_43d516ce1776bd08a58235a7785be1cc" + "https://fedoraproject.org/wiki/Licensing/DSDP" ], "isOsiApproved": false }, { - "reference": "./BSD-3-Clause-No-Nuclear-License-2014.html", + "reference": "https://spdx.org/licenses/AFL-3.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.json", - "referenceNumber": "137", - "name": "BSD 3-Clause No Nuclear License 2014", - "licenseId": "BSD-3-Clause-No-Nuclear-License-2014", + "detailsUrl": "https://spdx.org/licenses/AFL-3.0.json", + "referenceNumber": 47, + "name": "Academic Free License v3.0", + "licenseId": "AFL-3.0", "seeAlso": [ - "https://java.net/projects/javaeetutorial/pages/BerkeleyLicense" + "http://www.rosenlaw.com/AFL3.0.htm", + "https://opensource.org/licenses/afl-3.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./BSD-3-Clause-No-Nuclear-Warranty.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-No-Nuclear-Warranty.json", - "referenceNumber": "44", - "name": "BSD 3-Clause No Nuclear Warranty", - "licenseId": "BSD-3-Clause-No-Nuclear-Warranty", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-1.0.json", + "referenceNumber": 48, + "name": "Creative Commons Attribution Non Commercial 1.0 Generic", + "licenseId": "CC-BY-NC-1.0", "seeAlso": [ - "https://jogamp.org/git/?p\u003dgluegen.git;a\u003dblob_plain;f\u003dLICENSE.txt" + "https://creativecommons.org/licenses/by-nc/1.0/legalcode" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": false }, { - "reference": "./BSD-3-Clause-Open-MPI.html", + "reference": "https://spdx.org/licenses/CECILL-C.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-3-Clause-Open-MPI.json", - "referenceNumber": "349", - "name": "BSD 3-Clause Open MPI variant", - "licenseId": "BSD-3-Clause-Open-MPI", + "detailsUrl": "https://spdx.org/licenses/CECILL-C.json", + "referenceNumber": 49, + "name": "CeCILL-C Free Software License Agreement", + "licenseId": "CECILL-C", "seeAlso": [ - "https://www.open-mpi.org/community/license.php", - "http://www.netlib.org/lapack/LICENSE.txt" + "http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./BSD-4-Clause.html", + "reference": "https://spdx.org/licenses/OpenSSL.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/BSD-4-Clause.json", - "referenceNumber": "162", - "name": "BSD 4-Clause \"Original\" or \"Old\" License", - "licenseId": "BSD-4-Clause", + "detailsUrl": "https://spdx.org/licenses/OpenSSL.json", + "referenceNumber": 50, + "name": "OpenSSL License", + "licenseId": "OpenSSL", "seeAlso": [ - "http://directory.fsf.org/wiki/License:BSD_4Clause" + "http://www.openssl.org/source/license.html" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./BSD-4-Clause-UC.html", + "reference": "https://spdx.org/licenses/OLDAP-2.7.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-4-Clause-UC.json", - "referenceNumber": "203", - "name": "BSD-4-Clause (University of California-Specific)", - "licenseId": "BSD-4-Clause-UC", + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.7.json", + "referenceNumber": 51, + "name": "Open LDAP Public License v2.7", + "licenseId": "OLDAP-2.7", "seeAlso": [ - "http://www.freebsd.org/copyright/license.html" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d47c2415c1df81556eeb39be6cad458ef87c534a2" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./BSD-Protection.html", + "reference": "https://spdx.org/licenses/NGPL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-Protection.json", - "referenceNumber": "119", - "name": "BSD Protection License", - "licenseId": "BSD-Protection", + "detailsUrl": "https://spdx.org/licenses/NGPL.json", + "referenceNumber": 52, + "name": "Nethack General Public License", + "licenseId": "NGPL", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/BSD_Protection_License" + "https://opensource.org/licenses/NGPL" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./BSD-Source-Code.html", + "reference": "https://spdx.org/licenses/Linux-man-pages-copyleft.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BSD-Source-Code.json", - "referenceNumber": "308", - "name": "BSD Source Code Attribution", - "licenseId": "BSD-Source-Code", + "detailsUrl": "https://spdx.org/licenses/Linux-man-pages-copyleft.json", + "referenceNumber": 53, + "name": "Linux man-pages Copyleft", + "licenseId": "Linux-man-pages-copyleft", "seeAlso": [ - "https://github.com/robbiehanson/CocoaHTTPServer/blob/master/LICENSE.txt" + "https://www.kernel.org/doc/man-pages/licenses.html" ], "isOsiApproved": false }, { - "reference": "./BSL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/BSL-1.0.json", - "referenceNumber": "224", - "name": "Boost Software License 1.0", - "licenseId": "BSL-1.0", + "reference": "https://spdx.org/licenses/AGPL-3.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/AGPL-3.0.json", + "referenceNumber": 54, + "name": "GNU Affero General Public License v3.0", + "licenseId": "AGPL-3.0", "seeAlso": [ - "http://www.boost.org/LICENSE_1_0.txt", - "https://opensource.org/licenses/BSL-1.0" + "https://www.gnu.org/licenses/agpl.txt", + "https://opensource.org/licenses/AGPL-3.0" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./Bahyph.html", + "reference": "https://spdx.org/licenses/OLDAP-2.5.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Bahyph.json", - "referenceNumber": "366", - "name": "Bahyph License", - "licenseId": "Bahyph", + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.5.json", + "referenceNumber": 55, + "name": "Open LDAP Public License v2.5", + "licenseId": "OLDAP-2.5", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Bahyph" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d6852b9d90022e8593c98205413380536b1b5a7cf" ], "isOsiApproved": false }, { - "reference": "./Barr.html", + "reference": "https://spdx.org/licenses/CAL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Barr.json", - "referenceNumber": "333", - "name": "Barr License", - "licenseId": "Barr", + "detailsUrl": "https://spdx.org/licenses/CAL-1.0.json", + "referenceNumber": 56, + "name": "Cryptographic Autonomy License 1.0", + "licenseId": "CAL-1.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Barr" + "http://cryptographicautonomylicense.com/license-text.html", + "https://opensource.org/licenses/CAL-1.0" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./Beerware.html", + "reference": "https://spdx.org/licenses/CC-BY-SA-2.0-UK.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Beerware.json", - "referenceNumber": "17", - "name": "Beerware License", - "licenseId": "Beerware", + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-2.0-UK.json", + "referenceNumber": 57, + "name": "Creative Commons Attribution Share Alike 2.0 England and Wales", + "licenseId": "CC-BY-SA-2.0-UK", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Beerware", - "https://people.freebsd.org/~phk/" + "https://creativecommons.org/licenses/by-sa/2.0/uk/legalcode" ], "isOsiApproved": false }, { - "reference": "./BitTorrent-1.0.html", + "reference": "https://spdx.org/licenses/TCP-wrappers.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BitTorrent-1.0.json", - "referenceNumber": "218", - "name": "BitTorrent Open Source License v1.0", - "licenseId": "BitTorrent-1.0", + "detailsUrl": "https://spdx.org/licenses/TCP-wrappers.json", + "referenceNumber": 58, + "name": "TCP Wrappers License", + "licenseId": "TCP-wrappers", "seeAlso": [ - "http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/licenses/BitTorrent?r1\u003d1.1\u0026r2\u003d1.1.1.1\u0026diff_format\u003ds" + "http://rc.quest.com/topics/openssh/license.php#tcpwrappers" ], "isOsiApproved": false }, { - "reference": "./BitTorrent-1.1.html", + "reference": "https://spdx.org/licenses/Dotseqn.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/BitTorrent-1.1.json", - "referenceNumber": "179", - "name": "BitTorrent Open Source License v1.1", - "licenseId": "BitTorrent-1.1", + "detailsUrl": "https://spdx.org/licenses/Dotseqn.json", + "referenceNumber": 59, + "name": "Dotseqn License", + "licenseId": "Dotseqn", "seeAlso": [ - "http://directory.fsf.org/wiki/License:BitTorrentOSL1.1" + "https://fedoraproject.org/wiki/Licensing/Dotseqn" ], "isOsiApproved": false }, { - "reference": "./BlueOak-1.0.0.html", + "reference": "https://spdx.org/licenses/OSL-3.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/BlueOak-1.0.0.json", - "referenceNumber": "23", - "name": "Blue Oak Model License 1.0.0", - "licenseId": "BlueOak-1.0.0", + "detailsUrl": "https://spdx.org/licenses/OSL-3.0.json", + "referenceNumber": 60, + "name": "Open Software License 3.0", + "licenseId": "OSL-3.0", "seeAlso": [ - "https://blueoakcouncil.org/license/1.0.0" + "https://web.archive.org/web/20120101081418/http://rosenlaw.com:80/OSL3.0.htm", + "https://opensource.org/licenses/OSL-3.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./Borceux.html", + "reference": "https://spdx.org/licenses/Linux-OpenIB.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Borceux.json", - "referenceNumber": "311", - "name": "Borceux license", - "licenseId": "Borceux", + "detailsUrl": "https://spdx.org/licenses/Linux-OpenIB.json", + "referenceNumber": 61, + "name": "Linux Kernel Variant of OpenIB.org license", + "licenseId": "Linux-OpenIB", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Borceux" + "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/infiniband/core/sa.h" ], "isOsiApproved": false }, { - "reference": "./CATOSL-1.1.html", + "reference": "https://spdx.org/licenses/SMPPL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CATOSL-1.1.json", - "referenceNumber": "262", - "name": "Computer Associates Trusted Open Source License 1.1", - "licenseId": "CATOSL-1.1", + "detailsUrl": "https://spdx.org/licenses/SMPPL.json", + "referenceNumber": 62, + "name": "Secure Messaging Protocol Public License", + "licenseId": "SMPPL", "seeAlso": [ - "https://opensource.org/licenses/CATOSL-1.1" + "https://github.com/dcblake/SMP/blob/master/Documentation/License.txt" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./CC-BY-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-1.0.json", - "referenceNumber": "128", - "name": "Creative Commons Attribution 1.0 Generic", - "licenseId": "CC-BY-1.0", + "reference": "https://spdx.org/licenses/AGPL-1.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/AGPL-1.0.json", + "referenceNumber": 63, + "name": "Affero General Public License v1.0", + "licenseId": "AGPL-1.0", "seeAlso": [ - "https://creativecommons.org/licenses/by/1.0/legalcode" + "http://www.affero.org/oagpl.html" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./CC-BY-2.0.html", + "reference": "https://spdx.org/licenses/GFDL-1.3-no-invariants-or-later.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-2.0.json", - "referenceNumber": "232", - "name": "Creative Commons Attribution 2.0 Generic", - "licenseId": "CC-BY-2.0", + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-no-invariants-or-later.json", + "referenceNumber": 64, + "name": "GNU Free Documentation License v1.3 or later - no invariants", + "licenseId": "GFDL-1.3-no-invariants-or-later", "seeAlso": [ - "https://creativecommons.org/licenses/by/2.0/legalcode" + "https://www.gnu.org/licenses/fdl-1.3.txt" ], "isOsiApproved": false }, { - "reference": "./CC-BY-2.5.html", + "reference": "https://spdx.org/licenses/Net-SNMP.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-2.5.json", - "referenceNumber": "129", - "name": "Creative Commons Attribution 2.5 Generic", - "licenseId": "CC-BY-2.5", + "detailsUrl": "https://spdx.org/licenses/Net-SNMP.json", + "referenceNumber": 65, + "name": "Net-SNMP License", + "licenseId": "Net-SNMP", "seeAlso": [ - "https://creativecommons.org/licenses/by/2.5/legalcode" + "http://net-snmp.sourceforge.net/about/license.html" ], "isOsiApproved": false }, { - "reference": "./CC-BY-3.0.html", + "reference": "https://spdx.org/licenses/LAL-1.3.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-3.0.json", - "referenceNumber": "256", - "name": "Creative Commons Attribution 3.0 Unported", - "licenseId": "CC-BY-3.0", + "detailsUrl": "https://spdx.org/licenses/LAL-1.3.json", + "referenceNumber": 66, + "name": "Licence Art Libre 1.3", + "licenseId": "LAL-1.3", "seeAlso": [ - "https://creativecommons.org/licenses/by/3.0/legalcode" + "https://artlibre.org/" ], "isOsiApproved": false }, { - "reference": "./CC-BY-4.0.html", + "reference": "https://spdx.org/licenses/HPND-Markus-Kuhn.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CC-BY-4.0.json", - "referenceNumber": "330", - "name": "Creative Commons Attribution 4.0 International", - "licenseId": "CC-BY-4.0", + "detailsUrl": "https://spdx.org/licenses/HPND-Markus-Kuhn.json", + "referenceNumber": 67, + "name": "Historical Permission Notice and Disclaimer - Markus Kuhn variant", + "licenseId": "HPND-Markus-Kuhn", "seeAlso": [ - "https://creativecommons.org/licenses/by/4.0/legalcode" + "https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c", + "https://sourceware.org/git/?p\u003dbinutils-gdb.git;a\u003dblob;f\u003dreadline/readline/support/wcwidth.c;h\u003d0f5ec995796f4813abbcf4972aec0378ab74722a;hb\u003dHEAD#l55" ], "isOsiApproved": false }, { - "reference": "./CC-BY-NC-1.0.html", + "reference": "https://spdx.org/licenses/FSFULLR.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-1.0.json", - "referenceNumber": "130", - "name": "Creative Commons Attribution Non Commercial 1.0 Generic", - "licenseId": "CC-BY-NC-1.0", + "detailsUrl": "https://spdx.org/licenses/FSFULLR.json", + "referenceNumber": 68, + "name": "FSF Unlimited License (with License Retention)", + "licenseId": "FSFULLR", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/1.0/legalcode" + "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License#License_Retention_Variant" ], "isOsiApproved": false }, { - "reference": "./CC-BY-NC-2.0.html", + "reference": "https://spdx.org/licenses/QPL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-2.0.json", - "referenceNumber": "244", - "name": "Creative Commons Attribution Non Commercial 2.0 Generic", - "licenseId": "CC-BY-NC-2.0", + "detailsUrl": "https://spdx.org/licenses/QPL-1.0.json", + "referenceNumber": 69, + "name": "Q Public License 1.0", + "licenseId": "QPL-1.0", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/2.0/legalcode" + "http://doc.qt.nokia.com/3.3/license.html", + "https://opensource.org/licenses/QPL-1.0", + "https://doc.qt.io/archives/3.3/license.html" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./CC-BY-NC-2.5.html", + "reference": "https://spdx.org/licenses/AFL-1.2.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-2.5.json", - "referenceNumber": "1", - "name": "Creative Commons Attribution Non Commercial 2.5 Generic", - "licenseId": "CC-BY-NC-2.5", + "detailsUrl": "https://spdx.org/licenses/AFL-1.2.json", + "referenceNumber": 70, + "name": "Academic Free License v1.2", + "licenseId": "AFL-1.2", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/2.5/legalcode" + "http://opensource.linux-mirror.org/licenses/afl-1.2.txt", + "http://wayback.archive.org/web/20021204204652/http://www.opensource.org/licenses/academic.php" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./CC-BY-NC-3.0.html", + "reference": "https://spdx.org/licenses/AFL-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-3.0.json", - "referenceNumber": "255", - "name": "Creative Commons Attribution Non Commercial 3.0 Unported", - "licenseId": "CC-BY-NC-3.0", + "detailsUrl": "https://spdx.org/licenses/AFL-1.1.json", + "referenceNumber": 71, + "name": "Academic Free License v1.1", + "licenseId": "AFL-1.1", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/3.0/legalcode" + "http://opensource.linux-mirror.org/licenses/afl-1.1.txt", + "http://wayback.archive.org/web/20021004124254/http://www.opensource.org/licenses/academic.php" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./CC-BY-NC-4.0.html", + "reference": "https://spdx.org/licenses/Apache-2.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-4.0.json", - "referenceNumber": "186", - "name": "Creative Commons Attribution Non Commercial 4.0 International", - "licenseId": "CC-BY-NC-4.0", + "detailsUrl": "https://spdx.org/licenses/Apache-2.0.json", + "referenceNumber": 72, + "name": "Apache License 2.0", + "licenseId": "Apache-2.0", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc/4.0/legalcode" + "https://www.apache.org/licenses/LICENSE-2.0", + "https://opensource.org/licenses/Apache-2.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./CC-BY-NC-ND-1.0.html", + "reference": "https://spdx.org/licenses/UPL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-1.0.json", - "referenceNumber": "59", - "name": "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic", - "licenseId": "CC-BY-NC-ND-1.0", + "detailsUrl": "https://spdx.org/licenses/UPL-1.0.json", + "referenceNumber": 73, + "name": "Universal Permissive License v1.0", + "licenseId": "UPL-1.0", "seeAlso": [ - "https://creativecommons.org/licenses/by-nd-nc/1.0/legalcode" + "https://opensource.org/licenses/UPL" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./CC-BY-NC-ND-2.0.html", + "reference": "https://spdx.org/licenses/GLWTPL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-2.0.json", - "referenceNumber": "36", - "name": "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic", - "licenseId": "CC-BY-NC-ND-2.0", + "detailsUrl": "https://spdx.org/licenses/GLWTPL.json", + "referenceNumber": 74, + "name": "Good Luck With That Public License", + "licenseId": "GLWTPL", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/2.0/legalcode" + "https://github.com/me-shaon/GLWTPL/commit/da5f6bc734095efbacb442c0b31e33a65b9d6e85" ], "isOsiApproved": false }, { - "reference": "./CC-BY-NC-ND-2.5.html", + "reference": "https://spdx.org/licenses/RPL-1.5.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-2.5.json", - "referenceNumber": "158", - "name": "Creative Commons Attribution Non Commercial No Derivatives 2.5 Generic", - "licenseId": "CC-BY-NC-ND-2.5", + "detailsUrl": "https://spdx.org/licenses/RPL-1.5.json", + "referenceNumber": 75, + "name": "Reciprocal Public License 1.5", + "licenseId": "RPL-1.5", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/2.5/legalcode" + "https://opensource.org/licenses/RPL-1.5" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./CC-BY-NC-ND-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-3.0.json", - "referenceNumber": "48", - "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported", - "licenseId": "CC-BY-NC-ND-3.0", + "reference": "https://spdx.org/licenses/bzip2-1.0.5.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/bzip2-1.0.5.json", + "referenceNumber": 76, + "name": "bzip2 and libbzip2 License v1.0.5", + "licenseId": "bzip2-1.0.5", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode" + "https://sourceware.org/bzip2/1.0.5/bzip2-manual-1.0.5.html", + "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html" ], "isOsiApproved": false }, { - "reference": "./CC-BY-NC-ND-4.0.html", + "reference": "https://spdx.org/licenses/OFL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-ND-4.0.json", - "referenceNumber": "281", - "name": "Creative Commons Attribution Non Commercial No Derivatives 4.0 International", - "licenseId": "CC-BY-NC-ND-4.0", + "detailsUrl": "https://spdx.org/licenses/OFL-1.0.json", + "referenceNumber": 77, + "name": "SIL Open Font License 1.0", + "licenseId": "OFL-1.0", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode" + "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./CC-BY-NC-SA-1.0.html", + "reference": "https://spdx.org/licenses/LPL-1.02.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-1.0.json", - "referenceNumber": "178", - "name": "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic", - "licenseId": "CC-BY-NC-SA-1.0", + "detailsUrl": "https://spdx.org/licenses/LPL-1.02.json", + "referenceNumber": 78, + "name": "Lucent Public License v1.02", + "licenseId": "LPL-1.02", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/1.0/legalcode" - ], - "isOsiApproved": false + "http://plan9.bell-labs.com/plan9/license.html", + "https://opensource.org/licenses/LPL-1.02" + ], + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./CC-BY-NC-SA-2.0.html", + "reference": "https://spdx.org/licenses/OFL-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-2.0.json", - "referenceNumber": "81", - "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic", - "licenseId": "CC-BY-NC-SA-2.0", + "detailsUrl": "https://spdx.org/licenses/OFL-1.1.json", + "referenceNumber": 79, + "name": "SIL Open Font License 1.1", + "licenseId": "OFL-1.1", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode" + "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web", + "https://opensource.org/licenses/OFL-1.1" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./CC-BY-NC-SA-2.5.html", + "reference": "https://spdx.org/licenses/Mup.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-2.5.json", - "referenceNumber": "62", - "name": "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic", - "licenseId": "CC-BY-NC-SA-2.5", + "detailsUrl": "https://spdx.org/licenses/Mup.json", + "referenceNumber": 80, + "name": "Mup License", + "licenseId": "Mup", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/2.5/legalcode" + "https://fedoraproject.org/wiki/Licensing/Mup" ], "isOsiApproved": false }, { - "reference": "./CC-BY-NC-SA-3.0.html", + "reference": "https://spdx.org/licenses/Borceux.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-3.0.json", - "referenceNumber": "22", - "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported", - "licenseId": "CC-BY-NC-SA-3.0", + "detailsUrl": "https://spdx.org/licenses/Borceux.json", + "referenceNumber": 81, + "name": "Borceux license", + "licenseId": "Borceux", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode" + "https://fedoraproject.org/wiki/Licensing/Borceux" ], "isOsiApproved": false }, { - "reference": "./CC-BY-NC-SA-4.0.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-FR.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-NC-SA-4.0.json", - "referenceNumber": "47", - "name": "Creative Commons Attribution Non Commercial Share Alike 4.0 International", - "licenseId": "CC-BY-NC-SA-4.0", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-FR.json", + "referenceNumber": 82, + "name": "Creative Commons Attribution-NonCommercial-ShareAlike 2.0 France", + "licenseId": "CC-BY-NC-SA-2.0-FR", "seeAlso": [ - "https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode" + "https://creativecommons.org/licenses/by-nc-sa/2.0/fr/legalcode" ], "isOsiApproved": false }, { - "reference": "./CC-BY-ND-1.0.html", + "reference": "https://spdx.org/licenses/BSD-Attribution-HPND-disclaimer.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-1.0.json", - "referenceNumber": "50", - "name": "Creative Commons Attribution No Derivatives 1.0 Generic", - "licenseId": "CC-BY-ND-1.0", + "detailsUrl": "https://spdx.org/licenses/BSD-Attribution-HPND-disclaimer.json", + "referenceNumber": 83, + "name": "BSD with Attribution and HPND disclaimer", + "licenseId": "BSD-Attribution-HPND-disclaimer", "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/1.0/legalcode" + "https://github.com/cyrusimap/cyrus-sasl/blob/master/COPYING" ], "isOsiApproved": false }, { - "reference": "./CC-BY-ND-2.0.html", + "reference": "https://spdx.org/licenses/OGL-UK-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-2.0.json", - "referenceNumber": "287", - "name": "Creative Commons Attribution No Derivatives 2.0 Generic", - "licenseId": "CC-BY-ND-2.0", + "detailsUrl": "https://spdx.org/licenses/OGL-UK-1.0.json", + "referenceNumber": 84, + "name": "Open Government Licence v1.0", + "licenseId": "OGL-UK-1.0", "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/2.0/legalcode" + "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/1/" ], "isOsiApproved": false }, { - "reference": "./CC-BY-ND-2.5.html", + "reference": "https://spdx.org/licenses/Parity-6.0.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-2.5.json", - "referenceNumber": "68", - "name": "Creative Commons Attribution No Derivatives 2.5 Generic", - "licenseId": "CC-BY-ND-2.5", + "detailsUrl": "https://spdx.org/licenses/Parity-6.0.0.json", + "referenceNumber": 85, + "name": "The Parity Public License 6.0.0", + "licenseId": "Parity-6.0.0", "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/2.5/legalcode" + "https://paritylicense.com/versions/6.0.0.html" ], "isOsiApproved": false }, { - "reference": "./CC-BY-ND-3.0.html", + "reference": "https://spdx.org/licenses/SPL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-3.0.json", - "referenceNumber": "393", - "name": "Creative Commons Attribution No Derivatives 3.0 Unported", - "licenseId": "CC-BY-ND-3.0", + "detailsUrl": "https://spdx.org/licenses/SPL-1.0.json", + "referenceNumber": 86, + "name": "Sun Public License v1.0", + "licenseId": "SPL-1.0", "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/3.0/legalcode" + "https://opensource.org/licenses/SPL-1.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./CC-BY-ND-4.0.html", + "reference": "https://spdx.org/licenses/CECILL-2.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-ND-4.0.json", - "referenceNumber": "132", - "name": "Creative Commons Attribution No Derivatives 4.0 International", - "licenseId": "CC-BY-ND-4.0", + "detailsUrl": "https://spdx.org/licenses/CECILL-2.0.json", + "referenceNumber": 87, + "name": "CeCILL Free Software License Agreement v2.0", + "licenseId": "CECILL-2.0", "seeAlso": [ - "https://creativecommons.org/licenses/by-nd/4.0/legalcode" + "http://www.cecill.info/licences/Licence_CeCILL_V2-en.html" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./CC-BY-SA-1.0.html", + "reference": "https://spdx.org/licenses/TPDL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-1.0.json", - "referenceNumber": "322", - "name": "Creative Commons Attribution Share Alike 1.0 Generic", - "licenseId": "CC-BY-SA-1.0", + "detailsUrl": "https://spdx.org/licenses/TPDL.json", + "referenceNumber": 88, + "name": "Time::ParseDate License", + "licenseId": "TPDL", "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/1.0/legalcode" + "https://metacpan.org/pod/Time::ParseDate#LICENSE" ], "isOsiApproved": false }, { - "reference": "./CC-BY-SA-2.0.html", + "reference": "https://spdx.org/licenses/LOOP.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-2.0.json", - "referenceNumber": "142", - "name": "Creative Commons Attribution Share Alike 2.0 Generic", - "licenseId": "CC-BY-SA-2.0", + "detailsUrl": "https://spdx.org/licenses/LOOP.json", + "referenceNumber": 89, + "name": "Common Lisp LOOP License", + "licenseId": "LOOP", "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/2.0/legalcode" + "https://gitlab.com/embeddable-common-lisp/ecl/-/blob/develop/src/lsp/loop.lsp", + "http://git.savannah.gnu.org/cgit/gcl.git/tree/gcl/lsp/gcl_loop.lsp?h\u003dVersion_2_6_13pre", + "https://sourceforge.net/p/sbcl/sbcl/ci/master/tree/src/code/loop.lisp", + "https://github.com/cl-adams/adams/blob/master/LICENSE.md", + "https://github.com/blakemcbride/eclipse-lisp/blob/master/lisp/loop.lisp", + "https://gitlab.common-lisp.net/cmucl/cmucl/-/blob/master/src/code/loop.lisp" ], "isOsiApproved": false }, { - "reference": "./CC-BY-SA-2.5.html", + "reference": "https://spdx.org/licenses/BSD-Source-Code.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-2.5.json", - "referenceNumber": "306", - "name": "Creative Commons Attribution Share Alike 2.5 Generic", - "licenseId": "CC-BY-SA-2.5", + "detailsUrl": "https://spdx.org/licenses/BSD-Source-Code.json", + "referenceNumber": 90, + "name": "BSD Source Code Attribution", + "licenseId": "BSD-Source-Code", "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/2.5/legalcode" + "https://github.com/robbiehanson/CocoaHTTPServer/blob/master/LICENSE.txt" ], "isOsiApproved": false }, { - "reference": "./CC-BY-SA-3.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-3.0.json", - "referenceNumber": "394", - "name": "Creative Commons Attribution Share Alike 3.0 Unported", - "licenseId": "CC-BY-SA-3.0", + "reference": "https://spdx.org/licenses/GFDL-1.1.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1.json", + "referenceNumber": 91, + "name": "GNU Free Documentation License v1.1", + "licenseId": "GFDL-1.1", "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/3.0/legalcode" + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./CC-BY-SA-4.0.html", + "reference": "https://spdx.org/licenses/MulanPSL-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CC-BY-SA-4.0.json", - "referenceNumber": "32", - "name": "Creative Commons Attribution Share Alike 4.0 International", - "licenseId": "CC-BY-SA-4.0", + "detailsUrl": "https://spdx.org/licenses/MulanPSL-2.0.json", + "referenceNumber": 92, + "name": "Mulan Permissive Software License, Version 2", + "licenseId": "MulanPSL-2.0", "seeAlso": [ - "https://creativecommons.org/licenses/by-sa/4.0/legalcode" + "https://license.coscl.org.cn/MulanPSL2/" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./CC-PDDC.html", + "reference": "https://spdx.org/licenses/OLDAP-2.8.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CC-PDDC.json", - "referenceNumber": "371", - "name": "Creative Commons Public Domain Dedication and Certification", - "licenseId": "CC-PDDC", + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.8.json", + "referenceNumber": 93, + "name": "Open LDAP Public License v2.8", + "licenseId": "OLDAP-2.8", "seeAlso": [ - "https://creativecommons.org/licenses/publicdomain/" + "http://www.openldap.org/software/release/license.html" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./CC0-1.0.html", + "reference": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CC0-1.0.json", - "referenceNumber": "213", - "name": "Creative Commons Zero v1.0 Universal", - "licenseId": "CC0-1.0", + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License-2014.json", + "referenceNumber": 94, + "name": "BSD 3-Clause No Nuclear License 2014", + "licenseId": "BSD-3-Clause-No-Nuclear-License-2014", "seeAlso": [ - "https://creativecommons.org/publicdomain/zero/1.0/legalcode" + "https://java.net/projects/javaeetutorial/pages/BerkeleyLicense" ], "isOsiApproved": false }, { - "reference": "./CDDL-1.0.html", + "reference": "https://spdx.org/licenses/FDK-AAC.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CDDL-1.0.json", - "referenceNumber": "138", - "name": "Common Development and Distribution License 1.0", - "licenseId": "CDDL-1.0", + "detailsUrl": "https://spdx.org/licenses/FDK-AAC.json", + "referenceNumber": 95, + "name": "Fraunhofer FDK AAC Codec Library", + "licenseId": "FDK-AAC", "seeAlso": [ - "https://opensource.org/licenses/cddl1" + "https://fedoraproject.org/wiki/Licensing/FDK-AAC", + "https://directory.fsf.org/wiki/License:Fdk" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./CDDL-1.1.html", + "reference": "https://spdx.org/licenses/GPL-1.0-or-later.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CDDL-1.1.json", - "referenceNumber": "376", - "name": "Common Development and Distribution License 1.1", - "licenseId": "CDDL-1.1", + "detailsUrl": "https://spdx.org/licenses/GPL-1.0-or-later.json", + "referenceNumber": 96, + "name": "GNU General Public License v1.0 or later", + "licenseId": "GPL-1.0-or-later", "seeAlso": [ - "http://glassfish.java.net/public/CDDL+GPL_1_1.html", - "https://javaee.github.io/glassfish/LICENSE" + "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" ], "isOsiApproved": false }, { - "reference": "./CDLA-Permissive-1.0.html", + "reference": "https://spdx.org/licenses/Sendmail.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CDLA-Permissive-1.0.json", - "referenceNumber": "250", - "name": "Community Data License Agreement Permissive 1.0", - "licenseId": "CDLA-Permissive-1.0", + "detailsUrl": "https://spdx.org/licenses/Sendmail.json", + "referenceNumber": 97, + "name": "Sendmail License", + "licenseId": "Sendmail", "seeAlso": [ - "https://cdla.io/permissive-1-0" + "http://www.sendmail.com/pdfs/open_source/sendmail_license.pdf", + "https://web.archive.org/web/20160322142305/https://www.sendmail.com/pdfs/open_source/sendmail_license.pdf" ], "isOsiApproved": false }, { - "reference": "./CDLA-Sharing-1.0.html", + "reference": "https://spdx.org/licenses/CC-BY-ND-3.0-DE.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CDLA-Sharing-1.0.json", - "referenceNumber": "310", - "name": "Community Data License Agreement Sharing 1.0", - "licenseId": "CDLA-Sharing-1.0", + "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-3.0-DE.json", + "referenceNumber": 98, + "name": "Creative Commons Attribution No Derivatives 3.0 Germany", + "licenseId": "CC-BY-ND-3.0-DE", "seeAlso": [ - "https://cdla.io/sharing-1-0" + "https://creativecommons.org/licenses/by-nd/3.0/de/legalcode" ], "isOsiApproved": false }, { - "reference": "./CECILL-1.0.html", + "reference": "https://spdx.org/licenses/Afmparse.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CECILL-1.0.json", - "referenceNumber": "223", - "name": "CeCILL Free Software License Agreement v1.0", - "licenseId": "CECILL-1.0", + "detailsUrl": "https://spdx.org/licenses/Afmparse.json", + "referenceNumber": 99, + "name": "Afmparse License", + "licenseId": "Afmparse", "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL_V1-fr.html" + "https://fedoraproject.org/wiki/Licensing/Afmparse" ], "isOsiApproved": false }, { - "reference": "./CECILL-1.1.html", + "reference": "https://spdx.org/licenses/MIT-feh.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CECILL-1.1.json", - "referenceNumber": "300", - "name": "CeCILL Free Software License Agreement v1.1", - "licenseId": "CECILL-1.1", + "detailsUrl": "https://spdx.org/licenses/MIT-feh.json", + "referenceNumber": 100, + "name": "feh License", + "licenseId": "MIT-feh", "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL_V1.1-US.html" + "https://fedoraproject.org/wiki/Licensing/MIT#feh" ], "isOsiApproved": false }, { - "reference": "./CECILL-2.0.html", + "reference": "https://spdx.org/licenses/CC-BY-ND-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CECILL-2.0.json", - "referenceNumber": "352", - "name": "CeCILL Free Software License Agreement v2.0", - "licenseId": "CECILL-2.0", + "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-2.0.json", + "referenceNumber": 101, + "name": "Creative Commons Attribution No Derivatives 2.0 Generic", + "licenseId": "CC-BY-ND-2.0", "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL_V2-en.html" + "https://creativecommons.org/licenses/by-nd/2.0/legalcode" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": false }, { - "reference": "./CECILL-2.1.html", + "reference": "https://spdx.org/licenses/SHL-0.5.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CECILL-2.1.json", - "referenceNumber": "120", - "name": "CeCILL Free Software License Agreement v2.1", - "licenseId": "CECILL-2.1", + "detailsUrl": "https://spdx.org/licenses/SHL-0.5.json", + "referenceNumber": 102, + "name": "Solderpad Hardware License v0.5", + "licenseId": "SHL-0.5", "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.html" + "https://solderpad.org/licenses/SHL-0.5/" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./CECILL-B.html", + "reference": "https://spdx.org/licenses/MIT-CMU.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CECILL-B.json", - "referenceNumber": "340", - "name": "CeCILL-B Free Software License Agreement", - "licenseId": "CECILL-B", + "detailsUrl": "https://spdx.org/licenses/MIT-CMU.json", + "referenceNumber": 103, + "name": "CMU License", + "licenseId": "MIT-CMU", "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html" + "https://fedoraproject.org/wiki/Licensing:MIT?rd\u003dLicensing/MIT#CMU_Style", + "https://github.com/python-pillow/Pillow/blob/fffb426092c8db24a5f4b6df243a8a3c01fb63cd/LICENSE" ], "isOsiApproved": false }, { - "reference": "./CECILL-C.html", + "reference": "https://spdx.org/licenses/Adobe-2006.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CECILL-C.json", - "referenceNumber": "77", - "name": "CeCILL-C Free Software License Agreement", - "licenseId": "CECILL-C", + "detailsUrl": "https://spdx.org/licenses/Adobe-2006.json", + "referenceNumber": 104, + "name": "Adobe Systems Incorporated Source Code License Agreement", + "licenseId": "Adobe-2006", "seeAlso": [ - "http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html" + "https://fedoraproject.org/wiki/Licensing/AdobeLicense" ], "isOsiApproved": false }, { - "reference": "./CERN-OHL-1.1.html", + "reference": "https://spdx.org/licenses/EPL-2.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CERN-OHL-1.1.json", - "referenceNumber": "341", - "name": "CERN Open Hardware License v1.1", - "licenseId": "CERN-OHL-1.1", + "detailsUrl": "https://spdx.org/licenses/EPL-2.0.json", + "referenceNumber": 105, + "name": "Eclipse Public License 2.0", + "licenseId": "EPL-2.0", "seeAlso": [ - "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.1" + "https://www.eclipse.org/legal/epl-2.0", + "https://www.opensource.org/licenses/EPL-2.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./CERN-OHL-1.2.html", + "reference": "https://spdx.org/licenses/ODbL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CERN-OHL-1.2.json", - "referenceNumber": "3", - "name": "CERN Open Hardware Licence v1.2", - "licenseId": "CERN-OHL-1.2", + "detailsUrl": "https://spdx.org/licenses/ODbL-1.0.json", + "referenceNumber": 106, + "name": "Open Data Commons Open Database License v1.0", + "licenseId": "ODbL-1.0", "seeAlso": [ - "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.2" + "http://www.opendatacommons.org/licenses/odbl/1.0/", + "https://opendatacommons.org/licenses/odbl/1-0/" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./CNRI-Jython.html", + "reference": "https://spdx.org/licenses/CERN-OHL-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CNRI-Jython.json", - "referenceNumber": "94", - "name": "CNRI Jython License", - "licenseId": "CNRI-Jython", + "detailsUrl": "https://spdx.org/licenses/CERN-OHL-1.1.json", + "referenceNumber": 107, + "name": "CERN Open Hardware Licence v1.1", + "licenseId": "CERN-OHL-1.1", "seeAlso": [ - "http://www.jython.org/license.html" + "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.1" ], "isOsiApproved": false }, { - "reference": "./CNRI-Python.html", + "reference": "https://spdx.org/licenses/App-s2p.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CNRI-Python.json", - "referenceNumber": "45", - "name": "CNRI Python License", - "licenseId": "CNRI-Python", + "detailsUrl": "https://spdx.org/licenses/App-s2p.json", + "referenceNumber": 108, + "name": "App::s2p License", + "licenseId": "App-s2p", "seeAlso": [ - "https://opensource.org/licenses/CNRI-Python" + "https://fedoraproject.org/wiki/Licensing/App-s2p" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./CNRI-Python-GPL-Compatible.html", + "reference": "https://spdx.org/licenses/SWL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CNRI-Python-GPL-Compatible.json", - "referenceNumber": "202", - "name": "CNRI Python Open Source GPL Compatible License Agreement", - "licenseId": "CNRI-Python-GPL-Compatible", + "detailsUrl": "https://spdx.org/licenses/SWL.json", + "referenceNumber": 109, + "name": "Scheme Widget Library (SWL) Software License Agreement", + "licenseId": "SWL", "seeAlso": [ - "http://www.python.org/download/releases/1.6.1/download_win/" + "https://fedoraproject.org/wiki/Licensing/SWL" ], "isOsiApproved": false }, { - "reference": "./CPAL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CPAL-1.0.json", - "referenceNumber": "170", - "name": "Common Public Attribution License 1.0", - "licenseId": "CPAL-1.0", + "reference": "https://spdx.org/licenses/GPL-3.0+.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-3.0+.json", + "referenceNumber": 110, + "name": "GNU General Public License v3.0 or later", + "licenseId": "GPL-3.0+", "seeAlso": [ - "https://opensource.org/licenses/CPAL-1.0" + "https://www.gnu.org/licenses/gpl-3.0-standalone.html", + "https://opensource.org/licenses/GPL-3.0" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./CPL-1.0.html", + "reference": "https://spdx.org/licenses/NASA-1.3.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/CPL-1.0.json", - "referenceNumber": "172", - "name": "Common Public License 1.0", - "licenseId": "CPL-1.0", + "detailsUrl": "https://spdx.org/licenses/NASA-1.3.json", + "referenceNumber": 111, + "name": "NASA Open Source Agreement 1.3", + "licenseId": "NASA-1.3", "seeAlso": [ - "https://opensource.org/licenses/CPL-1.0" + "http://ti.arc.nasa.gov/opensource/nosa/", + "https://opensource.org/licenses/NASA-1.3" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": false }, { - "reference": "./CPOL-1.02.html", + "reference": "https://spdx.org/licenses/OLDAP-2.2.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CPOL-1.02.json", - "referenceNumber": "28", - "name": "Code Project Open License 1.02", - "licenseId": "CPOL-1.02", + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.2.1.json", + "referenceNumber": 112, + "name": "Open LDAP Public License v2.2.1", + "licenseId": "OLDAP-2.2.1", "seeAlso": [ - "http://www.codeproject.com/info/cpol10.aspx" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d4bc786f34b50aa301be6f5600f58a980070f481e" ], "isOsiApproved": false }, { - "reference": "./CUA-OPL-1.0.html", + "reference": "https://spdx.org/licenses/Libpng.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CUA-OPL-1.0.json", - "referenceNumber": "365", - "name": "CUA Office Public License v1.0", - "licenseId": "CUA-OPL-1.0", + "detailsUrl": "https://spdx.org/licenses/Libpng.json", + "referenceNumber": 113, + "name": "libpng License", + "licenseId": "Libpng", "seeAlso": [ - "https://opensource.org/licenses/CUA-OPL-1.0" + "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt" ], - "isOsiApproved": true + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-2-Clause-NetBSD.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-NetBSD.json", + "referenceNumber": 114, + "name": "BSD 2-Clause NetBSD License", + "licenseId": "BSD-2-Clause-NetBSD", + "seeAlso": [ + "http://www.netbsd.org/about/redistribution.html#default" + ], + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./Caldera.html", + "reference": "https://spdx.org/licenses/checkmk.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Caldera.json", - "referenceNumber": "108", - "name": "Caldera License", - "licenseId": "Caldera", + "detailsUrl": "https://spdx.org/licenses/checkmk.json", + "referenceNumber": 115, + "name": "Checkmk License", + "licenseId": "checkmk", "seeAlso": [ - "http://www.lemis.com/grog/UNIX/ancient-source-all.pdf" + "https://github.com/libcheck/check/blob/master/checkmk/checkmk.in" ], "isOsiApproved": false }, { - "reference": "./ClArtistic.html", + "reference": "https://spdx.org/licenses/ZPL-1.1.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/ClArtistic.json", - "referenceNumber": "271", - "name": "Clarified Artistic License", - "licenseId": "ClArtistic", + "detailsUrl": "https://spdx.org/licenses/ZPL-1.1.json", + "referenceNumber": 116, + "name": "Zope Public License 1.1", + "licenseId": "ZPL-1.1", "seeAlso": [ - "http://gianluca.dellavedova.org/2011/01/03/clarified-artistic-license/", - "http://www.ncftp.com/ncftp/doc/LICENSE.txt" + "http://old.zope.org/Resources/License/ZPL-1.1" ], "isOsiApproved": false }, { - "reference": "./Condor-1.1.html", + "reference": "https://spdx.org/licenses/Saxpath.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Condor-1.1.json", - "referenceNumber": "307", - "name": "Condor Public License v1.1", - "licenseId": "Condor-1.1", + "detailsUrl": "https://spdx.org/licenses/Saxpath.json", + "referenceNumber": 117, + "name": "Saxpath License", + "licenseId": "Saxpath", "seeAlso": [ - "http://research.cs.wisc.edu/condor/license.html#condor", - "http://web.archive.org/web/20111123062036/http://research.cs.wisc.edu/condor/license.html#condor" + "https://fedoraproject.org/wiki/Licensing/Saxpath_License" ], "isOsiApproved": false }, { - "reference": "./Crossword.html", + "reference": "https://spdx.org/licenses/xinetd.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Crossword.json", - "referenceNumber": "363", - "name": "Crossword License", - "licenseId": "Crossword", + "detailsUrl": "https://spdx.org/licenses/xinetd.json", + "referenceNumber": 118, + "name": "xinetd License", + "licenseId": "xinetd", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Crossword" + "https://fedoraproject.org/wiki/Licensing/Xinetd_License" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./CrystalStacker.html", + "reference": "https://spdx.org/licenses/HP-1986.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/CrystalStacker.json", - "referenceNumber": "168", - "name": "CrystalStacker License", - "licenseId": "CrystalStacker", + "detailsUrl": "https://spdx.org/licenses/HP-1986.json", + "referenceNumber": 119, + "name": "Hewlett-Packard 1986 License", + "licenseId": "HP-1986", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing:CrystalStacker?rd\u003dLicensing/CrystalStacker" + "https://sourceware.org/git/?p\u003dnewlib-cygwin.git;a\u003dblob;f\u003dnewlib/libc/machine/hppa/memchr.S;h\u003d1cca3e5e8867aa4bffef1f75a5c1bba25c0c441e;hb\u003dHEAD#l2" ], "isOsiApproved": false }, { - "reference": "./Cube.html", + "reference": "https://spdx.org/licenses/SSH-OpenSSH.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Cube.json", - "referenceNumber": "370", - "name": "Cube License", - "licenseId": "Cube", + "detailsUrl": "https://spdx.org/licenses/SSH-OpenSSH.json", + "referenceNumber": 120, + "name": "SSH OpenSSH license", + "licenseId": "SSH-OpenSSH", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Cube" + "https://github.com/openssh/openssh-portable/blob/1b11ea7c58cd5c59838b5fa574cd456d6047b2d4/LICENCE#L10" ], "isOsiApproved": false }, { - "reference": "./D-FSL-1.0.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-3.0-DE.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/D-FSL-1.0.json", - "referenceNumber": "182", - "name": "Deutsche Freie Software Lizenz", - "licenseId": "D-FSL-1.0", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-3.0-DE.json", + "referenceNumber": 121, + "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 Germany", + "licenseId": "CC-BY-NC-ND-3.0-DE", "seeAlso": [ - "http://www.dipp.nrw.de/d-fsl/lizenzen/", - "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/de/D-FSL-1_0_de.txt", - "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/en/D-FSL-1_0_en.txt", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/deutsche-freie-software-lizenz", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/german-free-software-license", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_de.txt/at_download/file", - "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_en.txt/at_download/file" + "https://creativecommons.org/licenses/by-nc-nd/3.0/de/legalcode" ], "isOsiApproved": false }, { - "reference": "./DOC.html", + "reference": "https://spdx.org/licenses/APAFML.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/DOC.json", - "referenceNumber": "160", - "name": "DOC License", - "licenseId": "DOC", + "detailsUrl": "https://spdx.org/licenses/APAFML.json", + "referenceNumber": 122, + "name": "Adobe Postscript AFM License", + "licenseId": "APAFML", "seeAlso": [ - "http://www.cs.wustl.edu/~schmidt/ACE-copying.html" + "https://fedoraproject.org/wiki/Licensing/AdobePostscriptAFM" ], "isOsiApproved": false }, { - "reference": "./DSDP.html", + "reference": "https://spdx.org/licenses/PHP-3.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/DSDP.json", - "referenceNumber": "141", - "name": "DSDP License", - "licenseId": "DSDP", + "detailsUrl": "https://spdx.org/licenses/PHP-3.0.json", + "referenceNumber": 123, + "name": "PHP License v3.0", + "licenseId": "PHP-3.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/DSDP" + "http://www.php.net/license/3_0.txt", + "https://opensource.org/licenses/PHP-3.0" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./Dotseqn.html", + "reference": "https://spdx.org/licenses/GFDL-1.2-only.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Dotseqn.json", - "referenceNumber": "390", - "name": "Dotseqn License", - "licenseId": "Dotseqn", + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-only.json", + "referenceNumber": 124, + "name": "GNU Free Documentation License v1.2 only", + "licenseId": "GFDL-1.2-only", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Dotseqn" + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./ECL-1.0.html", + "reference": "https://spdx.org/licenses/UCAR.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ECL-1.0.json", - "referenceNumber": "396", - "name": "Educational Community License v1.0", - "licenseId": "ECL-1.0", + "detailsUrl": "https://spdx.org/licenses/UCAR.json", + "referenceNumber": 125, + "name": "UCAR License", + "licenseId": "UCAR", "seeAlso": [ - "https://opensource.org/licenses/ECL-1.0" + "https://github.com/Unidata/UDUNITS-2/blob/master/COPYRIGHT" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./ECL-2.0.html", + "reference": "https://spdx.org/licenses/ErlPL-1.1.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/ECL-2.0.json", - "referenceNumber": "298", - "name": "Educational Community License v2.0", - "licenseId": "ECL-2.0", + "detailsUrl": "https://spdx.org/licenses/ErlPL-1.1.json", + "referenceNumber": 126, + "name": "Erlang Public License v1.1", + "licenseId": "ErlPL-1.1", "seeAlso": [ - "https://opensource.org/licenses/ECL-2.0" + "http://www.erlang.org/EPLICENSE" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./EFL-1.0.html", + "reference": "https://spdx.org/licenses/LPPL-1.3a.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/EFL-1.0.json", - "referenceNumber": "150", - "name": "Eiffel Forum License v1.0", - "licenseId": "EFL-1.0", + "detailsUrl": "https://spdx.org/licenses/LPPL-1.3a.json", + "referenceNumber": 127, + "name": "LaTeX Project Public License v1.3a", + "licenseId": "LPPL-1.3a", "seeAlso": [ - "http://www.eiffel-nice.org/license/forum.txt", - "https://opensource.org/licenses/EFL-1.0" + "http://www.latex-project.org/lppl/lppl-1-3a.txt" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./EFL-2.0.html", + "reference": "https://spdx.org/licenses/CERN-OHL-S-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/EFL-2.0.json", - "referenceNumber": "161", - "name": "Eiffel Forum License v2.0", - "licenseId": "EFL-2.0", + "detailsUrl": "https://spdx.org/licenses/CERN-OHL-S-2.0.json", + "referenceNumber": 128, + "name": "CERN Open Hardware Licence Version 2 - Strongly Reciprocal", + "licenseId": "CERN-OHL-S-2.0", "seeAlso": [ - "http://www.eiffel-nice.org/license/eiffel-forum-license-2.html", - "https://opensource.org/licenses/EFL-2.0" + "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2" ], "isOsiApproved": true }, { - "reference": "./EPL-1.0.html", + "reference": "https://spdx.org/licenses/MIT.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/EPL-1.0.json", - "referenceNumber": "214", - "name": "Eclipse Public License 1.0", - "licenseId": "EPL-1.0", + "detailsUrl": "https://spdx.org/licenses/MIT.json", + "referenceNumber": 129, + "name": "MIT License", + "licenseId": "MIT", "seeAlso": [ - "http://www.eclipse.org/legal/epl-v10.html", - "https://opensource.org/licenses/EPL-1.0" + "https://opensource.org/licenses/MIT" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./EPL-2.0.html", + "reference": "https://spdx.org/licenses/CC-BY-SA-2.1-JP.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/EPL-2.0.json", - "referenceNumber": "134", - "name": "Eclipse Public License 2.0", - "licenseId": "EPL-2.0", + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-2.1-JP.json", + "referenceNumber": 130, + "name": "Creative Commons Attribution Share Alike 2.1 Japan", + "licenseId": "CC-BY-SA-2.1-JP", "seeAlso": [ - "https://www.eclipse.org/legal/epl-2.0", - "https://www.opensource.org/licenses/EPL-2.0" + "https://creativecommons.org/licenses/by-sa/2.1/jp/legalcode" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./EUDatagrid.html", + "reference": "https://spdx.org/licenses/BSD-4.3RENO.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/EUDatagrid.json", - "referenceNumber": "192", - "name": "EU DataGrid Software License", - "licenseId": "EUDatagrid", + "detailsUrl": "https://spdx.org/licenses/BSD-4.3RENO.json", + "referenceNumber": 131, + "name": "BSD 4.3 RENO License", + "licenseId": "BSD-4.3RENO", "seeAlso": [ - "http://eu-datagrid.web.cern.ch/eu-datagrid/license.html", - "https://opensource.org/licenses/EUDatagrid" + "https://sourceware.org/git/?p\u003dbinutils-gdb.git;a\u003dblob;f\u003dlibiberty/strcasecmp.c;h\u003d131d81c2ce7881fa48c363dc5bf5fb302c61ce0b;hb\u003dHEAD" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./EUPL-1.0.html", + "reference": "https://spdx.org/licenses/CMU-Mach.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/EUPL-1.0.json", - "referenceNumber": "173", - "name": "European Union Public License 1.0", - "licenseId": "EUPL-1.0", + "detailsUrl": "https://spdx.org/licenses/CMU-Mach.json", + "referenceNumber": 132, + "name": "CMU Mach License", + "licenseId": "CMU-Mach", "seeAlso": [ - "http://ec.europa.eu/idabc/en/document/7330.html", - "http://ec.europa.eu/idabc/servlets/Doc027f.pdf?id\u003d31096" + "https://www.cs.cmu.edu/~410/licenses.html" ], "isOsiApproved": false }, { - "reference": "./EUPL-1.1.html", + "reference": "https://spdx.org/licenses/CC-BY-3.0-US.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/EUPL-1.1.json", - "referenceNumber": "92", - "name": "European Union Public License 1.1", - "licenseId": "EUPL-1.1", + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-US.json", + "referenceNumber": 133, + "name": "Creative Commons Attribution 3.0 United States", + "licenseId": "CC-BY-3.0-US", "seeAlso": [ - "https://joinup.ec.europa.eu/software/page/eupl/licence-eupl", - "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl1.1.-licence-en_0.pdf", - "https://opensource.org/licenses/EUPL-1.1" + "https://creativecommons.org/licenses/by/3.0/us/legalcode" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./EUPL-1.2.html", + "reference": "https://spdx.org/licenses/TOSL.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/EUPL-1.2.json", - "referenceNumber": "387", - "name": "European Union Public License 1.2", - "licenseId": "EUPL-1.2", + "detailsUrl": "https://spdx.org/licenses/TOSL.json", + "referenceNumber": 134, + "name": "Trusster Open Source License", + "licenseId": "TOSL", "seeAlso": [ - "https://joinup.ec.europa.eu/page/eupl-text-11-12", - "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl_v1.2_en.pdf", - "https://joinup.ec.europa.eu/sites/default/files/inline-files/EUPL%20v1_2%20EN(1).txt", - "http://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri\u003dCELEX:32017D0863", - "https://opensource.org/licenses/EUPL-1.1" + "https://fedoraproject.org/wiki/Licensing/TOSL" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./Entessa.html", + "reference": "https://spdx.org/licenses/Giftware.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Entessa.json", - "referenceNumber": "99", - "name": "Entessa Public License v1.0", - "licenseId": "Entessa", + "detailsUrl": "https://spdx.org/licenses/Giftware.json", + "referenceNumber": 135, + "name": "Giftware License", + "licenseId": "Giftware", "seeAlso": [ - "https://opensource.org/licenses/Entessa" + "http://liballeg.org/license.html#allegro-4-the-giftware-license" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./ErlPL-1.1.html", + "reference": "https://spdx.org/licenses/dvipdfm.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ErlPL-1.1.json", - "referenceNumber": "157", - "name": "Erlang Public License v1.1", - "licenseId": "ErlPL-1.1", + "detailsUrl": "https://spdx.org/licenses/dvipdfm.json", + "referenceNumber": 136, + "name": "dvipdfm License", + "licenseId": "dvipdfm", "seeAlso": [ - "http://www.erlang.org/EPLICENSE" + "https://fedoraproject.org/wiki/Licensing/dvipdfm" ], "isOsiApproved": false }, { - "reference": "./Eurosym.html", + "reference": "https://spdx.org/licenses/GFDL-1.1-only.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Eurosym.json", - "referenceNumber": "113", - "name": "Eurosym License", - "licenseId": "Eurosym", + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-only.json", + "referenceNumber": 137, + "name": "GNU Free Documentation License v1.1 only", + "licenseId": "GFDL-1.1-only", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Eurosym" + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./FSFAP.html", + "reference": "https://spdx.org/licenses/Crossword.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/FSFAP.json", - "referenceNumber": "114", - "name": "FSF All Permissive License", - "licenseId": "FSFAP", + "detailsUrl": "https://spdx.org/licenses/Crossword.json", + "referenceNumber": 138, + "name": "Crossword License", + "licenseId": "Crossword", "seeAlso": [ - "https://www.gnu.org/prep/maintain/html_node/License-Notices-for-Other-Files.html" + "https://fedoraproject.org/wiki/Licensing/Crossword" ], "isOsiApproved": false }, { - "reference": "./FSFUL.html", + "reference": "https://spdx.org/licenses/LGPL-2.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/LGPL-2.0.json", + "referenceNumber": 139, + "name": "GNU Library General Public License v2 only", + "licenseId": "LGPL-2.0", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/NCGL-UK-2.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/FSFUL.json", - "referenceNumber": "193", - "name": "FSF Unlimited License", - "licenseId": "FSFUL", + "detailsUrl": "https://spdx.org/licenses/NCGL-UK-2.0.json", + "referenceNumber": 140, + "name": "Non-Commercial Government Licence", + "licenseId": "NCGL-UK-2.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License" + "http://www.nationalarchives.gov.uk/doc/non-commercial-government-licence/version/2/" ], "isOsiApproved": false }, { - "reference": "./FSFULLR.html", + "reference": "https://spdx.org/licenses/NPL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/FSFULLR.json", - "referenceNumber": "43", - "name": "FSF Unlimited License (with License Retention)", - "licenseId": "FSFULLR", + "detailsUrl": "https://spdx.org/licenses/NPL-1.0.json", + "referenceNumber": 141, + "name": "Netscape Public License v1.0", + "licenseId": "NPL-1.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License#License_Retention_Variant" + "http://www.mozilla.org/MPL/NPL/1.0/" ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/SchemeReport.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SchemeReport.json", + "referenceNumber": 142, + "name": "Scheme Language Report License", + "licenseId": "SchemeReport", + "seeAlso": [], "isOsiApproved": false }, { - "reference": "./FTL.html", + "reference": "https://spdx.org/licenses/NLOD-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/FTL.json", - "referenceNumber": "240", - "name": "Freetype Project License", - "licenseId": "FTL", + "detailsUrl": "https://spdx.org/licenses/NLOD-2.0.json", + "referenceNumber": 143, + "name": "Norwegian Licence for Open Government Data (NLOD) 2.0", + "licenseId": "NLOD-2.0", "seeAlso": [ - "http://freetype.fis.uniroma2.it/FTL.TXT", - "http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT" + "http://data.norge.no/nlod/en/2.0" ], "isOsiApproved": false }, { - "reference": "./Fair.html", + "reference": "https://spdx.org/licenses/Intel-ACPI.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Fair.json", - "referenceNumber": "297", - "name": "Fair License", - "licenseId": "Fair", + "detailsUrl": "https://spdx.org/licenses/Intel-ACPI.json", + "referenceNumber": 144, + "name": "Intel ACPI Software License Agreement", + "licenseId": "Intel-ACPI", "seeAlso": [ - "http://fairlicense.org/", - "https://opensource.org/licenses/Fair" + "https://fedoraproject.org/wiki/Licensing/Intel_ACPI_Software_License_Agreement" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./Frameworx-1.0.html", + "reference": "https://spdx.org/licenses/LGPL-2.0-or-later.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Frameworx-1.0.json", - "referenceNumber": "389", - "name": "Frameworx Open License 1.0", - "licenseId": "Frameworx-1.0", + "detailsUrl": "https://spdx.org/licenses/LGPL-2.0-or-later.json", + "referenceNumber": 145, + "name": "GNU Library General Public License v2 or later", + "licenseId": "LGPL-2.0-or-later", "seeAlso": [ - "https://opensource.org/licenses/Frameworx-1.0" + "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" ], "isOsiApproved": true }, { - "reference": "./FreeImage.html", + "reference": "https://spdx.org/licenses/SMLNJ.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/FreeImage.json", - "referenceNumber": "277", - "name": "FreeImage Public License v1.0", - "licenseId": "FreeImage", + "detailsUrl": "https://spdx.org/licenses/SMLNJ.json", + "referenceNumber": 146, + "name": "Standard ML of New Jersey License", + "licenseId": "SMLNJ", "seeAlso": [ - "http://freeimage.sourceforge.net/freeimage-license.txt" + "https://www.smlnj.org/license.html" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./GFDL-1.1.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.1.json", - "referenceNumber": "98", - "name": "GNU Free Documentation License v1.1", - "licenseId": "GFDL-1.1", + "reference": "https://spdx.org/licenses/GFDL-1.2-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-or-later.json", + "referenceNumber": 147, + "name": "GNU Free Documentation License v1.2 or later", + "licenseId": "GFDL-1.2-or-later", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./GFDL-1.1-only.html", + "reference": "https://spdx.org/licenses/Bitstream-Charter.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.1-only.json", - "referenceNumber": "102", - "name": "GNU Free Documentation License v1.1 only", - "licenseId": "GFDL-1.1-only", + "detailsUrl": "https://spdx.org/licenses/Bitstream-Charter.json", + "referenceNumber": 148, + "name": "Bitstream Charter Font License", + "licenseId": "Bitstream-Charter", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + "https://fedoraproject.org/wiki/Licensing/Charter#License_Text", + "https://raw.githubusercontent.com/blackhole89/notekit/master/data/fonts/Charter%20license.txt" ], "isOsiApproved": false }, { - "reference": "./GFDL-1.1-or-later.html", + "reference": "https://spdx.org/licenses/Elastic-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.1-or-later.json", - "referenceNumber": "348", - "name": "GNU Free Documentation License v1.1 or later", - "licenseId": "GFDL-1.1-or-later", + "detailsUrl": "https://spdx.org/licenses/Elastic-2.0.json", + "referenceNumber": 149, + "name": "Elastic License 2.0", + "licenseId": "Elastic-2.0", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + "https://www.elastic.co/licensing/elastic-license", + "https://github.com/elastic/elasticsearch/blob/master/licenses/ELASTIC-LICENSE-2.0.txt" ], "isOsiApproved": false }, { - "reference": "./GFDL-1.2.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.2.json", - "referenceNumber": "197", - "name": "GNU Free Documentation License v1.2", - "licenseId": "GFDL-1.2", + "reference": "https://spdx.org/licenses/LGPL-3.0-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LGPL-3.0-or-later.json", + "referenceNumber": 150, + "name": "GNU Lesser General Public License v3.0 or later", + "licenseId": "LGPL-3.0-or-later", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" + "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", + "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt", + "https://opensource.org/licenses/LGPL-3.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./GFDL-1.2-only.html", + "reference": "https://spdx.org/licenses/ECL-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.2-only.json", - "referenceNumber": "236", - "name": "GNU Free Documentation License v1.2 only", - "licenseId": "GFDL-1.2-only", + "detailsUrl": "https://spdx.org/licenses/ECL-1.0.json", + "referenceNumber": 151, + "name": "Educational Community License v1.0", + "licenseId": "ECL-1.0", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" + "https://opensource.org/licenses/ECL-1.0" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./GFDL-1.2-or-later.html", + "reference": "https://spdx.org/licenses/Wsuipa.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.2-or-later.json", - "referenceNumber": "215", - "name": "GNU Free Documentation License v1.2 or later", - "licenseId": "GFDL-1.2-or-later", + "detailsUrl": "https://spdx.org/licenses/Wsuipa.json", + "referenceNumber": 152, + "name": "Wsuipa License", + "licenseId": "Wsuipa", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" + "https://fedoraproject.org/wiki/Licensing/Wsuipa" ], "isOsiApproved": false }, { - "reference": "./GFDL-1.3.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.3.json", - "referenceNumber": "112", - "name": "GNU Free Documentation License v1.3", - "licenseId": "GFDL-1.3", + "reference": "https://spdx.org/licenses/Sendmail-8.23.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Sendmail-8.23.json", + "referenceNumber": 153, + "name": "Sendmail License 8.23", + "licenseId": "Sendmail-8.23", "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" + "https://www.proofpoint.com/sites/default/files/sendmail-license.pdf", + "https://web.archive.org/web/20181003101040/https://www.proofpoint.com/sites/default/files/sendmail-license.pdf" ], "isOsiApproved": false }, { - "reference": "./GFDL-1.3-only.html", + "reference": "https://spdx.org/licenses/CC-BY-SA-4.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.3-only.json", - "referenceNumber": "69", - "name": "GNU Free Documentation License v1.3 only", - "licenseId": "GFDL-1.3-only", + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-4.0.json", + "referenceNumber": 154, + "name": "Creative Commons Attribution Share Alike 4.0 International", + "licenseId": "CC-BY-SA-4.0", "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" + "https://creativecommons.org/licenses/by-sa/4.0/legalcode" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./GFDL-1.3-or-later.html", + "reference": "https://spdx.org/licenses/ODC-By-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GFDL-1.3-or-later.json", - "referenceNumber": "4", - "name": "GNU Free Documentation License v1.3 or later", - "licenseId": "GFDL-1.3-or-later", + "detailsUrl": "https://spdx.org/licenses/ODC-By-1.0.json", + "referenceNumber": 155, + "name": "Open Data Commons Attribution License v1.0", + "licenseId": "ODC-By-1.0", "seeAlso": [ - "https://www.gnu.org/licenses/fdl-1.3.txt" + "https://opendatacommons.org/licenses/by/1.0/" ], "isOsiApproved": false }, { - "reference": "./GL2PS.html", + "reference": "https://spdx.org/licenses/LGPL-2.1-or-later.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/GL2PS.json", - "referenceNumber": "124", - "name": "GL2PS License", - "licenseId": "GL2PS", + "detailsUrl": "https://spdx.org/licenses/LGPL-2.1-or-later.json", + "referenceNumber": 156, + "name": "GNU Lesser General Public License v2.1 or later", + "licenseId": "LGPL-2.1-or-later", "seeAlso": [ - "http://www.geuz.org/gl2ps/COPYING.GL2PS" + "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", + "https://opensource.org/licenses/LGPL-2.1" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./GPL-1.0.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-1.0.json", - "referenceNumber": "79", - "name": "GNU General Public License v1.0 only", - "licenseId": "GPL-1.0", + "reference": "https://spdx.org/licenses/etalab-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/etalab-2.0.json", + "referenceNumber": 157, + "name": "Etalab Open License 2.0", + "licenseId": "etalab-2.0", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" + "https://github.com/DISIC/politique-de-contribution-open-source/blob/master/LICENSE.pdf", + "https://raw.githubusercontent.com/DISIC/politique-de-contribution-open-source/master/LICENSE" ], "isOsiApproved": false }, { - "reference": "./GPL-1.0+.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-1.0+.json", - "referenceNumber": "175", - "name": "GNU General Public License v1.0 or later", - "licenseId": "GPL-1.0+", + "reference": "https://spdx.org/licenses/Xerox.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Xerox.json", + "referenceNumber": 158, + "name": "Xerox License", + "licenseId": "Xerox", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" + "https://fedoraproject.org/wiki/Licensing/Xerox" ], "isOsiApproved": false }, { - "reference": "./GPL-1.0-only.html", + "reference": "https://spdx.org/licenses/CC-BY-4.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/GPL-1.0-only.json", - "referenceNumber": "15", - "name": "GNU General Public License v1.0 only", - "licenseId": "GPL-1.0-only", + "detailsUrl": "https://spdx.org/licenses/CC-BY-4.0.json", + "referenceNumber": 159, + "name": "Creative Commons Attribution 4.0 International", + "licenseId": "CC-BY-4.0", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" + "https://creativecommons.org/licenses/by/4.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Zend-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Zend-2.0.json", + "referenceNumber": 160, + "name": "Zend License v2.0", + "licenseId": "Zend-2.0", + "seeAlso": [ + "https://web.archive.org/web/20130517195954/http://www.zend.com/license/2_00.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Zimbra-1.4.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Zimbra-1.4.json", + "referenceNumber": 161, + "name": "Zimbra Public License v1.4", + "licenseId": "Zimbra-1.4", + "seeAlso": [ + "http://www.zimbra.com/legal/zimbra-public-license-1-4" ], "isOsiApproved": false }, { - "reference": "./GPL-1.0-or-later.html", + "reference": "https://spdx.org/licenses/Qhull.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/GPL-1.0-or-later.json", - "referenceNumber": "357", - "name": "GNU General Public License v1.0 or later", - "licenseId": "GPL-1.0-or-later", + "detailsUrl": "https://spdx.org/licenses/Qhull.json", + "referenceNumber": 162, + "name": "Qhull License", + "licenseId": "Qhull", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" + "https://fedoraproject.org/wiki/Licensing/Qhull" ], "isOsiApproved": false }, { - "reference": "./GPL-2.0.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0.json", - "referenceNumber": "147", - "name": "GNU General Public License v2.0 only", - "licenseId": "GPL-2.0", + "reference": "https://spdx.org/licenses/curl.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/curl.json", + "referenceNumber": 163, + "name": "curl License", + "licenseId": "curl", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", - "https://opensource.org/licenses/GPL-2.0" + "https://github.com/bagder/curl/blob/master/COPYING" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./GPL-2.0+.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0+.json", - "referenceNumber": "75", - "name": "GNU General Public License v2.0 or later", - "licenseId": "GPL-2.0+", + "reference": "https://spdx.org/licenses/W3C.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/W3C.json", + "referenceNumber": 164, + "name": "W3C Software Notice and License (2002-12-31)", + "licenseId": "W3C", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", - "https://opensource.org/licenses/GPL-2.0" + "http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html", + "https://opensource.org/licenses/W3C" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Hippocratic-2.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Hippocratic-2.1.json", + "referenceNumber": 165, + "name": "Hippocratic License 2.1", + "licenseId": "Hippocratic-2.1", + "seeAlso": [ + "https://firstdonoharm.dev/version/2/1/license.html", + "https://github.com/EthicalSource/hippocratic-license/blob/58c0e646d64ff6fbee275bfe2b9492f914e3ab2a/LICENSE.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CPL-1.0.json", + "referenceNumber": 166, + "name": "Common Public License 1.0", + "licenseId": "CPL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/CPL-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/BSD-2-Clause.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause.json", + "referenceNumber": 167, + "name": "BSD 2-Clause \"Simplified\" License", + "licenseId": "BSD-2-Clause", + "seeAlso": [ + "https://opensource.org/licenses/BSD-2-Clause" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Caldera.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Caldera.json", + "referenceNumber": 168, + "name": "Caldera License", + "licenseId": "Caldera", + "seeAlso": [ + "http://www.lemis.com/grog/UNIX/ancient-source-all.pdf" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OPUBL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OPUBL-1.0.json", + "referenceNumber": 169, + "name": "Open Publication License v1.0", + "licenseId": "OPUBL-1.0", + "seeAlso": [ + "http://opencontent.org/openpub/", + "https://www.debian.org/opl", + "https://www.ctan.org/license/opl" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-DE.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-DE.json", + "referenceNumber": 170, + "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 Germany", + "licenseId": "CC-BY-NC-SA-2.0-DE", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-sa/2.0/de/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CDL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CDL-1.0.json", + "referenceNumber": 171, + "name": "Common Documentation License 1.0", + "licenseId": "CDL-1.0", + "seeAlso": [ + "http://www.opensource.apple.com/cdl/", + "https://fedoraproject.org/wiki/Licensing/Common_Documentation_License", + "https://www.gnu.org/licenses/license-list.html#ACDL" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MS-LPL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MS-LPL.json", + "referenceNumber": 172, + "name": "Microsoft Limited Public License", + "licenseId": "MS-LPL", + "seeAlso": [ + "https://www.openhub.net/licenses/mslpl", + "https://github.com/gabegundy/atlserver/blob/master/License.txt", + "https://en.wikipedia.org/wiki/Shared_Source_Initiative#Microsoft_Limited_Public_License_(Ms-LPL)" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NAIST-2003.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NAIST-2003.json", + "referenceNumber": 173, + "name": "Nara Institute of Science and Technology License (2003)", + "licenseId": "NAIST-2003", + "seeAlso": [ + "https://enterprise.dejacode.com/licenses/public/naist-2003/#license-text", + "https://github.com/nodejs/node/blob/4a19cc8947b1bba2b2d27816ec3d0edf9b28e503/LICENSE#L343" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.1-invariants-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-invariants-or-later.json", + "referenceNumber": 174, + "name": "GNU Free Documentation License v1.1 or later - invariants", + "licenseId": "GFDL-1.1-invariants-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + ], + "isOsiApproved": false }, { - "reference": "./GPL-2.0-only.html", + "reference": "https://spdx.org/licenses/GPL-2.0-only.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-only.json", - "referenceNumber": "233", + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-only.json", + "referenceNumber": 175, "name": "GNU General Public License v2.0 only", "licenseId": "GPL-2.0-only", "seeAlso": [ "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", "https://opensource.org/licenses/GPL-2.0" ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/BitTorrent-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BitTorrent-1.1.json", + "referenceNumber": 176, + "name": "BitTorrent Open Source License v1.1", + "licenseId": "BitTorrent-1.1", + "seeAlso": [ + "http://directory.fsf.org/wiki/License:BitTorrentOSL1.1" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0-with-GCC-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-GCC-exception.json", + "referenceNumber": 177, + "name": "GNU General Public License v2.0 w/GCC Runtime Library exception", + "licenseId": "GPL-2.0-with-GCC-exception", + "seeAlso": [ + "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/IPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/IPL-1.0.json", + "referenceNumber": 178, + "name": "IBM Public License v1.0", + "licenseId": "IPL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/IPL-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CECILL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CECILL-1.1.json", + "referenceNumber": 179, + "name": "CeCILL Free Software License Agreement v1.1", + "licenseId": "CECILL-1.1", + "seeAlso": [ + "http://www.cecill.info/licences/Licence_CeCILL_V1.1-US.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CAL-1.0-Combined-Work-Exception.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CAL-1.0-Combined-Work-Exception.json", + "referenceNumber": 180, + "name": "Cryptographic Autonomy License 1.0 (Combined Work Exception)", + "licenseId": "CAL-1.0-Combined-Work-Exception", + "seeAlso": [ + "http://cryptographicautonomylicense.com/license-text.html", + "https://opensource.org/licenses/CAL-1.0" + ], "isOsiApproved": true }, { - "reference": "./GPL-2.0-or-later.html", + "reference": "https://spdx.org/licenses/PDDL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PDDL-1.0.json", + "referenceNumber": 181, + "name": "Open Data Commons Public Domain Dedication \u0026 License 1.0", + "licenseId": "PDDL-1.0", + "seeAlso": [ + "http://opendatacommons.org/licenses/pddl/1.0/", + "https://opendatacommons.org/licenses/pddl/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ANTLR-PD.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ANTLR-PD.json", + "referenceNumber": 182, + "name": "ANTLR Software Rights Notice", + "licenseId": "ANTLR-PD", + "seeAlso": [ + "http://www.antlr2.org/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0-or-later.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-or-later.json", - "referenceNumber": "56", + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-or-later.json", + "referenceNumber": 183, "name": "GNU General Public License v2.0 or later", "licenseId": "GPL-2.0-or-later", "seeAlso": [ "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", "https://opensource.org/licenses/GPL-2.0" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./GPL-2.0-with-GCC-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-GCC-exception.json", - "referenceNumber": "117", - "name": "GNU General Public License v2.0 w/GCC Runtime Library exception", - "licenseId": "GPL-2.0-with-GCC-exception", + "reference": "https://spdx.org/licenses/IJG.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/IJG.json", + "referenceNumber": 184, + "name": "Independent JPEG Group License", + "licenseId": "IJG", "seeAlso": [ - "https://gcc.gnu.org/git/?p\u003dgcc.git;a\u003dblob;f\u003dgcc/libgcc1.c;h\u003d762f5143fc6eed57b6797c82710f3538aa52b40b;hb\u003dcb143a3ce4fb417c68f5fa2691a1b1b1053dfba9#l10" + "http://dev.w3.org/cvsweb/Amaya/libjpeg/Attic/README?rev\u003d1.2" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/AGPL-1.0-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AGPL-1.0-only.json", + "referenceNumber": 185, + "name": "Affero General Public License v1.0 only", + "licenseId": "AGPL-1.0-only", + "seeAlso": [ + "http://www.affero.org/oagpl.html" ], "isOsiApproved": false }, { - "reference": "./GPL-2.0-with-autoconf-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-autoconf-exception.json", - "referenceNumber": "355", - "name": "GNU General Public License v2.0 w/Autoconf exception", - "licenseId": "GPL-2.0-with-autoconf-exception", + "reference": "https://spdx.org/licenses/Spencer-99.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Spencer-99.json", + "referenceNumber": 186, + "name": "Spencer License 99", + "licenseId": "Spencer-99", "seeAlso": [ - "http://ac-archive.sourceforge.net/doc/copyright.html" + "http://www.opensource.apple.com/source/tcl/tcl-5/tcl/generic/regfronts.c" ], "isOsiApproved": false }, { - "reference": "./GPL-2.0-with-bison-exception.html", + "reference": "https://spdx.org/licenses/LGPL-2.1+.html", "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-bison-exception.json", - "referenceNumber": "378", - "name": "GNU General Public License v2.0 w/Bison exception", - "licenseId": "GPL-2.0-with-bison-exception", + "detailsUrl": "https://spdx.org/licenses/LGPL-2.1+.json", + "referenceNumber": 187, + "name": "GNU Lesser General Public License v2.1 or later", + "licenseId": "LGPL-2.1+", "seeAlso": [ - "http://git.savannah.gnu.org/cgit/bison.git/tree/data/yacc.c?id\u003d193d7c7054ba7197b0789e14965b739162319b5e#n141" + "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", + "https://opensource.org/licenses/LGPL-2.1" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/BSD-4-Clause-UC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-4-Clause-UC.json", + "referenceNumber": 188, + "name": "BSD-4-Clause (University of California-Specific)", + "licenseId": "BSD-4-Clause-UC", + "seeAlso": [ + "http://www.freebsd.org/copyright/license.html" ], "isOsiApproved": false }, { - "reference": "./GPL-2.0-with-classpath-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-classpath-exception.json", - "referenceNumber": "60", - "name": "GNU General Public License v2.0 w/Classpath exception", - "licenseId": "GPL-2.0-with-classpath-exception", + "reference": "https://spdx.org/licenses/CC0-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC0-1.0.json", + "referenceNumber": 189, + "name": "Creative Commons Zero v1.0 Universal", + "licenseId": "CC0-1.0", + "seeAlso": [ + "https://creativecommons.org/publicdomain/zero/1.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/MPL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MPL-2.0.json", + "referenceNumber": 190, + "name": "Mozilla Public License 2.0", + "licenseId": "MPL-2.0", + "seeAlso": [ + "https://www.mozilla.org/MPL/2.0/", + "https://opensource.org/licenses/MPL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LZMA-SDK-9.11-to-9.20.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LZMA-SDK-9.11-to-9.20.json", + "referenceNumber": 191, + "name": "LZMA SDK License (versions 9.11 to 9.20)", + "licenseId": "LZMA-SDK-9.11-to-9.20", + "seeAlso": [ + "https://www.7-zip.org/sdk.html", + "https://sourceforge.net/projects/sevenzip/files/LZMA%20SDK/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Sleepycat.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Sleepycat.json", + "referenceNumber": 192, + "name": "Sleepycat License", + "licenseId": "Sleepycat", + "seeAlso": [ + "https://opensource.org/licenses/Sleepycat" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CrystalStacker.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CrystalStacker.json", + "referenceNumber": 193, + "name": "CrystalStacker License", + "licenseId": "CrystalStacker", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing:CrystalStacker?rd\u003dLicensing/CrystalStacker" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/MPL-2.0-no-copyleft-exception.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MPL-2.0-no-copyleft-exception.json", + "referenceNumber": 194, + "name": "Mozilla Public License 2.0 (no copyleft exception)", + "licenseId": "MPL-2.0-no-copyleft-exception", + "seeAlso": [ + "https://www.mozilla.org/MPL/2.0/", + "https://opensource.org/licenses/MPL-2.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Unicode-TOU.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Unicode-TOU.json", + "referenceNumber": 195, + "name": "Unicode Terms of Use", + "licenseId": "Unicode-TOU", + "seeAlso": [ + "http://www.unicode.org/copyright.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/FreeImage.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FreeImage.json", + "referenceNumber": 196, + "name": "FreeImage Public License v1.0", + "licenseId": "FreeImage", + "seeAlso": [ + "http://freeimage.sourceforge.net/freeimage-license.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AFL-2.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AFL-2.1.json", + "referenceNumber": 197, + "name": "Academic Free License v2.1", + "licenseId": "AFL-2.1", + "seeAlso": [ + "http://opensource.linux-mirror.org/licenses/afl-2.1.txt" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/NBPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NBPL-1.0.json", + "referenceNumber": 198, + "name": "Net Boolean Public License v1", + "licenseId": "NBPL-1.0", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d37b4b3f6cc4bf34e1d3dec61e69914b9819d8894" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NLOD-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NLOD-1.0.json", + "referenceNumber": 199, + "name": "Norwegian Licence for Open Government Data (NLOD) 1.0", + "licenseId": "NLOD-1.0", + "seeAlso": [ + "http://data.norge.no/nlod/en/1.0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ADSL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ADSL.json", + "referenceNumber": 200, + "name": "Amazon Digital Services License", + "licenseId": "ADSL", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/AmazonDigitalServicesLicense" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SHL-0.51.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SHL-0.51.json", + "referenceNumber": 201, + "name": "Solderpad Hardware License, Version 0.51", + "licenseId": "SHL-0.51", + "seeAlso": [ + "https://solderpad.org/licenses/SHL-0.51/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Spencer-94.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Spencer-94.json", + "referenceNumber": 202, + "name": "Spencer License 94", + "licenseId": "Spencer-94", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/PSF-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PSF-2.0.json", + "referenceNumber": 203, + "name": "Python Software Foundation License 2.0", + "licenseId": "PSF-2.0", + "seeAlso": [ + "https://opensource.org/licenses/Python-2.0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OFL-1.0-no-RFN.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OFL-1.0-no-RFN.json", + "referenceNumber": 204, + "name": "SIL Open Font License 1.0 with no Reserved Font Name", + "licenseId": "OFL-1.0-no-RFN", + "seeAlso": [ + "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/IEC-Code-Components-EULA.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/IEC-Code-Components-EULA.json", + "referenceNumber": 205, + "name": "IEC Code Components End-user licence agreement", + "licenseId": "IEC-Code-Components-EULA", + "seeAlso": [ + "https://www.iec.ch/webstore/custserv/pdf/CC-EULA.pdf", + "https://www.iec.ch/CCv1", + "https://www.iec.ch/copyright" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Jam.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Jam.json", + "referenceNumber": 206, + "name": "Jam License", + "licenseId": "Jam", + "seeAlso": [ + "https://www.boost.org/doc/libs/1_35_0/doc/html/jam.html", + "https://web.archive.org/web/20160330173339/https://swarm.workshop.perforce.com/files/guest/perforce_software/jam/src/README" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/TU-Berlin-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TU-Berlin-1.0.json", + "referenceNumber": 207, + "name": "Technische Universitaet Berlin License 1.0", + "licenseId": "TU-Berlin-1.0", + "seeAlso": [ + "https://github.com/swh/ladspa/blob/7bf6f3799fdba70fda297c2d8fd9f526803d9680/gsm/COPYRIGHT" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-3.0.json", + "referenceNumber": 208, + "name": "Creative Commons Attribution Share Alike 3.0 Unported", + "licenseId": "CC-BY-SA-3.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/3.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/APSL-1.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/APSL-1.2.json", + "referenceNumber": 209, + "name": "Apple Public Source License 1.2", + "licenseId": "APSL-1.2", + "seeAlso": [ + "http://www.samurajdata.se/opensource/mirror/licenses/apsl.php" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-3.0-AT.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-3.0-AT.json", + "referenceNumber": 210, + "name": "Creative Commons Attribution Share Alike 3.0 Austria", + "licenseId": "CC-BY-SA-3.0-AT", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/3.0/at/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ImageMagick.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ImageMagick.json", + "referenceNumber": 211, + "name": "ImageMagick License", + "licenseId": "ImageMagick", + "seeAlso": [ + "http://www.imagemagick.org/script/license.php" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Newsletr.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Newsletr.json", + "referenceNumber": 212, + "name": "Newsletr License", + "licenseId": "Newsletr", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Newsletr" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/IPA.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/IPA.json", + "referenceNumber": 213, + "name": "IPA Font License", + "licenseId": "IPA", + "seeAlso": [ + "https://opensource.org/licenses/IPA" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Unlicense.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Unlicense.json", + "referenceNumber": 214, + "name": "The Unlicense", + "licenseId": "Unlicense", + "seeAlso": [ + "https://unlicense.org/" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/MIT-Modern-Variant.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/MIT-Modern-Variant.json", + "referenceNumber": 215, + "name": "MIT License Modern Variant", + "licenseId": "MIT-Modern-Variant", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing:MIT#Modern_Variants", + "https://ptolemy.berkeley.edu/copyright.htm", + "https://pirlwww.lpl.arizona.edu/resources/guide/software/PerlTk/Tixlic.html" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/ECL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ECL-2.0.json", + "referenceNumber": 216, + "name": "Educational Community License v2.0", + "licenseId": "ECL-2.0", + "seeAlso": [ + "https://opensource.org/licenses/ECL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Barr.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Barr.json", + "referenceNumber": 217, + "name": "Barr License", + "licenseId": "Barr", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Barr" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0+.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0+.json", + "referenceNumber": 218, + "name": "GNU General Public License v2.0 or later", + "licenseId": "GPL-2.0+", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", + "https://opensource.org/licenses/GPL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/BitTorrent-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BitTorrent-1.0.json", + "referenceNumber": 219, + "name": "BitTorrent Open Source License v1.0", + "licenseId": "BitTorrent-1.0", + "seeAlso": [ + "http://sources.gentoo.org/cgi-bin/viewvc.cgi/gentoo-x86/licenses/BitTorrent?r1\u003d1.1\u0026r2\u003d1.1.1.1\u0026diff_format\u003ds" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Brian-Gladman-3-Clause.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Brian-Gladman-3-Clause.json", + "referenceNumber": 220, + "name": "Brian Gladman 3-Clause License", + "licenseId": "Brian-Gladman-3-Clause", + "seeAlso": [ + "https://github.com/SWI-Prolog/packages-clib/blob/master/sha1/brg_endian.h" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SSH-short.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SSH-short.json", + "referenceNumber": 221, + "name": "SSH short notice", + "licenseId": "SSH-short", + "seeAlso": [ + "https://github.com/openssh/openssh-portable/blob/1b11ea7c58cd5c59838b5fa574cd456d6047b2d4/pathnames.h", + "http://web.mit.edu/kolya/.f/root/athena.mit.edu/sipb.mit.edu/project/openssh/OldFiles/src/openssh-2.9.9p2/ssh-add.1", + "https://joinup.ec.europa.eu/svn/lesoll/trunk/italc/lib/src/dsa_key.cpp" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-ND-4.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-4.0.json", + "referenceNumber": 222, + "name": "Creative Commons Attribution No Derivatives 4.0 International", + "licenseId": "CC-BY-ND-4.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nd/4.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/VSL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/VSL-1.0.json", + "referenceNumber": 223, + "name": "Vovida Software License v1.0", + "licenseId": "VSL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/VSL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/eCos-2.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/eCos-2.0.json", + "referenceNumber": 224, + "name": "eCos license version 2.0", + "licenseId": "eCos-2.0", + "seeAlso": [ + "https://www.gnu.org/licenses/ecos-license.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Info-ZIP.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Info-ZIP.json", + "referenceNumber": 225, + "name": "Info-ZIP License", + "licenseId": "Info-ZIP", + "seeAlso": [ + "http://www.info-zip.org/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SGI-B-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SGI-B-1.0.json", + "referenceNumber": 226, + "name": "SGI Free Software License B v1.0", + "licenseId": "SGI-B-1.0", + "seeAlso": [ + "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.1.0.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-No-Military-License.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-No-Military-License.json", + "referenceNumber": 227, + "name": "BSD 3-Clause No Military License", + "licenseId": "BSD-3-Clause-No-Military-License", + "seeAlso": [ + "https://gitlab.syncad.com/hive/dhive/-/blob/master/LICENSE", + "https://github.com/greymass/swift-eosio/blob/master/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ISC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ISC.json", + "referenceNumber": 228, + "name": "ISC License", + "licenseId": "ISC", + "seeAlso": [ + "https://www.isc.org/licenses/", + "https://www.isc.org/downloads/software-support-policy/isc-license/", + "https://opensource.org/licenses/ISC" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/FSFUL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/FSFUL.json", + "referenceNumber": 229, + "name": "FSF Unlimited License", + "licenseId": "FSFUL", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/FSF_Unlimited_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OSET-PL-2.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OSET-PL-2.1.json", + "referenceNumber": 230, + "name": "OSET Public License version 2.1", + "licenseId": "OSET-PL-2.1", + "seeAlso": [ + "http://www.osetfoundation.org/public-license", + "https://opensource.org/licenses/OPL-2.1" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/ClArtistic.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ClArtistic.json", + "referenceNumber": 231, + "name": "Clarified Artistic License", + "licenseId": "ClArtistic", + "seeAlso": [ + "http://gianluca.dellavedova.org/2011/01/03/clarified-artistic-license/", + "http://www.ncftp.com/ncftp/doc/LICENSE.txt" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/NTP-0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NTP-0.json", + "referenceNumber": 232, + "name": "NTP No Attribution", + "licenseId": "NTP-0", + "seeAlso": [ + "https://github.com/tytso/e2fsprogs/blob/master/lib/et/et_name.c" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NTP.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NTP.json", + "referenceNumber": 233, + "name": "NTP License", + "licenseId": "NTP", + "seeAlso": [ + "https://opensource.org/licenses/NTP" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/AMPAS.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AMPAS.json", + "referenceNumber": 234, + "name": "Academy of Motion Picture Arts and Sciences BSD", + "licenseId": "AMPAS", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/BSD#AMPASBSD" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LGPLLR.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LGPLLR.json", + "referenceNumber": 235, + "name": "Lesser General Public License For Linguistic Resources", + "licenseId": "LGPLLR", + "seeAlso": [ + "http://www-igm.univ-mlv.fr/~unitex/lgpllr.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GPL-2.0-with-font-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-font-exception.json", + "referenceNumber": 236, + "name": "GNU General Public License v2.0 w/Font exception", + "licenseId": "GPL-2.0-with-font-exception", + "seeAlso": [ + "https://www.gnu.org/licenses/gpl-faq.html#FontException" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AFL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AFL-2.0.json", + "referenceNumber": 237, + "name": "Academic Free License v2.0", + "licenseId": "AFL-2.0", + "seeAlso": [ + "http://wayback.archive.org/web/20060924134533/http://www.opensource.org/licenses/afl-2.0.txt" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CC-PDDC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-PDDC.json", + "referenceNumber": 238, + "name": "Creative Commons Public Domain Dedication and Certification", + "licenseId": "CC-PDDC", + "seeAlso": [ + "https://creativecommons.org/licenses/publicdomain/" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Spencer-86.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Spencer-86.json", + "referenceNumber": 239, + "name": "Spencer License 86", + "licenseId": "Spencer-86", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/W3C-19980720.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/W3C-19980720.json", + "referenceNumber": 240, + "name": "W3C Software Notice and License (1998-07-20)", + "licenseId": "W3C-19980720", + "seeAlso": [ + "http://www.w3.org/Consortium/Legal/copyright-software-19980720.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-2.5.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-2.5.json", + "referenceNumber": 241, + "name": "Creative Commons Attribution Share Alike 2.5 Generic", + "licenseId": "CC-BY-SA-2.5", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/2.5/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ICU.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ICU.json", + "referenceNumber": 242, + "name": "ICU License", + "licenseId": "ICU", + "seeAlso": [ + "http://source.icu-project.org/repos/icu/icu/trunk/license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/JasPer-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/JasPer-2.0.json", + "referenceNumber": 243, + "name": "JasPer License", + "licenseId": "JasPer-2.0", + "seeAlso": [ + "http://www.ece.uvic.ca/~mdadams/jasper/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Bahyph.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Bahyph.json", + "referenceNumber": 244, + "name": "Bahyph License", + "licenseId": "Bahyph", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Bahyph" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/LPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LPL-1.0.json", + "referenceNumber": 245, + "name": "Lucent Public License Version 1.0", + "licenseId": "LPL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/LPL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Glulxe.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Glulxe.json", + "referenceNumber": 246, + "name": "Glulxe License", + "licenseId": "Glulxe", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Glulxe" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SISSL-1.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SISSL-1.2.json", + "referenceNumber": 247, + "name": "Sun Industry Standards Source License v1.2", + "licenseId": "SISSL-1.2", + "seeAlso": [ + "http://gridscheduler.sourceforge.net/Gridengine_SISSL_license.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/ZPL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/ZPL-2.0.json", + "referenceNumber": 248, + "name": "Zope Public License 2.0", + "licenseId": "ZPL-2.0", + "seeAlso": [ + "http://old.zope.org/Resources/License/ZPL-2.0", + "https://opensource.org/licenses/ZPL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/TPL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/TPL-1.0.json", + "referenceNumber": 249, + "name": "THOR Public License 1.0", + "licenseId": "TPL-1.0", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing:ThorPublicLicense" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.1-invariants-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-invariants-only.json", + "referenceNumber": 250, + "name": "GNU Free Documentation License v1.1 only - invariants", + "licenseId": "GFDL-1.1-invariants-only", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/APSL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/APSL-2.0.json", + "referenceNumber": 251, + "name": "Apple Public Source License 2.0", + "licenseId": "APSL-2.0", + "seeAlso": [ + "http://www.opensource.apple.com/license/apsl/" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/EPICS.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/EPICS.json", + "referenceNumber": 252, + "name": "EPICS Open License", + "licenseId": "EPICS", + "seeAlso": [ + "https://epics.anl.gov/license/open.php" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/D-FSL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/D-FSL-1.0.json", + "referenceNumber": 253, + "name": "Deutsche Freie Software Lizenz", + "licenseId": "D-FSL-1.0", + "seeAlso": [ + "http://www.dipp.nrw.de/d-fsl/lizenzen/", + "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/de/D-FSL-1_0_de.txt", + "http://www.dipp.nrw.de/d-fsl/index_html/lizenzen/en/D-FSL-1_0_en.txt", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/deutsche-freie-software-lizenz", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/german-free-software-license", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_de.txt/at_download/file", + "https://www.hbz-nrw.de/produkte/open-access/lizenzen/dfsl/D-FSL-1_0_en.txt/at_download/file" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CERN-OHL-W-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CERN-OHL-W-2.0.json", + "referenceNumber": 254, + "name": "CERN Open Hardware Licence Version 2 - Weakly Reciprocal", + "licenseId": "CERN-OHL-W-2.0", + "seeAlso": [ + "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/IBM-pibs.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/IBM-pibs.json", + "referenceNumber": 255, + "name": "IBM PowerPC Initialization and Boot Software", + "licenseId": "IBM-pibs", + "seeAlso": [ + "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003darch/powerpc/cpu/ppc4xx/miiphy.c;h\u003d297155fdafa064b955e53e9832de93bfb0cfb85b;hb\u003d9fab4bf4cc077c21e43941866f3f2c196f28670d" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SISSL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SISSL.json", + "referenceNumber": 256, + "name": "Sun Industry Standards Source License v1.1", + "licenseId": "SISSL", + "seeAlso": [ + "http://www.openoffice.org/licenses/sissl_license.html", + "https://opensource.org/licenses/SISSL" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LiLiQ-Rplus-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LiLiQ-Rplus-1.1.json", + "referenceNumber": 257, + "name": "Licence Libre du Québec – Réciprocité forte version 1.1", + "licenseId": "LiLiQ-Rplus-1.1", + "seeAlso": [ + "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-forte-liliq-r-v1-1/", + "http://opensource.org/licenses/LiLiQ-Rplus-1.1" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/iMatix.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/iMatix.json", + "referenceNumber": 258, + "name": "iMatix Standard Function Library Agreement", + "licenseId": "iMatix", + "seeAlso": [ + "http://legacy.imatix.com/html/sfl/sfl4.htm#license" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/OLDAP-2.4.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.4.json", + "referenceNumber": 259, + "name": "Open LDAP Public License v2.4", + "licenseId": "OLDAP-2.4", + "seeAlso": [ + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcd1284c4a91a8a380d904eee68d1583f989ed386" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-No-Nuclear-License.json", + "referenceNumber": 260, + "name": "BSD 3-Clause No Nuclear License", + "licenseId": "BSD-3-Clause-No-Nuclear-License", + "seeAlso": [ + "http://download.oracle.com/otn-pub/java/licenses/bsd.txt?AuthParam\u003d1467140197_43d516ce1776bd08a58235a7785be1cc" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Condor-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Condor-1.1.json", + "referenceNumber": 261, + "name": "Condor Public License v1.1", + "licenseId": "Condor-1.1", + "seeAlso": [ + "http://research.cs.wisc.edu/condor/license.html#condor", + "http://web.archive.org/web/20111123062036/http://research.cs.wisc.edu/condor/license.html#condor" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/BSL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSL-1.0.json", + "referenceNumber": 262, + "name": "Boost Software License 1.0", + "licenseId": "BSL-1.0", + "seeAlso": [ + "http://www.boost.org/LICENSE_1_0.txt", + "https://opensource.org/licenses/BSL-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Community-Spec-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Community-Spec-1.0.json", + "referenceNumber": 263, + "name": "Community Specification License 1.0", + "licenseId": "Community-Spec-1.0", + "seeAlso": [ + "https://github.com/CommunitySpecification/1.0/blob/master/1._Community_Specification_License-v1.md" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/DRL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/DRL-1.0.json", + "referenceNumber": 264, + "name": "Detection Rule License 1.0", + "licenseId": "DRL-1.0", + "seeAlso": [ + "https://github.com/Neo23x0/sigma/blob/master/LICENSE.Detection.Rules.md" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NRL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NRL.json", + "referenceNumber": 265, + "name": "NRL License", + "licenseId": "NRL", + "seeAlso": [ + "http://web.mit.edu/network/isakmp/nrllicense.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Xnet.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Xnet.json", + "referenceNumber": 266, + "name": "X.Net License", + "licenseId": "Xnet", + "seeAlso": [ + "https://opensource.org/licenses/Xnet" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Artistic-1.0-cl8.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Artistic-1.0-cl8.json", + "referenceNumber": 267, + "name": "Artistic License 1.0 w/clause 8", + "licenseId": "Artistic-1.0-cl8", + "seeAlso": [ + "https://opensource.org/licenses/Artistic-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-3.0-IGO.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-3.0-IGO.json", + "referenceNumber": 268, + "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 IGO", + "licenseId": "CC-BY-NC-SA-3.0-IGO", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc-sa/3.0/igo/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/YPL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/YPL-1.1.json", + "referenceNumber": 269, + "name": "Yahoo! Public License v1.1", + "licenseId": "YPL-1.1", + "seeAlso": [ + "http://www.zimbra.com/license/yahoo_public_license_1.1.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/APL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/APL-1.0.json", + "referenceNumber": 270, + "name": "Adaptive Public License 1.0", + "licenseId": "APL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/APL-1.0" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/Intel.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Intel.json", + "referenceNumber": 271, + "name": "Intel Open Source License", + "licenseId": "Intel", + "seeAlso": [ + "https://opensource.org/licenses/Intel" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/XSkat.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/XSkat.json", + "referenceNumber": 272, + "name": "XSkat License", + "licenseId": "XSkat", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/XSkat_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/SNIA.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/SNIA.json", + "referenceNumber": 273, + "name": "SNIA Public License 1.1", + "licenseId": "SNIA", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/SNIA_Public_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/NLPL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NLPL.json", + "referenceNumber": 274, + "name": "No Limit Public License", + "licenseId": "NLPL", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/NLPL" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/AAL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AAL.json", + "referenceNumber": 275, + "name": "Attribution Assurance License", + "licenseId": "AAL", + "seeAlso": [ + "https://opensource.org/licenses/attribution" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-3.0-only.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/LGPL-3.0-only.json", + "referenceNumber": 276, + "name": "GNU Lesser General Public License v3.0 only", + "licenseId": "LGPL-3.0-only", + "seeAlso": [ + "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", + "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt", + "https://opensource.org/licenses/LGPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CC-BY-ND-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-3.0.json", + "referenceNumber": 277, + "name": "Creative Commons Attribution No Derivatives 3.0 Unported", + "licenseId": "CC-BY-ND-3.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nd/3.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/NIST-PD.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NIST-PD.json", + "referenceNumber": 278, + "name": "NIST Public Domain Notice", + "licenseId": "NIST-PD", + "seeAlso": [ + "https://github.com/tcheneau/simpleRPL/blob/e645e69e38dd4e3ccfeceb2db8cba05b7c2e0cd3/LICENSE.txt", + "https://github.com/tcheneau/Routing/blob/f09f46fcfe636107f22f2c98348188a65a135d98/README.md" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/w3m.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/w3m.json", + "referenceNumber": 279, + "name": "w3m License", + "licenseId": "w3m", + "seeAlso": [ + "https://github.com/tats/w3m/blob/master/COPYING" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-SA-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-2.0.json", + "referenceNumber": 280, + "name": "Creative Commons Attribution Share Alike 2.0 Generic", + "licenseId": "CC-BY-SA-2.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-sa/2.0/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.2-invariants-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-invariants-or-later.json", + "referenceNumber": 281, + "name": "GNU Free Documentation License v1.2 or later - invariants", + "licenseId": "GFDL-1.2-invariants-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/JPL-image.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/JPL-image.json", + "referenceNumber": 282, + "name": "JPL Image Use Policy", + "licenseId": "JPL-image", + "seeAlso": [ + "https://www.jpl.nasa.gov/jpl-image-use-policy" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/EFL-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/EFL-2.0.json", + "referenceNumber": 283, + "name": "Eiffel Forum License v2.0", + "licenseId": "EFL-2.0", + "seeAlso": [ + "http://www.eiffel-nice.org/license/eiffel-forum-license-2.html", + "https://opensource.org/licenses/EFL-2.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-4.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-4.0.json", + "referenceNumber": 284, + "name": "Creative Commons Attribution Non Commercial 4.0 International", + "licenseId": "CC-BY-NC-4.0", + "seeAlso": [ + "https://creativecommons.org/licenses/by-nc/4.0/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/PolyForm-Noncommercial-1.0.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PolyForm-Noncommercial-1.0.0.json", + "referenceNumber": 285, + "name": "PolyForm Noncommercial License 1.0.0", + "licenseId": "PolyForm-Noncommercial-1.0.0", + "seeAlso": [ + "https://polyformproject.org/licenses/noncommercial/1.0.0" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/Plexus.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Plexus.json", + "referenceNumber": 286, + "name": "Plexus Classworlds License", + "licenseId": "Plexus", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Plexus_Classworlds_License" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.3-invariants-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-invariants-or-later.json", + "referenceNumber": 287, + "name": "GNU Free Documentation License v1.3 or later - invariants", + "licenseId": "GFDL-1.3-invariants-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/fdl-1.3.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/HPND-sell-variant-MIT-disclaimer.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HPND-sell-variant-MIT-disclaimer.json", + "referenceNumber": 288, + "name": "HPND sell variant with MIT disclaimer", + "licenseId": "HPND-sell-variant-MIT-disclaimer", + "seeAlso": [ + "https://github.com/sigmavirus24/x11-ssh-askpass/blob/master/README" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/X11.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/X11.json", + "referenceNumber": 289, + "name": "X11 License", + "licenseId": "X11", + "seeAlso": [ + "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/Arphic-1999.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Arphic-1999.json", + "referenceNumber": 290, + "name": "Arphic Public License", + "licenseId": "Arphic-1999", + "seeAlso": [ + "http://ftp.gnu.org/gnu/non-gnu/chinese-fonts-truetype/LICENSE" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CC-BY-2.5-AU.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-2.5-AU.json", + "referenceNumber": 291, + "name": "Creative Commons Attribution 2.5 Australia", + "licenseId": "CC-BY-2.5-AU", + "seeAlso": [ + "https://creativecommons.org/licenses/by/2.5/au/legalcode" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/APSL-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/APSL-1.1.json", + "referenceNumber": 292, + "name": "Apple Public Source License 1.1", + "licenseId": "APSL-1.1", + "seeAlso": [ + "http://www.opensource.apple.com/source/IOSerialFamily/IOSerialFamily-7/APPLE_LICENSE" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/GFDL-1.1-no-invariants-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-no-invariants-or-later.json", + "referenceNumber": 293, + "name": "GNU Free Documentation License v1.1 or later - no invariants", + "licenseId": "GFDL-1.1-no-invariants-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CERN-OHL-P-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CERN-OHL-P-2.0.json", + "referenceNumber": 294, + "name": "CERN Open Hardware Licence Version 2 - Permissive", + "licenseId": "CERN-OHL-P-2.0", + "seeAlso": [ + "https://www.ohwr.org/project/cernohl/wikis/Documents/CERN-OHL-version-2" + ], + "isOsiApproved": true + }, + { + "reference": "https://spdx.org/licenses/AGPL-3.0-or-later.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/AGPL-3.0-or-later.json", + "referenceNumber": 295, + "name": "GNU Affero General Public License v3.0 or later", + "licenseId": "AGPL-3.0-or-later", + "seeAlso": [ + "https://www.gnu.org/licenses/agpl.txt", + "https://opensource.org/licenses/AGPL-3.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/bzip2-1.0.6.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/bzip2-1.0.6.json", + "referenceNumber": 296, + "name": "bzip2 and libbzip2 License v1.0.6", + "licenseId": "bzip2-1.0.6", + "seeAlso": [ + "https://sourceware.org/git/?p\u003dbzip2.git;a\u003dblob;f\u003dLICENSE;hb\u003dbzip2-1.0.6", + "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/OSL-2.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OSL-2.1.json", + "referenceNumber": 297, + "name": "Open Software License 2.1", + "licenseId": "OSL-2.1", + "seeAlso": [ + "http://web.archive.org/web/20050212003940/http://www.rosenlaw.com/osl21.htm", + "https://opensource.org/licenses/OSL-2.1" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/OCCT-PL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OCCT-PL.json", + "referenceNumber": 298, + "name": "Open CASCADE Technology Public License", + "licenseId": "OCCT-PL", + "seeAlso": [ + "http://www.opencascade.com/content/occt-public-license" + ], + "isOsiApproved": false + }, + { + "reference": "https://spdx.org/licenses/CPAL-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CPAL-1.0.json", + "referenceNumber": 299, + "name": "Common Public Attribution License 1.0", + "licenseId": "CPAL-1.0", + "seeAlso": [ + "https://opensource.org/licenses/CPAL-1.0" + ], + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/CC-BY-NC-3.0-DE.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-3.0-DE.json", + "referenceNumber": 300, + "name": "Creative Commons Attribution Non Commercial 3.0 Germany", + "licenseId": "CC-BY-NC-3.0-DE", "seeAlso": [ - "https://www.gnu.org/software/classpath/license.html" + "https://creativecommons.org/licenses/by-nc/3.0/de/legalcode" ], "isOsiApproved": false }, { - "reference": "./GPL-2.0-with-font-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-2.0-with-font-exception.json", - "referenceNumber": "375", - "name": "GNU General Public License v2.0 w/Font exception", - "licenseId": "GPL-2.0-with-font-exception", + "reference": "https://spdx.org/licenses/OLDAP-2.0.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.0.1.json", + "referenceNumber": 301, + "name": "Open LDAP Public License v2.0.1", + "licenseId": "OLDAP-2.0.1", "seeAlso": [ - "https://www.gnu.org/licenses/gpl-faq.html#FontException" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db6d68acd14e51ca3aab4428bf26522aa74873f0e" ], "isOsiApproved": false }, { - "reference": "./GPL-3.0.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-3.0.json", - "referenceNumber": "242", - "name": "GNU General Public License v3.0 only", - "licenseId": "GPL-3.0", + "reference": "https://spdx.org/licenses/NOSL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NOSL.json", + "referenceNumber": 302, + "name": "Netizen Open Source License", + "licenseId": "NOSL", "seeAlso": [ - "https://www.gnu.org/licenses/gpl-3.0-standalone.html", - "https://opensource.org/licenses/GPL-3.0" + "http://bits.netizen.com.au/licenses/NOSL/nosl.txt" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./GPL-3.0+.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-3.0+.json", - "referenceNumber": "73", - "name": "GNU General Public License v3.0 or later", - "licenseId": "GPL-3.0+", + "reference": "https://spdx.org/licenses/Python-2.0.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Python-2.0.1.json", + "referenceNumber": 303, + "name": "Python License 2.0.1", + "licenseId": "Python-2.0.1", "seeAlso": [ - "https://www.gnu.org/licenses/gpl-3.0-standalone.html", - "https://opensource.org/licenses/GPL-3.0" + "https://www.python.org/download/releases/2.0.1/license/", + "https://docs.python.org/3/license.html", + "https://github.com/python/cpython/blob/main/LICENSE" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./GPL-3.0-only.html", + "reference": "https://spdx.org/licenses/Unicode-DFS-2015.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-3.0-only.json", - "referenceNumber": "206", - "name": "GNU General Public License v3.0 only", - "licenseId": "GPL-3.0-only", + "detailsUrl": "https://spdx.org/licenses/Unicode-DFS-2015.json", + "referenceNumber": 304, + "name": "Unicode License Agreement - Data Files and Software (2015)", + "licenseId": "Unicode-DFS-2015", "seeAlso": [ - "https://www.gnu.org/licenses/gpl-3.0-standalone.html", - "https://opensource.org/licenses/GPL-3.0" + "https://web.archive.org/web/20151224134844/http://unicode.org/copyright.html" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./GPL-3.0-or-later.html", + "reference": "https://spdx.org/licenses/TU-Berlin-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/GPL-3.0-or-later.json", - "referenceNumber": "196", - "name": "GNU General Public License v3.0 or later", - "licenseId": "GPL-3.0-or-later", + "detailsUrl": "https://spdx.org/licenses/TU-Berlin-2.0.json", + "referenceNumber": 305, + "name": "Technische Universitaet Berlin License 2.0", + "licenseId": "TU-Berlin-2.0", "seeAlso": [ - "https://www.gnu.org/licenses/gpl-3.0-standalone.html", - "https://opensource.org/licenses/GPL-3.0" + "https://github.com/CorsixTH/deps/blob/fd339a9f526d1d9c9f01ccf39e438a015da50035/licences/libgsm.txt" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./GPL-3.0-with-GCC-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-3.0-with-GCC-exception.json", - "referenceNumber": "221", - "name": "GNU General Public License v3.0 w/GCC Runtime Library exception", - "licenseId": "GPL-3.0-with-GCC-exception", + "reference": "https://spdx.org/licenses/Fair.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Fair.json", + "referenceNumber": 306, + "name": "Fair License", + "licenseId": "Fair", "seeAlso": [ - "https://www.gnu.org/licenses/gcc-exception-3.1.html" + "http://fairlicense.org/", + "https://opensource.org/licenses/Fair" ], "isOsiApproved": true }, { - "reference": "./GPL-3.0-with-autoconf-exception.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/GPL-3.0-with-autoconf-exception.json", - "referenceNumber": "235", - "name": "GNU General Public License v3.0 w/Autoconf exception", - "licenseId": "GPL-3.0-with-autoconf-exception", + "reference": "https://spdx.org/licenses/CDLA-Permissive-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CDLA-Permissive-1.0.json", + "referenceNumber": 307, + "name": "Community Data License Agreement Permissive 1.0", + "licenseId": "CDLA-Permissive-1.0", "seeAlso": [ - "https://www.gnu.org/licenses/autoconf-exception-3.0.html" + "https://cdla.io/permissive-1-0" ], "isOsiApproved": false }, { - "reference": "./Giftware.html", + "reference": "https://spdx.org/licenses/libpng-2.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Giftware.json", - "referenceNumber": "369", - "name": "Giftware License", - "licenseId": "Giftware", + "detailsUrl": "https://spdx.org/licenses/libpng-2.0.json", + "referenceNumber": 308, + "name": "PNG Reference Library version 2", + "licenseId": "libpng-2.0", "seeAlso": [ - "http://liballeg.org/license.html#allegro-4-the-giftware-license" + "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt" ], "isOsiApproved": false }, { - "reference": "./Glide.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Glide.json", - "referenceNumber": "374", - "name": "3dfx Glide License", - "licenseId": "Glide", + "reference": "https://spdx.org/licenses/GPL-2.0-with-classpath-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-classpath-exception.json", + "referenceNumber": 309, + "name": "GNU General Public License v2.0 w/Classpath exception", + "licenseId": "GPL-2.0-with-classpath-exception", "seeAlso": [ - "http://www.users.on.net/~triforce/glidexp/COPYING.txt" + "https://www.gnu.org/software/classpath/license.html" ], "isOsiApproved": false }, { - "reference": "./Glulxe.html", + "reference": "https://spdx.org/licenses/C-UDA-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Glulxe.json", - "referenceNumber": "93", - "name": "Glulxe License", - "licenseId": "Glulxe", + "detailsUrl": "https://spdx.org/licenses/C-UDA-1.0.json", + "referenceNumber": 310, + "name": "Computational Use of Data Agreement v1.0", + "licenseId": "C-UDA-1.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Glulxe" + "https://github.com/microsoft/Computational-Use-of-Data-Agreement/blob/master/C-UDA-1.0.md", + "https://cdla.dev/computational-use-of-data-agreement-v1-0/" ], "isOsiApproved": false }, { - "reference": "./HPND.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/HPND.json", - "referenceNumber": "264", - "name": "Historical Permission Notice and Disclaimer", - "licenseId": "HPND", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-2.0.json", + "referenceNumber": 311, + "name": "Creative Commons Attribution Non Commercial 2.0 Generic", + "licenseId": "CC-BY-NC-2.0", "seeAlso": [ - "https://opensource.org/licenses/HPND" + "https://creativecommons.org/licenses/by-nc/2.0/legalcode" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": false }, { - "reference": "./HPND-sell-variant.html", + "reference": "https://spdx.org/licenses/GPL-3.0-only.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/HPND-sell-variant.json", - "referenceNumber": "145", - "name": "Historical Permission Notice and Disclaimer - sell variant", - "licenseId": "HPND-sell-variant", + "detailsUrl": "https://spdx.org/licenses/GPL-3.0-only.json", + "referenceNumber": 312, + "name": "GNU General Public License v3.0 only", + "licenseId": "GPL-3.0-only", "seeAlso": [ - "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/sunrpc/auth_gss/gss_generic_token.c?h\u003dv4.19" + "https://www.gnu.org/licenses/gpl-3.0-standalone.html", + "https://opensource.org/licenses/GPL-3.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./HaskellReport.html", + "reference": "https://spdx.org/licenses/RPL-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/HaskellReport.json", - "referenceNumber": "122", - "name": "Haskell Language Report License", - "licenseId": "HaskellReport", + "detailsUrl": "https://spdx.org/licenses/RPL-1.1.json", + "referenceNumber": 313, + "name": "Reciprocal Public License 1.1", + "licenseId": "RPL-1.1", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Haskell_Language_Report_License" + "https://opensource.org/licenses/RPL-1.1" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./IBM-pibs.html", + "reference": "https://spdx.org/licenses/GFDL-1.2-invariants-only.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/IBM-pibs.json", - "referenceNumber": "207", - "name": "IBM PowerPC Initialization and Boot Software", - "licenseId": "IBM-pibs", + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-invariants-only.json", + "referenceNumber": 314, + "name": "GNU Free Documentation License v1.2 only - invariants", + "licenseId": "GFDL-1.2-invariants-only", "seeAlso": [ - "http://git.denx.de/?p\u003du-boot.git;a\u003dblob;f\u003darch/powerpc/cpu/ppc4xx/miiphy.c;h\u003d297155fdafa064b955e53e9832de93bfb0cfb85b;hb\u003d9fab4bf4cc077c21e43941866f3f2c196f28670d" + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" ], "isOsiApproved": false }, { - "reference": "./ICU.html", + "reference": "https://spdx.org/licenses/SGI-B-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ICU.json", - "referenceNumber": "194", - "name": "ICU License", - "licenseId": "ICU", + "detailsUrl": "https://spdx.org/licenses/SGI-B-1.1.json", + "referenceNumber": 315, + "name": "SGI Free Software License B v1.1", + "licenseId": "SGI-B-1.1", "seeAlso": [ - "http://source.icu-project.org/repos/icu/icu/trunk/license.html" + "http://oss.sgi.com/projects/FreeB/" ], "isOsiApproved": false }, { - "reference": "./IJG.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/IJG.json", - "referenceNumber": "55", - "name": "Independent JPEG Group License", - "licenseId": "IJG", + "reference": "https://spdx.org/licenses/GPL-2.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0.json", + "referenceNumber": 316, + "name": "GNU General Public License v2.0 only", + "licenseId": "GPL-2.0", "seeAlso": [ - "http://dev.w3.org/cvsweb/Amaya/libjpeg/Attic/README?rev\u003d1.2" + "https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html", + "https://opensource.org/licenses/GPL-2.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./IPA.html", + "reference": "https://spdx.org/licenses/Frameworx-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/IPA.json", - "referenceNumber": "312", - "name": "IPA Font License", - "licenseId": "IPA", + "detailsUrl": "https://spdx.org/licenses/Frameworx-1.0.json", + "referenceNumber": 317, + "name": "Frameworx Open License 1.0", + "licenseId": "Frameworx-1.0", "seeAlso": [ - "https://opensource.org/licenses/IPA" + "https://opensource.org/licenses/Frameworx-1.0" ], "isOsiApproved": true }, { - "reference": "./IPL-1.0.html", + "reference": "https://spdx.org/licenses/BSD-3-Clause-Attribution.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/IPL-1.0.json", - "referenceNumber": "31", - "name": "IBM Public License v1.0", - "licenseId": "IPL-1.0", + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Attribution.json", + "referenceNumber": 318, + "name": "BSD with attribution", + "licenseId": "BSD-3-Clause-Attribution", "seeAlso": [ - "https://opensource.org/licenses/IPL-1.0" + "https://fedoraproject.org/wiki/Licensing/BSD_with_Attribution" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./ISC.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/ISC.json", - "referenceNumber": "110", - "name": "ISC License", - "licenseId": "ISC", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-1.0.json", + "referenceNumber": 319, + "name": "Creative Commons Attribution Non Commercial Share Alike 1.0 Generic", + "licenseId": "CC-BY-NC-SA-1.0", "seeAlso": [ - "https://www.isc.org/downloads/software-support-policy/isc-license/", - "https://opensource.org/licenses/ISC" + "https://creativecommons.org/licenses/by-nc-sa/1.0/legalcode" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./ImageMagick.html", + "reference": "https://spdx.org/licenses/CNRI-Jython.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ImageMagick.json", - "referenceNumber": "231", - "name": "ImageMagick License", - "licenseId": "ImageMagick", + "detailsUrl": "https://spdx.org/licenses/CNRI-Jython.json", + "referenceNumber": 320, + "name": "CNRI Jython License", + "licenseId": "CNRI-Jython", "seeAlso": [ - "http://www.imagemagick.org/script/license.php" + "http://www.jython.org/license.html" ], "isOsiApproved": false }, { - "reference": "./Imlib2.html", + "reference": "https://spdx.org/licenses/SSPL-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Imlib2.json", - "referenceNumber": "257", - "name": "Imlib2 License", - "licenseId": "Imlib2", + "detailsUrl": "https://spdx.org/licenses/SSPL-1.0.json", + "referenceNumber": 321, + "name": "Server Side Public License, v 1", + "licenseId": "SSPL-1.0", "seeAlso": [ - "http://trac.enlightenment.org/e/browser/trunk/imlib2/COPYING", - "https://git.enlightenment.org/legacy/imlib2.git/tree/COPYING" + "https://www.mongodb.com/licensing/server-side-public-license" ], "isOsiApproved": false }, { - "reference": "./Info-ZIP.html", + "reference": "https://spdx.org/licenses/TTWL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Info-ZIP.json", - "referenceNumber": "104", - "name": "Info-ZIP License", - "licenseId": "Info-ZIP", + "detailsUrl": "https://spdx.org/licenses/TTWL.json", + "referenceNumber": 322, + "name": "Text-Tabs+Wrap License", + "licenseId": "TTWL", "seeAlso": [ - "http://www.info-zip.org/license.html" + "https://fedoraproject.org/wiki/Licensing/TTWL", + "https://github.com/ap/Text-Tabs/blob/master/lib.modern/Text/Tabs.pm#L148" ], "isOsiApproved": false }, { - "reference": "./Intel.html", + "reference": "https://spdx.org/licenses/MirOS.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Intel.json", - "referenceNumber": "167", - "name": "Intel Open Source License", - "licenseId": "Intel", + "detailsUrl": "https://spdx.org/licenses/MirOS.json", + "referenceNumber": 323, + "name": "The MirOS Licence", + "licenseId": "MirOS", "seeAlso": [ - "https://opensource.org/licenses/Intel" + "https://opensource.org/licenses/MirOS" ], "isOsiApproved": true }, { - "reference": "./Intel-ACPI.html", + "reference": "https://spdx.org/licenses/OGTSL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Intel-ACPI.json", - "referenceNumber": "88", - "name": "Intel ACPI Software License Agreement", - "licenseId": "Intel-ACPI", + "detailsUrl": "https://spdx.org/licenses/OGTSL.json", + "referenceNumber": 324, + "name": "Open Group Test Suite License", + "licenseId": "OGTSL", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Intel_ACPI_Software_License_Agreement" + "http://www.opengroup.org/testing/downloads/The_Open_Group_TSL.txt", + "https://opensource.org/licenses/OGTSL" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./Interbase-1.0.html", + "reference": "https://spdx.org/licenses/GL2PS.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Interbase-1.0.json", - "referenceNumber": "83", - "name": "Interbase Public License v1.0", - "licenseId": "Interbase-1.0", + "detailsUrl": "https://spdx.org/licenses/GL2PS.json", + "referenceNumber": 325, + "name": "GL2PS License", + "licenseId": "GL2PS", "seeAlso": [ - "https://web.archive.org/web/20060319014854/http://info.borland.com/devsupport/interbase/opensource/IPL.html" + "http://www.geuz.org/gl2ps/COPYING.GL2PS" ], "isOsiApproved": false }, { - "reference": "./JPNIC.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-3.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/JPNIC.json", - "referenceNumber": "105", - "name": "Japan Network Information Center License", - "licenseId": "JPNIC", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-3.0.json", + "referenceNumber": 326, + "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 Unported", + "licenseId": "CC-BY-NC-SA-3.0", "seeAlso": [ - "https://gitlab.isc.org/isc-projects/bind9/blob/master/COPYRIGHT#L366" + "https://creativecommons.org/licenses/by-nc-sa/3.0/legalcode" ], "isOsiApproved": false }, { - "reference": "./JSON.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/JSON.json", - "referenceNumber": "372", - "name": "JSON License", - "licenseId": "JSON", + "reference": "https://spdx.org/licenses/GPL-2.0-with-autoconf-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-2.0-with-autoconf-exception.json", + "referenceNumber": 327, + "name": "GNU General Public License v2.0 w/Autoconf exception", + "licenseId": "GPL-2.0-with-autoconf-exception", "seeAlso": [ - "http://www.json.org/license.html" + "http://ac-archive.sourceforge.net/doc/copyright.html" ], "isOsiApproved": false }, { - "reference": "./JasPer-2.0.html", + "reference": "https://spdx.org/licenses/HPND-sell-variant.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/JasPer-2.0.json", - "referenceNumber": "239", - "name": "JasPer License", - "licenseId": "JasPer-2.0", + "detailsUrl": "https://spdx.org/licenses/HPND-sell-variant.json", + "referenceNumber": 328, + "name": "Historical Permission Notice and Disclaimer - sell variant", + "licenseId": "HPND-sell-variant", "seeAlso": [ - "http://www.ece.uvic.ca/~mdadams/jasper/LICENSE" + "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/sunrpc/auth_gss/gss_generic_token.c?h\u003dv4.19" ], "isOsiApproved": false }, { - "reference": "./LAL-1.2.html", + "reference": "https://spdx.org/licenses/CC-BY-ND-2.5.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LAL-1.2.json", - "referenceNumber": "380", - "name": "Licence Art Libre 1.2", - "licenseId": "LAL-1.2", + "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-2.5.json", + "referenceNumber": 329, + "name": "Creative Commons Attribution No Derivatives 2.5 Generic", + "licenseId": "CC-BY-ND-2.5", "seeAlso": [ - "http://artlibre.org/licence/lal/licence-art-libre-12/" + "https://creativecommons.org/licenses/by-nd/2.5/legalcode" + ], + "isOsiApproved": false, + "isFsfLibre": false + }, + { + "reference": "https://spdx.org/licenses/JPNIC.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/JPNIC.json", + "referenceNumber": 330, + "name": "Japan Network Information Center License", + "licenseId": "JPNIC", + "seeAlso": [ + "https://gitlab.isc.org/isc-projects/bind9/blob/master/COPYRIGHT#L366" ], "isOsiApproved": false }, { - "reference": "./LAL-1.3.html", + "reference": "https://spdx.org/licenses/CC-BY-2.5.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LAL-1.3.json", - "referenceNumber": "156", - "name": "Licence Art Libre 1.3", - "licenseId": "LAL-1.3", + "detailsUrl": "https://spdx.org/licenses/CC-BY-2.5.json", + "referenceNumber": 331, + "name": "Creative Commons Attribution 2.5 Generic", + "licenseId": "CC-BY-2.5", "seeAlso": [ - "http://artlibre.org/" + "https://creativecommons.org/licenses/by/2.5/legalcode" ], "isOsiApproved": false }, { - "reference": "./LGPL-2.0.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.0.json", - "referenceNumber": "268", - "name": "GNU Library General Public License v2 only", - "licenseId": "LGPL-2.0", + "reference": "https://spdx.org/licenses/Apache-1.1.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Apache-1.1.json", + "referenceNumber": 332, + "name": "Apache License 1.1", + "licenseId": "Apache-1.1", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" + "http://apache.org/licenses/LICENSE-1.1", + "https://opensource.org/licenses/Apache-1.1" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./LGPL-2.0+.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.0+.json", - "referenceNumber": "52", - "name": "GNU Library General Public License v2 or later", - "licenseId": "LGPL-2.0+", + "reference": "https://spdx.org/licenses/Parity-7.0.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Parity-7.0.0.json", + "referenceNumber": 333, + "name": "The Parity Public License 7.0.0", + "licenseId": "Parity-7.0.0", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" + "https://paritylicense.com/versions/7.0.0.html" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./LGPL-2.0-only.html", + "reference": "https://spdx.org/licenses/OGC-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.0-only.json", - "referenceNumber": "276", - "name": "GNU Library General Public License v2 only", - "licenseId": "LGPL-2.0-only", + "detailsUrl": "https://spdx.org/licenses/OGC-1.0.json", + "referenceNumber": 334, + "name": "OGC Software License, Version 1.0", + "licenseId": "OGC-1.0", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" + "https://www.ogc.org/ogc/software/1.0" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./LGPL-2.0-or-later.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-3.0-DE.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.0-or-later.json", - "referenceNumber": "217", - "name": "GNU Library General Public License v2 or later", - "licenseId": "LGPL-2.0-or-later", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-3.0-DE.json", + "referenceNumber": 335, + "name": "Creative Commons Attribution Non Commercial Share Alike 3.0 Germany", + "licenseId": "CC-BY-NC-SA-3.0-DE", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" + "https://creativecommons.org/licenses/by-nc-sa/3.0/de/legalcode" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./LGPL-2.1.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.1.json", - "referenceNumber": "166", - "name": "GNU Lesser General Public License v2.1 only", - "licenseId": "LGPL-2.1", + "reference": "https://spdx.org/licenses/CERN-OHL-1.2.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CERN-OHL-1.2.json", + "referenceNumber": 336, + "name": "CERN Open Hardware Licence v1.2", + "licenseId": "CERN-OHL-1.2", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", - "https://opensource.org/licenses/LGPL-2.1" + "https://www.ohwr.org/project/licenses/wikis/cern-ohl-v1.2" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./LGPL-2.1+.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.1+.json", - "referenceNumber": "64", - "name": "GNU Library General Public License v2.1 or later", - "licenseId": "LGPL-2.1+", + "reference": "https://spdx.org/licenses/Entessa.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Entessa.json", + "referenceNumber": 337, + "name": "Entessa Public License v1.0", + "licenseId": "Entessa", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", - "https://opensource.org/licenses/LGPL-2.1" + "https://opensource.org/licenses/Entessa" ], "isOsiApproved": true }, { - "reference": "./LGPL-2.1-only.html", + "reference": "https://spdx.org/licenses/GPL-3.0-or-later.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.1-only.json", - "referenceNumber": "2", - "name": "GNU Lesser General Public License v2.1 only", - "licenseId": "LGPL-2.1-only", + "detailsUrl": "https://spdx.org/licenses/GPL-3.0-or-later.json", + "referenceNumber": 338, + "name": "GNU General Public License v3.0 or later", + "licenseId": "GPL-3.0-or-later", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", - "https://opensource.org/licenses/LGPL-2.1" + "https://www.gnu.org/licenses/gpl-3.0-standalone.html", + "https://opensource.org/licenses/GPL-3.0" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./LGPL-2.1-or-later.html", + "reference": "https://spdx.org/licenses/FTL.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-2.1-or-later.json", - "referenceNumber": "338", - "name": "GNU Lesser General Public License v2.1 or later", - "licenseId": "LGPL-2.1-or-later", + "detailsUrl": "https://spdx.org/licenses/FTL.json", + "referenceNumber": 339, + "name": "Freetype Project License", + "licenseId": "FTL", "seeAlso": [ - "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", - "https://opensource.org/licenses/LGPL-2.1" + "http://freetype.fis.uniroma2.it/FTL.TXT", + "http://git.savannah.gnu.org/cgit/freetype/freetype2.git/tree/docs/FTL.TXT", + "http://gitlab.freedesktop.org/freetype/freetype/-/raw/master/docs/FTL.TXT" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./LGPL-3.0.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-3.0.json", - "referenceNumber": "210", - "name": "GNU Lesser General Public License v3.0 only", - "licenseId": "LGPL-3.0", + "reference": "https://spdx.org/licenses/PostgreSQL.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/PostgreSQL.json", + "referenceNumber": 340, + "name": "PostgreSQL License", + "licenseId": "PostgreSQL", "seeAlso": [ - "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", - "https://opensource.org/licenses/LGPL-3.0" + "http://www.postgresql.org/about/licence", + "https://opensource.org/licenses/PostgreSQL" ], "isOsiApproved": true }, { - "reference": "./LGPL-3.0+.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-3.0+.json", - "referenceNumber": "152", - "name": "GNU Lesser General Public License v3.0 or later", - "licenseId": "LGPL-3.0+", + "reference": "https://spdx.org/licenses/CC-BY-3.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0.json", + "referenceNumber": 341, + "name": "Creative Commons Attribution 3.0 Unported", + "licenseId": "CC-BY-3.0", "seeAlso": [ - "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", - "https://opensource.org/licenses/LGPL-3.0" + "https://creativecommons.org/licenses/by/3.0/legalcode" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./LGPL-3.0-only.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.5.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-3.0-only.json", - "referenceNumber": "254", - "name": "GNU Lesser General Public License v3.0 only", - "licenseId": "LGPL-3.0-only", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.5.json", + "referenceNumber": 342, + "name": "Creative Commons Attribution Non Commercial Share Alike 2.5 Generic", + "licenseId": "CC-BY-NC-SA-2.5", "seeAlso": [ - "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", - "https://opensource.org/licenses/LGPL-3.0" + "https://creativecommons.org/licenses/by-nc-sa/2.5/legalcode" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./LGPL-3.0-or-later.html", + "reference": "https://spdx.org/licenses/OCLC-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LGPL-3.0-or-later.json", - "referenceNumber": "301", - "name": "GNU Lesser General Public License v3.0 or later", - "licenseId": "LGPL-3.0-or-later", + "detailsUrl": "https://spdx.org/licenses/OCLC-2.0.json", + "referenceNumber": 343, + "name": "OCLC Research Public License 2.0", + "licenseId": "OCLC-2.0", "seeAlso": [ - "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", - "https://opensource.org/licenses/LGPL-3.0" + "http://www.oclc.org/research/activities/software/license/v2final.htm", + "https://opensource.org/licenses/OCLC-2.0" ], "isOsiApproved": true }, { - "reference": "./LGPLLR.html", + "reference": "https://spdx.org/licenses/Knuth-CTAN.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LGPLLR.json", - "referenceNumber": "103", - "name": "Lesser General Public License For Linguistic Resources", - "licenseId": "LGPLLR", + "detailsUrl": "https://spdx.org/licenses/Knuth-CTAN.json", + "referenceNumber": 344, + "name": "Knuth CTAN License", + "licenseId": "Knuth-CTAN", "seeAlso": [ - "http://www-igm.univ-mlv.fr/~unitex/lgpllr.html" + "https://ctan.org/license/knuth" ], "isOsiApproved": false }, { - "reference": "./LPL-1.0.html", + "reference": "https://spdx.org/licenses/BSD-3-Clause-Open-MPI.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LPL-1.0.json", - "referenceNumber": "89", - "name": "Lucent Public License Version 1.0", - "licenseId": "LPL-1.0", + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Open-MPI.json", + "referenceNumber": 345, + "name": "BSD 3-Clause Open MPI variant", + "licenseId": "BSD-3-Clause-Open-MPI", "seeAlso": [ - "https://opensource.org/licenses/LPL-1.0" + "https://www.open-mpi.org/community/license.php", + "http://www.netlib.org/lapack/LICENSE.txt" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./LPL-1.02.html", + "reference": "https://spdx.org/licenses/CECILL-B.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LPL-1.02.json", - "referenceNumber": "131", - "name": "Lucent Public License v1.02", - "licenseId": "LPL-1.02", + "detailsUrl": "https://spdx.org/licenses/CECILL-B.json", + "referenceNumber": 346, + "name": "CeCILL-B Free Software License Agreement", + "licenseId": "CECILL-B", "seeAlso": [ - "http://plan9.bell-labs.com/plan9/license.html", - "https://opensource.org/licenses/LPL-1.02" + "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./LPPL-1.0.html", + "reference": "https://spdx.org/licenses/Abstyles.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LPPL-1.0.json", - "referenceNumber": "259", - "name": "LaTeX Project Public License v1.0", - "licenseId": "LPPL-1.0", + "detailsUrl": "https://spdx.org/licenses/Abstyles.json", + "referenceNumber": 347, + "name": "Abstyles License", + "licenseId": "Abstyles", "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-0.txt" + "https://fedoraproject.org/wiki/Licensing/Abstyles" ], "isOsiApproved": false }, { - "reference": "./LPPL-1.1.html", + "reference": "https://spdx.org/licenses/xpp.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LPPL-1.1.json", - "referenceNumber": "309", - "name": "LaTeX Project Public License v1.1", - "licenseId": "LPPL-1.1", + "detailsUrl": "https://spdx.org/licenses/xpp.json", + "referenceNumber": 348, + "name": "XPP License", + "licenseId": "xpp", "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-1.txt" + "https://fedoraproject.org/wiki/Licensing/xpp" ], "isOsiApproved": false }, { - "reference": "./LPPL-1.2.html", + "reference": "https://spdx.org/licenses/FSFAP.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LPPL-1.2.json", - "referenceNumber": "392", - "name": "LaTeX Project Public License v1.2", - "licenseId": "LPPL-1.2", + "detailsUrl": "https://spdx.org/licenses/FSFAP.json", + "referenceNumber": 349, + "name": "FSF All Permissive License", + "licenseId": "FSFAP", "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-2.txt" + "https://www.gnu.org/prep/maintain/html_node/License-Notices-for-Other-Files.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/HaskellReport.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/HaskellReport.json", + "referenceNumber": 350, + "name": "Haskell Language Report License", + "licenseId": "HaskellReport", + "seeAlso": [ + "https://fedoraproject.org/wiki/Licensing/Haskell_Language_Report_License" ], "isOsiApproved": false }, { - "reference": "./LPPL-1.3a.html", + "reference": "https://spdx.org/licenses/X11-distribute-modifications-variant.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/LPPL-1.3a.json", - "referenceNumber": "305", - "name": "LaTeX Project Public License v1.3a", - "licenseId": "LPPL-1.3a", + "detailsUrl": "https://spdx.org/licenses/X11-distribute-modifications-variant.json", + "referenceNumber": 351, + "name": "X11 License Distribution Modification Variant", + "licenseId": "X11-distribute-modifications-variant", "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-3a.txt" + "https://github.com/mirror/ncurses/blob/master/COPYING" ], "isOsiApproved": false }, { - "reference": "./LPPL-1.3c.html", + "reference": "https://spdx.org/licenses/BSD-2-Clause-Patent.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LPPL-1.3c.json", - "referenceNumber": "326", - "name": "LaTeX Project Public License v1.3c", - "licenseId": "LPPL-1.3c", + "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-Patent.json", + "referenceNumber": 352, + "name": "BSD-2-Clause Plus Patent License", + "licenseId": "BSD-2-Clause-Patent", "seeAlso": [ - "http://www.latex-project.org/lppl/lppl-1-3c.txt", - "https://opensource.org/licenses/LPPL-1.3c" + "https://opensource.org/licenses/BSDplusPatent" ], "isOsiApproved": true }, { - "reference": "./Latex2e.html", + "reference": "https://spdx.org/licenses/NIST-PD-fallback.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Latex2e.json", - "referenceNumber": "283", - "name": "Latex2e License", - "licenseId": "Latex2e", + "detailsUrl": "https://spdx.org/licenses/NIST-PD-fallback.json", + "referenceNumber": 353, + "name": "NIST Public Domain Notice with license fallback", + "licenseId": "NIST-PD-fallback", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Latex2e" + "https://github.com/usnistgov/jsip/blob/59700e6926cbe96c5cdae897d9a7d2656b42abe3/LICENSE", + "https://github.com/usnistgov/fipy/blob/86aaa5c2ba2c6f1be19593c5986071cf6568cc34/LICENSE.rst" ], "isOsiApproved": false }, { - "reference": "./Leptonica.html", + "reference": "https://spdx.org/licenses/Bitstream-Vera.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Leptonica.json", - "referenceNumber": "159", - "name": "Leptonica License", - "licenseId": "Leptonica", + "detailsUrl": "https://spdx.org/licenses/Bitstream-Vera.json", + "referenceNumber": 354, + "name": "Bitstream Vera Font License", + "licenseId": "Bitstream-Vera", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Leptonica" + "https://web.archive.org/web/20080207013128/http://www.gnome.org/fonts/", + "https://docubrain.com/sites/default/files/licenses/bitstream-vera.html" ], "isOsiApproved": false }, { - "reference": "./LiLiQ-P-1.1.html", + "reference": "https://spdx.org/licenses/OGL-Canada-2.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LiLiQ-P-1.1.json", - "referenceNumber": "379", - "name": "Licence Libre du Québec – Permissive version 1.1", - "licenseId": "LiLiQ-P-1.1", + "detailsUrl": "https://spdx.org/licenses/OGL-Canada-2.0.json", + "referenceNumber": 355, + "name": "Open Government Licence - Canada", + "licenseId": "OGL-Canada-2.0", "seeAlso": [ - "https://forge.gouv.qc.ca/licence/fr/liliq-v1-1/", - "http://opensource.org/licenses/LiLiQ-P-1.1" + "https://open.canada.ca/en/open-government-licence-canada" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./LiLiQ-R-1.1.html", + "reference": "https://spdx.org/licenses/LAL-1.2.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LiLiQ-R-1.1.json", - "referenceNumber": "286", - "name": "Licence Libre du Québec – Réciprocité version 1.1", - "licenseId": "LiLiQ-R-1.1", + "detailsUrl": "https://spdx.org/licenses/LAL-1.2.json", + "referenceNumber": 356, + "name": "Licence Art Libre 1.2", + "licenseId": "LAL-1.2", "seeAlso": [ - "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-liliq-r-v1-1/", - "http://opensource.org/licenses/LiLiQ-R-1.1" + "http://artlibre.org/licence/lal/licence-art-libre-12/" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./LiLiQ-Rplus-1.1.html", + "reference": "https://spdx.org/licenses/LGPL-2.1-only.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/LiLiQ-Rplus-1.1.json", - "referenceNumber": "139", - "name": "Licence Libre du Québec – Réciprocité forte version 1.1", - "licenseId": "LiLiQ-Rplus-1.1", + "detailsUrl": "https://spdx.org/licenses/LGPL-2.1-only.json", + "referenceNumber": 357, + "name": "GNU Lesser General Public License v2.1 only", + "licenseId": "LGPL-2.1-only", "seeAlso": [ - "https://www.forge.gouv.qc.ca/participez/licence-logicielle/licence-libre-du-quebec-liliq-en-francais/licence-libre-du-quebec-reciprocite-forte-liliq-r-v1-1/", - "http://opensource.org/licenses/LiLiQ-Rplus-1.1" + "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", + "https://opensource.org/licenses/LGPL-2.1" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./Libpng.html", + "reference": "https://spdx.org/licenses/CNRI-Python-GPL-Compatible.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Libpng.json", - "referenceNumber": "101", - "name": "libpng License", - "licenseId": "Libpng", + "detailsUrl": "https://spdx.org/licenses/CNRI-Python-GPL-Compatible.json", + "referenceNumber": 358, + "name": "CNRI Python Open Source GPL Compatible License Agreement", + "licenseId": "CNRI-Python-GPL-Compatible", "seeAlso": [ - "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt" + "http://www.python.org/download/releases/1.6.1/download_win/" ], "isOsiApproved": false }, { - "reference": "./Linux-OpenIB.html", + "reference": "https://spdx.org/licenses/CC-BY-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Linux-OpenIB.json", - "referenceNumber": "5", - "name": "Linux Kernel Variant of OpenIB.org license", - "licenseId": "Linux-OpenIB", + "detailsUrl": "https://spdx.org/licenses/CC-BY-1.0.json", + "referenceNumber": 359, + "name": "Creative Commons Attribution 1.0 Generic", + "licenseId": "CC-BY-1.0", "seeAlso": [ - "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/infiniband/core/sa.h" + "https://creativecommons.org/licenses/by/1.0/legalcode" ], "isOsiApproved": false }, { - "reference": "./MIT.html", + "reference": "https://spdx.org/licenses/Zed.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/MIT.json", - "referenceNumber": "201", - "name": "MIT License", - "licenseId": "MIT", + "detailsUrl": "https://spdx.org/licenses/Zed.json", + "referenceNumber": 360, + "name": "Zed License", + "licenseId": "Zed", "seeAlso": [ - "https://opensource.org/licenses/MIT" + "https://fedoraproject.org/wiki/Licensing/Zed" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./MIT-0.html", + "reference": "https://spdx.org/licenses/SunPro.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MIT-0.json", - "referenceNumber": "6", - "name": "MIT No Attribution", - "licenseId": "MIT-0", + "detailsUrl": "https://spdx.org/licenses/SunPro.json", + "referenceNumber": 361, + "name": "SunPro License", + "licenseId": "SunPro", "seeAlso": [ - "https://github.com/aws/mit-0", - "https://romanrm.net/mit-zero", - "https://github.com/awsdocs/aws-cloud9-user-guide/blob/master/LICENSE-SAMPLECODE" + "https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_acosh.c", + "https://github.com/freebsd/freebsd-src/blob/main/lib/msun/src/e_lgammal.c" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./MIT-CMU.html", + "reference": "https://spdx.org/licenses/TMate.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MIT-CMU.json", - "referenceNumber": "9", - "name": "CMU License", - "licenseId": "MIT-CMU", + "detailsUrl": "https://spdx.org/licenses/TMate.json", + "referenceNumber": 362, + "name": "TMate Open Source License", + "licenseId": "TMate", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing:MIT?rd\u003dLicensing/MIT#CMU_Style", - "https://github.com/python-pillow/Pillow/blob/fffb426092c8db24a5f4b6df243a8a3c01fb63cd/LICENSE" + "http://svnkit.com/license.html" ], "isOsiApproved": false }, { - "reference": "./MIT-advertising.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MIT-advertising.json", - "referenceNumber": "8", - "name": "Enlightenment License (e16)", - "licenseId": "MIT-advertising", + "reference": "https://spdx.org/licenses/GPL-3.0-with-GCC-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-3.0-with-GCC-exception.json", + "referenceNumber": 363, + "name": "GNU General Public License v3.0 w/GCC Runtime Library exception", + "licenseId": "GPL-3.0-with-GCC-exception", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT_With_Advertising" + "https://www.gnu.org/licenses/gcc-exception-3.1.html" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./MIT-enna.html", + "reference": "https://spdx.org/licenses/ANTLR-PD-fallback.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MIT-enna.json", - "referenceNumber": "25", - "name": "enna License", - "licenseId": "MIT-enna", + "detailsUrl": "https://spdx.org/licenses/ANTLR-PD-fallback.json", + "referenceNumber": 364, + "name": "ANTLR Software Rights Notice with license fallback", + "licenseId": "ANTLR-PD-fallback", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT#enna" + "http://www.antlr2.org/license.html" ], "isOsiApproved": false }, { - "reference": "./MIT-feh.html", + "reference": "https://spdx.org/licenses/COIL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MIT-feh.json", - "referenceNumber": "38", - "name": "feh License", - "licenseId": "MIT-feh", + "detailsUrl": "https://spdx.org/licenses/COIL-1.0.json", + "referenceNumber": 365, + "name": "Copyfree Open Innovation License", + "licenseId": "COIL-1.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT#feh" + "https://coil.apotheon.org/plaintext/01.0.txt" ], "isOsiApproved": false }, { - "reference": "./MITNFA.html", + "reference": "https://spdx.org/licenses/MIT-Wu.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MITNFA.json", - "referenceNumber": "294", - "name": "MIT +no-false-attribs license", - "licenseId": "MITNFA", + "detailsUrl": "https://spdx.org/licenses/MIT-Wu.json", + "referenceNumber": 366, + "name": "MIT Tom Wu Variant", + "licenseId": "MIT-Wu", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MITNFA" + "https://github.com/chromium/octane/blob/master/crypto.js" ], "isOsiApproved": false }, { - "reference": "./MPL-1.0.html", + "reference": "https://spdx.org/licenses/MITNFA.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MPL-1.0.json", - "referenceNumber": "49", - "name": "Mozilla Public License 1.0", - "licenseId": "MPL-1.0", + "detailsUrl": "https://spdx.org/licenses/MITNFA.json", + "referenceNumber": 367, + "name": "MIT +no-false-attribs license", + "licenseId": "MITNFA", "seeAlso": [ - "http://www.mozilla.org/MPL/MPL-1.0.html", - "https://opensource.org/licenses/MPL-1.0" + "https://fedoraproject.org/wiki/Licensing/MITNFA" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./MPL-1.1.html", + "reference": "https://spdx.org/licenses/MIT-open-group.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/MPL-1.1.json", - "referenceNumber": "304", - "name": "Mozilla Public License 1.1", - "licenseId": "MPL-1.1", + "detailsUrl": "https://spdx.org/licenses/MIT-open-group.json", + "referenceNumber": 368, + "name": "MIT Open Group variant", + "licenseId": "MIT-open-group", "seeAlso": [ - "http://www.mozilla.org/MPL/MPL-1.1.html", - "https://opensource.org/licenses/MPL-1.1" + "https://gitlab.freedesktop.org/xorg/app/iceauth/-/blob/master/COPYING", + "https://gitlab.freedesktop.org/xorg/app/xvinfo/-/blob/master/COPYING", + "https://gitlab.freedesktop.org/xorg/app/xsetroot/-/blob/master/COPYING", + "https://gitlab.freedesktop.org/xorg/app/xauth/-/blob/master/COPYING" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./MPL-2.0.html", + "reference": "https://spdx.org/licenses/GFDL-1.1-or-later.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/MPL-2.0.json", - "referenceNumber": "234", - "name": "Mozilla Public License 2.0", - "licenseId": "MPL-2.0", + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-or-later.json", + "referenceNumber": 369, + "name": "GNU Free Documentation License v1.1 or later", + "licenseId": "GFDL-1.1-or-later", "seeAlso": [ - "http://www.mozilla.org/MPL/2.0/", - "https://opensource.org/licenses/MPL-2.0" + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./MPL-2.0-no-copyleft-exception.html", + "reference": "https://spdx.org/licenses/AGPL-1.0-or-later.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MPL-2.0-no-copyleft-exception.json", - "referenceNumber": "303", - "name": "Mozilla Public License 2.0 (no copyleft exception)", - "licenseId": "MPL-2.0-no-copyleft-exception", + "detailsUrl": "https://spdx.org/licenses/AGPL-1.0-or-later.json", + "referenceNumber": 370, + "name": "Affero General Public License v1.0 or later", + "licenseId": "AGPL-1.0-or-later", "seeAlso": [ - "http://www.mozilla.org/MPL/2.0/", - "https://opensource.org/licenses/MPL-2.0" + "http://www.affero.org/oagpl.html" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./MS-PL.html", + "reference": "https://spdx.org/licenses/Latex2e.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/MS-PL.json", - "referenceNumber": "336", - "name": "Microsoft Public License", - "licenseId": "MS-PL", + "detailsUrl": "https://spdx.org/licenses/Latex2e.json", + "referenceNumber": 371, + "name": "Latex2e License", + "licenseId": "Latex2e", "seeAlso": [ - "http://www.microsoft.com/opensource/licenses.mspx", - "https://opensource.org/licenses/MS-PL" + "https://fedoraproject.org/wiki/Licensing/Latex2e" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./MS-RL.html", + "reference": "https://spdx.org/licenses/0BSD.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/MS-RL.json", - "referenceNumber": "280", - "name": "Microsoft Reciprocal License", - "licenseId": "MS-RL", + "detailsUrl": "https://spdx.org/licenses/0BSD.json", + "referenceNumber": 372, + "name": "BSD Zero Clause License", + "licenseId": "0BSD", "seeAlso": [ - "http://www.microsoft.com/opensource/licenses.mspx", - "https://opensource.org/licenses/MS-RL" + "http://landley.net/toybox/license.html", + "https://opensource.org/licenses/0BSD" ], "isOsiApproved": true }, { - "reference": "./MTLL.html", + "reference": "https://spdx.org/licenses/BSD-Advertising-Acknowledgement.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MTLL.json", - "referenceNumber": "181", - "name": "Matrix Template Library License", - "licenseId": "MTLL", + "detailsUrl": "https://spdx.org/licenses/BSD-Advertising-Acknowledgement.json", + "referenceNumber": 373, + "name": "BSD Advertising Acknowledgement License", + "licenseId": "BSD-Advertising-Acknowledgement", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Matrix_Template_Library_License" + "https://github.com/python-excel/xlrd/blob/master/LICENSE#L33" ], "isOsiApproved": false }, { - "reference": "./MakeIndex.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MakeIndex.json", - "referenceNumber": "187", - "name": "MakeIndex License", - "licenseId": "MakeIndex", + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-2.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-2.0.json", + "referenceNumber": 374, + "name": "Creative Commons Attribution Non Commercial No Derivatives 2.0 Generic", + "licenseId": "CC-BY-NC-ND-2.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MakeIndex" + "https://creativecommons.org/licenses/by-nc-nd/2.0/legalcode" ], "isOsiApproved": false }, { - "reference": "./MirOS.html", + "reference": "https://spdx.org/licenses/BSD-3-Clause-LBNL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/MirOS.json", - "referenceNumber": "299", - "name": "MirOS License", - "licenseId": "MirOS", + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-LBNL.json", + "referenceNumber": 375, + "name": "Lawrence Berkeley National Labs BSD variant license", + "licenseId": "BSD-3-Clause-LBNL", "seeAlso": [ - "https://opensource.org/licenses/MirOS" + "https://fedoraproject.org/wiki/Licensing/LBNLBSD" ], "isOsiApproved": true }, { - "reference": "./Motosoto.html", + "reference": "https://spdx.org/licenses/MPL-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Motosoto.json", - "referenceNumber": "317", - "name": "Motosoto License", - "licenseId": "Motosoto", + "detailsUrl": "https://spdx.org/licenses/MPL-1.1.json", + "referenceNumber": 376, + "name": "Mozilla Public License 1.1", + "licenseId": "MPL-1.1", "seeAlso": [ - "https://opensource.org/licenses/Motosoto" + "http://www.mozilla.org/MPL/MPL-1.1.html", + "https://opensource.org/licenses/MPL-1.1" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./Multics.html", + "reference": "https://spdx.org/licenses/libutil-David-Nugent.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Multics.json", - "referenceNumber": "63", - "name": "Multics License", - "licenseId": "Multics", + "detailsUrl": "https://spdx.org/licenses/libutil-David-Nugent.json", + "referenceNumber": 377, + "name": "libutil David Nugent License", + "licenseId": "libutil-David-Nugent", "seeAlso": [ - "https://opensource.org/licenses/Multics" + "http://web.mit.edu/freebsd/head/lib/libutil/login_ok.3", + "https://cgit.freedesktop.org/libbsd/tree/man/setproctitle.3bsd" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./Mup.html", + "reference": "https://spdx.org/licenses/BUSL-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Mup.json", - "referenceNumber": "353", - "name": "Mup License", - "licenseId": "Mup", + "detailsUrl": "https://spdx.org/licenses/BUSL-1.1.json", + "referenceNumber": 378, + "name": "Business Source License 1.1", + "licenseId": "BUSL-1.1", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Mup" + "https://mariadb.com/bsl11/" ], "isOsiApproved": false }, { - "reference": "./NASA-1.3.html", + "reference": "https://spdx.org/licenses/LiLiQ-P-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NASA-1.3.json", - "referenceNumber": "87", - "name": "NASA Open Source Agreement 1.3", - "licenseId": "NASA-1.3", + "detailsUrl": "https://spdx.org/licenses/LiLiQ-P-1.1.json", + "referenceNumber": 379, + "name": "Licence Libre du Québec – Permissive version 1.1", + "licenseId": "LiLiQ-P-1.1", "seeAlso": [ - "http://ti.arc.nasa.gov/opensource/nosa/", - "https://opensource.org/licenses/NASA-1.3" + "https://forge.gouv.qc.ca/licence/fr/liliq-v1-1/", + "http://opensource.org/licenses/LiLiQ-P-1.1" ], "isOsiApproved": true }, { - "reference": "./NBPL-1.0.html", + "reference": "https://spdx.org/licenses/MPL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NBPL-1.0.json", - "referenceNumber": "361", - "name": "Net Boolean Public License v1", - "licenseId": "NBPL-1.0", + "detailsUrl": "https://spdx.org/licenses/MPL-1.0.json", + "referenceNumber": 380, + "name": "Mozilla Public License 1.0", + "licenseId": "MPL-1.0", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d37b4b3f6cc4bf34e1d3dec61e69914b9819d8894" + "http://www.mozilla.org/MPL/MPL-1.0.html", + "https://opensource.org/licenses/MPL-1.0" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./NCSA.html", + "reference": "https://spdx.org/licenses/Clips.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/NCSA.json", - "referenceNumber": "58", - "name": "University of Illinois/NCSA Open Source License", - "licenseId": "NCSA", + "detailsUrl": "https://spdx.org/licenses/Clips.json", + "referenceNumber": 381, + "name": "Clips License", + "licenseId": "Clips", "seeAlso": [ - "http://otm.illinois.edu/uiuc_openSource", - "https://opensource.org/licenses/NCSA" + "https://github.com/DrItanium/maya/blob/master/LICENSE.CLIPS" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./NGPL.html", + "reference": "https://spdx.org/licenses/HPND-export-US.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NGPL.json", - "referenceNumber": "71", - "name": "Nethack General Public License", - "licenseId": "NGPL", + "detailsUrl": "https://spdx.org/licenses/HPND-export-US.json", + "referenceNumber": 382, + "name": "HPND with US Government export control warning", + "licenseId": "HPND-export-US", "seeAlso": [ - "https://opensource.org/licenses/NGPL" + "https://www.kermitproject.org/ck90.html#source" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./NLOD-1.0.html", + "reference": "https://spdx.org/licenses/OLDAP-1.4.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NLOD-1.0.json", - "referenceNumber": "209", - "name": "Norwegian Licence for Open Government Data", - "licenseId": "NLOD-1.0", + "detailsUrl": "https://spdx.org/licenses/OLDAP-1.4.json", + "referenceNumber": 383, + "name": "Open LDAP Public License v1.4", + "licenseId": "OLDAP-1.4", "seeAlso": [ - "http://data.norge.no/nlod/en/1.0" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dc9f95c2f3f2ffb5e0ae55fe7388af75547660941" ], "isOsiApproved": false }, { - "reference": "./NLPL.html", + "reference": "https://spdx.org/licenses/OLDAP-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NLPL.json", - "referenceNumber": "344", - "name": "No Limit Public License", - "licenseId": "NLPL", + "detailsUrl": "https://spdx.org/licenses/OLDAP-1.1.json", + "referenceNumber": 384, + "name": "Open LDAP Public License v1.1", + "licenseId": "OLDAP-1.1", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/NLPL" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d806557a5ad59804ef3a44d5abfbe91d706b0791f" ], "isOsiApproved": false }, { - "reference": "./NOSL.html", + "reference": "https://spdx.org/licenses/DL-DE-BY-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/NOSL.json", - "referenceNumber": "383", - "name": "Netizen Open Source License", - "licenseId": "NOSL", + "detailsUrl": "https://spdx.org/licenses/DL-DE-BY-2.0.json", + "referenceNumber": 385, + "name": "Data licence Germany – attribution – version 2.0", + "licenseId": "DL-DE-BY-2.0", "seeAlso": [ - "http://bits.netizen.com.au/licenses/NOSL/nosl.txt" + "https://www.govdata.de/dl-de/by-2-0" ], "isOsiApproved": false }, { - "reference": "./NPL-1.0.html", + "reference": "https://spdx.org/licenses/HTMLTIDY.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/NPL-1.0.json", - "referenceNumber": "328", - "name": "Netscape Public License v1.0", - "licenseId": "NPL-1.0", + "detailsUrl": "https://spdx.org/licenses/HTMLTIDY.json", + "referenceNumber": 386, + "name": "HTML Tidy License", + "licenseId": "HTMLTIDY", "seeAlso": [ - "http://www.mozilla.org/MPL/NPL/1.0/" + "https://github.com/htacg/tidy-html5/blob/next/README/LICENSE.md" ], "isOsiApproved": false }, { - "reference": "./NPL-1.1.html", + "reference": "https://spdx.org/licenses/GPL-1.0-only.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/NPL-1.1.json", - "referenceNumber": "185", - "name": "Netscape Public License v1.1", - "licenseId": "NPL-1.1", + "detailsUrl": "https://spdx.org/licenses/GPL-1.0-only.json", + "referenceNumber": 387, + "name": "GNU General Public License v1.0 only", + "licenseId": "GPL-1.0-only", "seeAlso": [ - "http://www.mozilla.org/MPL/NPL/1.1/" + "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" ], "isOsiApproved": false }, { - "reference": "./NPOSL-3.0.html", + "reference": "https://spdx.org/licenses/EFL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NPOSL-3.0.json", - "referenceNumber": "222", - "name": "Non-Profit Open Software License 3.0", - "licenseId": "NPOSL-3.0", + "detailsUrl": "https://spdx.org/licenses/EFL-1.0.json", + "referenceNumber": 388, + "name": "Eiffel Forum License v1.0", + "licenseId": "EFL-1.0", "seeAlso": [ - "https://opensource.org/licenses/NOSL3.0" + "http://www.eiffel-nice.org/license/forum.txt", + "https://opensource.org/licenses/EFL-1.0" ], "isOsiApproved": true }, { - "reference": "./NRL.html", + "reference": "https://spdx.org/licenses/OLDAP-2.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NRL.json", - "referenceNumber": "53", - "name": "NRL License", - "licenseId": "NRL", + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.1.json", + "referenceNumber": 389, + "name": "Open LDAP Public License v2.1", + "licenseId": "OLDAP-2.1", "seeAlso": [ - "http://web.mit.edu/network/isakmp/nrllicense.html" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db0d176738e96a0d3b9f85cb51e140a86f21be715" ], "isOsiApproved": false }, { - "reference": "./NTP.html", + "reference": "https://spdx.org/licenses/libselinux-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NTP.json", - "referenceNumber": "261", - "name": "NTP License", - "licenseId": "NTP", + "detailsUrl": "https://spdx.org/licenses/libselinux-1.0.json", + "referenceNumber": 390, + "name": "libselinux public domain notice", + "licenseId": "libselinux-1.0", "seeAlso": [ - "https://opensource.org/licenses/NTP" + "https://github.com/SELinuxProject/selinux/blob/master/libselinux/LICENSE" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./Naumen.html", + "reference": "https://spdx.org/licenses/psutils.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Naumen.json", - "referenceNumber": "278", - "name": "Naumen Public License", - "licenseId": "Naumen", + "detailsUrl": "https://spdx.org/licenses/psutils.json", + "referenceNumber": 391, + "name": "psutils License", + "licenseId": "psutils", "seeAlso": [ - "https://opensource.org/licenses/Naumen" + "https://fedoraproject.org/wiki/Licensing/psutils" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./Net-SNMP.html", + "reference": "https://spdx.org/licenses/Symlinks.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Net-SNMP.json", - "referenceNumber": "284", - "name": "Net-SNMP License", - "licenseId": "Net-SNMP", + "detailsUrl": "https://spdx.org/licenses/Symlinks.json", + "referenceNumber": 392, + "name": "Symlinks License", + "licenseId": "Symlinks", "seeAlso": [ - "http://net-snmp.sourceforge.net/about/license.html" + "https://www.mail-archive.com/debian-bugs-rc@lists.debian.org/msg11494.html" ], "isOsiApproved": false }, { - "reference": "./NetCDF.html", + "reference": "https://spdx.org/licenses/GFDL-1.2-no-invariants-or-later.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/NetCDF.json", - "referenceNumber": "46", - "name": "NetCDF license", - "licenseId": "NetCDF", + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-no-invariants-or-later.json", + "referenceNumber": 393, + "name": "GNU Free Documentation License v1.2 or later - no invariants", + "licenseId": "GFDL-1.2-no-invariants-or-later", "seeAlso": [ - "http://www.unidata.ucar.edu/software/netcdf/copyright.html" + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" ], "isOsiApproved": false }, { - "reference": "./Newsletr.html", + "reference": "https://spdx.org/licenses/OLDAP-2.2.2.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Newsletr.json", - "referenceNumber": "279", - "name": "Newsletr License", - "licenseId": "Newsletr", + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.2.2.json", + "referenceNumber": 394, + "name": "Open LDAP Public License 2.2.2", + "licenseId": "OLDAP-2.2.2", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Newsletr" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003ddf2cc1e21eb7c160695f5b7cffd6296c151ba188" ], "isOsiApproved": false }, { - "reference": "./Nokia.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-4.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Nokia.json", - "referenceNumber": "327", - "name": "Nokia Open Source License", - "licenseId": "Nokia", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-4.0.json", + "referenceNumber": 395, + "name": "Creative Commons Attribution Non Commercial Share Alike 4.0 International", + "licenseId": "CC-BY-NC-SA-4.0", "seeAlso": [ - "https://opensource.org/licenses/nokia" + "https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./Noweb.html", + "reference": "https://spdx.org/licenses/Cornell-Lossless-JPEG.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Noweb.json", - "referenceNumber": "364", - "name": "Noweb License", - "licenseId": "Noweb", + "detailsUrl": "https://spdx.org/licenses/Cornell-Lossless-JPEG.json", + "referenceNumber": 396, + "name": "Cornell Lossless JPEG License", + "licenseId": "Cornell-Lossless-JPEG", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Noweb" + "https://android.googlesource.com/platform/external/dng_sdk/+/refs/heads/master/source/dng_lossless_jpeg.cpp#16", + "https://www.mssl.ucl.ac.uk/~mcrw/src/20050920/proto.h", + "https://gitlab.freedesktop.org/libopenraw/libopenraw/blob/master/lib/ljpegdecompressor.cpp#L32" ], "isOsiApproved": false }, { - "reference": "./Nunit.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Nunit.json", - "referenceNumber": "288", - "name": "Nunit License", - "licenseId": "Nunit", + "reference": "https://spdx.org/licenses/NICTA-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/NICTA-1.0.json", + "referenceNumber": 397, + "name": "NICTA Public Software License, Version 1.0", + "licenseId": "NICTA-1.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Nunit" + "https://opensource.apple.com/source/mDNSResponder/mDNSResponder-320.10/mDNSPosix/nss_ReadMe.txt" ], "isOsiApproved": false }, { - "reference": "./OCCT-PL.html", + "reference": "https://spdx.org/licenses/zlib-acknowledgement.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OCCT-PL.json", - "referenceNumber": "282", - "name": "Open CASCADE Technology Public License", - "licenseId": "OCCT-PL", + "detailsUrl": "https://spdx.org/licenses/zlib-acknowledgement.json", + "referenceNumber": 398, + "name": "zlib/libpng License with Acknowledgement", + "licenseId": "zlib-acknowledgement", "seeAlso": [ - "http://www.opencascade.com/content/occt-public-license" + "https://fedoraproject.org/wiki/Licensing/ZlibWithAcknowledgement" ], "isOsiApproved": false }, { - "reference": "./OCLC-2.0.html", + "reference": "https://spdx.org/licenses/CNRI-Python.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OCLC-2.0.json", - "referenceNumber": "111", - "name": "OCLC Research Public License 2.0", - "licenseId": "OCLC-2.0", + "detailsUrl": "https://spdx.org/licenses/CNRI-Python.json", + "referenceNumber": 399, + "name": "CNRI Python License", + "licenseId": "CNRI-Python", "seeAlso": [ - "http://www.oclc.org/research/activities/software/license/v2final.htm", - "https://opensource.org/licenses/OCLC-2.0" + "https://opensource.org/licenses/CNRI-Python" ], "isOsiApproved": true }, { - "reference": "./ODC-By-1.0.html", + "reference": "https://spdx.org/licenses/VOSTROM.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ODC-By-1.0.json", - "referenceNumber": "144", - "name": "Open Data Commons Attribution License v1.0", - "licenseId": "ODC-By-1.0", + "detailsUrl": "https://spdx.org/licenses/VOSTROM.json", + "referenceNumber": 400, + "name": "VOSTROM Public License for Open Source", + "licenseId": "VOSTROM", "seeAlso": [ - "https://opendatacommons.org/licenses/by/1.0/" + "https://fedoraproject.org/wiki/Licensing/VOSTROM" ], "isOsiApproved": false }, { - "reference": "./ODbL-1.0.html", + "reference": "https://spdx.org/licenses/Zimbra-1.3.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/ODbL-1.0.json", - "referenceNumber": "246", - "name": "ODC Open Database License v1.0", - "licenseId": "ODbL-1.0", + "detailsUrl": "https://spdx.org/licenses/Zimbra-1.3.json", + "referenceNumber": 401, + "name": "Zimbra Public License v1.3", + "licenseId": "Zimbra-1.3", "seeAlso": [ - "http://www.opendatacommons.org/licenses/odbl/1.0/" + "http://web.archive.org/web/20100302225219/http://www.zimbra.com/license/zimbra-public-license-1-3.html" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./OFL-1.0.html", + "reference": "https://spdx.org/licenses/OLDAP-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OFL-1.0.json", - "referenceNumber": "153", - "name": "SIL Open Font License 1.0", - "licenseId": "OFL-1.0", + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.0.json", + "referenceNumber": 402, + "name": "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)", + "licenseId": "OLDAP-2.0", "seeAlso": [ - "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcbf50f4e1185a21abd4c0a54d3f4341fe28f36ea" ], "isOsiApproved": false }, { - "reference": "./OFL-1.1.html", + "reference": "https://spdx.org/licenses/eGenix.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OFL-1.1.json", - "referenceNumber": "315", - "name": "SIL Open Font License 1.1", - "licenseId": "OFL-1.1", + "detailsUrl": "https://spdx.org/licenses/eGenix.json", + "referenceNumber": 403, + "name": "eGenix.com Public License 1.1.0", + "licenseId": "eGenix", "seeAlso": [ - "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL_web", - "https://opensource.org/licenses/OFL-1.1" + "http://www.egenix.com/products/eGenix.com-Public-License-1.1.0.pdf", + "https://fedoraproject.org/wiki/Licensing/eGenix.com_Public_License_1.1.0" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./OGL-UK-1.0.html", + "reference": "https://spdx.org/licenses/blessing.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OGL-UK-1.0.json", - "referenceNumber": "116", - "name": "Open Government Licence v1.0", - "licenseId": "OGL-UK-1.0", + "detailsUrl": "https://spdx.org/licenses/blessing.json", + "referenceNumber": 404, + "name": "SQLite Blessing", + "licenseId": "blessing", "seeAlso": [ - "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/1/" + "https://www.sqlite.org/src/artifact/e33a4df7e32d742a?ln\u003d4-9", + "https://sqlite.org/src/artifact/df5091916dbb40e6" ], "isOsiApproved": false }, { - "reference": "./OGL-UK-2.0.html", + "reference": "https://spdx.org/licenses/copyleft-next-0.3.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OGL-UK-2.0.json", - "referenceNumber": "289", - "name": "Open Government Licence v2.0", - "licenseId": "OGL-UK-2.0", + "detailsUrl": "https://spdx.org/licenses/copyleft-next-0.3.0.json", + "referenceNumber": 405, + "name": "copyleft-next 0.3.0", + "licenseId": "copyleft-next-0.3.0", "seeAlso": [ - "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/2/" + "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.0" ], "isOsiApproved": false }, { - "reference": "./OGL-UK-3.0.html", + "reference": "https://spdx.org/licenses/Motosoto.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OGL-UK-3.0.json", - "referenceNumber": "226", - "name": "Open Government Licence v3.0", - "licenseId": "OGL-UK-3.0", + "detailsUrl": "https://spdx.org/licenses/Motosoto.json", + "referenceNumber": 406, + "name": "Motosoto License", + "licenseId": "Motosoto", "seeAlso": [ - "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/" + "https://opensource.org/licenses/Motosoto" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./OGTSL.html", + "reference": "https://spdx.org/licenses/CC-BY-SA-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OGTSL.json", - "referenceNumber": "125", - "name": "Open Group Test Suite License", - "licenseId": "OGTSL", + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-1.0.json", + "referenceNumber": 407, + "name": "Creative Commons Attribution Share Alike 1.0 Generic", + "licenseId": "CC-BY-SA-1.0", "seeAlso": [ - "http://www.opengroup.org/testing/downloads/The_Open_Group_TSL.txt", - "https://opensource.org/licenses/OGTSL" + "https://creativecommons.org/licenses/by-sa/1.0/legalcode" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./OLDAP-1.1.html", + "reference": "https://spdx.org/licenses/OPL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-1.1.json", - "referenceNumber": "97", - "name": "Open LDAP Public License v1.1", - "licenseId": "OLDAP-1.1", + "detailsUrl": "https://spdx.org/licenses/OPL-1.0.json", + "referenceNumber": 408, + "name": "Open Public License v1.0", + "licenseId": "OPL-1.0", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d806557a5ad59804ef3a44d5abfbe91d706b0791f" + "http://old.koalateam.com/jackaroo/OPL_1_0.TXT", + "https://fedoraproject.org/wiki/Licensing/Open_Public_License" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": false }, { - "reference": "./OLDAP-1.2.html", + "reference": "https://spdx.org/licenses/OLDAP-1.2.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-1.2.json", - "referenceNumber": "190", + "detailsUrl": "https://spdx.org/licenses/OLDAP-1.2.json", + "referenceNumber": 409, "name": "Open LDAP Public License v1.2", "licenseId": "OLDAP-1.2", "seeAlso": [ @@ -3428,1547 +5153,1592 @@ "isOsiApproved": false }, { - "reference": "./OLDAP-1.3.html", + "reference": "https://spdx.org/licenses/NPL-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-1.3.json", - "referenceNumber": "106", - "name": "Open LDAP Public License v1.3", - "licenseId": "OLDAP-1.3", + "detailsUrl": "https://spdx.org/licenses/NPL-1.1.json", + "referenceNumber": 410, + "name": "Netscape Public License v1.1", + "licenseId": "NPL-1.1", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003de5f8117f0ce088d0bd7a8e18ddf37eaa40eb09b1" + "http://www.mozilla.org/MPL/NPL/1.1/" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./OLDAP-1.4.html", + "reference": "https://spdx.org/licenses/CC-BY-ND-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-1.4.json", - "referenceNumber": "30", - "name": "Open LDAP Public License v1.4", - "licenseId": "OLDAP-1.4", + "detailsUrl": "https://spdx.org/licenses/CC-BY-ND-1.0.json", + "referenceNumber": 411, + "name": "Creative Commons Attribution No Derivatives 1.0 Generic", + "licenseId": "CC-BY-ND-1.0", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dc9f95c2f3f2ffb5e0ae55fe7388af75547660941" + "https://creativecommons.org/licenses/by-nd/1.0/legalcode" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": false }, { - "reference": "./OLDAP-2.0.html", + "reference": "https://spdx.org/licenses/ZPL-2.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.0.json", - "referenceNumber": "266", - "name": "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)", - "licenseId": "OLDAP-2.0", + "detailsUrl": "https://spdx.org/licenses/ZPL-2.1.json", + "referenceNumber": 412, + "name": "Zope Public License 2.1", + "licenseId": "ZPL-2.1", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcbf50f4e1185a21abd4c0a54d3f4341fe28f36ea" + "http://old.zope.org/Resources/ZPL/" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./OLDAP-2.0.1.html", + "reference": "https://spdx.org/licenses/CATOSL-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.0.1.json", - "referenceNumber": "350", - "name": "Open LDAP Public License v2.0.1", - "licenseId": "OLDAP-2.0.1", + "detailsUrl": "https://spdx.org/licenses/CATOSL-1.1.json", + "referenceNumber": 413, + "name": "Computer Associates Trusted Open Source License 1.1", + "licenseId": "CATOSL-1.1", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db6d68acd14e51ca3aab4428bf26522aa74873f0e" + "https://opensource.org/licenses/CATOSL-1.1" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./OLDAP-2.1.html", + "reference": "https://spdx.org/licenses/Beerware.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.1.json", - "referenceNumber": "154", - "name": "Open LDAP Public License v2.1", - "licenseId": "OLDAP-2.1", + "detailsUrl": "https://spdx.org/licenses/Beerware.json", + "referenceNumber": 414, + "name": "Beerware License", + "licenseId": "Beerware", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003db0d176738e96a0d3b9f85cb51e140a86f21be715" + "https://fedoraproject.org/wiki/Licensing/Beerware", + "https://people.freebsd.org/~phk/" ], "isOsiApproved": false }, { - "reference": "./OLDAP-2.2.html", + "reference": "https://spdx.org/licenses/CFITSIO.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.json", - "referenceNumber": "362", - "name": "Open LDAP Public License v2.2", - "licenseId": "OLDAP-2.2", + "detailsUrl": "https://spdx.org/licenses/CFITSIO.json", + "referenceNumber": 415, + "name": "CFITSIO License", + "licenseId": "CFITSIO", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d470b0c18ec67621c85881b2733057fecf4a1acc3" + "https://heasarc.gsfc.nasa.gov/docs/software/fitsio/c/f_user/node9.html" ], "isOsiApproved": false }, { - "reference": "./OLDAP-2.2.1.html", + "reference": "https://spdx.org/licenses/Watcom-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.1.json", - "referenceNumber": "339", - "name": "Open LDAP Public License v2.2.1", - "licenseId": "OLDAP-2.2.1", + "detailsUrl": "https://spdx.org/licenses/Watcom-1.0.json", + "referenceNumber": 416, + "name": "Sybase Open Watcom Public License 1.0", + "licenseId": "Watcom-1.0", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d4bc786f34b50aa301be6f5600f58a980070f481e" + "https://opensource.org/licenses/Watcom-1.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": false }, { - "reference": "./OLDAP-2.2.2.html", + "reference": "https://spdx.org/licenses/MS-PL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.2.2.json", - "referenceNumber": "199", - "name": "Open LDAP Public License 2.2.2", - "licenseId": "OLDAP-2.2.2", + "detailsUrl": "https://spdx.org/licenses/MS-PL.json", + "referenceNumber": 417, + "name": "Microsoft Public License", + "licenseId": "MS-PL", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003ddf2cc1e21eb7c160695f5b7cffd6296c151ba188" + "http://www.microsoft.com/opensource/licenses.mspx", + "https://opensource.org/licenses/MS-PL" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./OLDAP-2.3.html", + "reference": "https://spdx.org/licenses/snprintf.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.3.json", - "referenceNumber": "164", - "name": "Open LDAP Public License v2.3", - "licenseId": "OLDAP-2.3", + "detailsUrl": "https://spdx.org/licenses/snprintf.json", + "referenceNumber": 418, + "name": "snprintf License", + "licenseId": "snprintf", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dd32cf54a32d581ab475d23c810b0a7fbaf8d63c3" + "https://github.com/openssh/openssh-portable/blob/master/openbsd-compat/bsd-snprintf.c#L2" ], "isOsiApproved": false }, { - "reference": "./OLDAP-2.4.html", + "reference": "https://spdx.org/licenses/Naumen.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.4.json", - "referenceNumber": "66", - "name": "Open LDAP Public License v2.4", - "licenseId": "OLDAP-2.4", + "detailsUrl": "https://spdx.org/licenses/Naumen.json", + "referenceNumber": 419, + "name": "Naumen Public License", + "licenseId": "Naumen", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dcd1284c4a91a8a380d904eee68d1583f989ed386" + "https://opensource.org/licenses/Naumen" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./OLDAP-2.5.html", + "reference": "https://spdx.org/licenses/EUPL-1.2.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.5.json", - "referenceNumber": "183", - "name": "Open LDAP Public License v2.5", - "licenseId": "OLDAP-2.5", + "detailsUrl": "https://spdx.org/licenses/EUPL-1.2.json", + "referenceNumber": 420, + "name": "European Union Public License 1.2", + "licenseId": "EUPL-1.2", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d6852b9d90022e8593c98205413380536b1b5a7cf" + "https://joinup.ec.europa.eu/page/eupl-text-11-12", + "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl_v1.2_en.pdf", + "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/2020-03/EUPL-1.2%20EN.txt", + "https://joinup.ec.europa.eu/sites/default/files/inline-files/EUPL%20v1_2%20EN(1).txt", + "http://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri\u003dCELEX:32017D0863", + "https://opensource.org/licenses/EUPL-1.2" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./OLDAP-2.6.html", + "reference": "https://spdx.org/licenses/DOC.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.6.json", - "referenceNumber": "61", - "name": "Open LDAP Public License v2.6", - "licenseId": "OLDAP-2.6", + "detailsUrl": "https://spdx.org/licenses/DOC.json", + "referenceNumber": 421, + "name": "DOC License", + "licenseId": "DOC", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d1cae062821881f41b73012ba816434897abf4205" + "http://www.cs.wustl.edu/~schmidt/ACE-copying.html", + "https://www.dre.vanderbilt.edu/~schmidt/ACE-copying.html" ], "isOsiApproved": false }, { - "reference": "./OLDAP-2.7.html", + "reference": "https://spdx.org/licenses/Artistic-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.7.json", - "referenceNumber": "123", - "name": "Open LDAP Public License v2.7", - "licenseId": "OLDAP-2.7", + "detailsUrl": "https://spdx.org/licenses/Artistic-1.0.json", + "referenceNumber": 422, + "name": "Artistic License 1.0", + "licenseId": "Artistic-1.0", "seeAlso": [ - "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d47c2415c1df81556eeb39be6cad458ef87c534a2" + "https://opensource.org/licenses/Artistic-1.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": false }, { - "reference": "./OLDAP-2.8.html", + "reference": "https://spdx.org/licenses/Imlib2.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OLDAP-2.8.json", - "referenceNumber": "37", - "name": "Open LDAP Public License v2.8", - "licenseId": "OLDAP-2.8", + "detailsUrl": "https://spdx.org/licenses/Imlib2.json", + "referenceNumber": 423, + "name": "Imlib2 License", + "licenseId": "Imlib2", "seeAlso": [ - "http://www.openldap.org/software/release/license.html" + "http://trac.enlightenment.org/e/browser/trunk/imlib2/COPYING", + "https://git.enlightenment.org/legacy/imlib2.git/tree/COPYING" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./OML.html", + "reference": "https://spdx.org/licenses/OGL-UK-2.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OML.json", - "referenceNumber": "65", - "name": "Open Market License", - "licenseId": "OML", + "detailsUrl": "https://spdx.org/licenses/OGL-UK-2.0.json", + "referenceNumber": 424, + "name": "Open Government Licence v2.0", + "licenseId": "OGL-UK-2.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Open_Market_License" + "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/2/" ], "isOsiApproved": false }, { - "reference": "./OPL-1.0.html", + "reference": "https://spdx.org/licenses/GFDL-1.3-no-invariants-only.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OPL-1.0.json", - "referenceNumber": "343", - "name": "Open Public License v1.0", - "licenseId": "OPL-1.0", + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-no-invariants-only.json", + "referenceNumber": 425, + "name": "GNU Free Documentation License v1.3 only - no invariants", + "licenseId": "GFDL-1.3-no-invariants-only", "seeAlso": [ - "http://old.koalateam.com/jackaroo/OPL_1_0.TXT", - "https://fedoraproject.org/wiki/Licensing/Open_Public_License" + "https://www.gnu.org/licenses/fdl-1.3.txt" ], "isOsiApproved": false }, { - "reference": "./OSET-PL-2.1.html", + "reference": "https://spdx.org/licenses/PolyForm-Small-Business-1.0.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/OSET-PL-2.1.json", - "referenceNumber": "291", - "name": "OSET Public License version 2.1", - "licenseId": "OSET-PL-2.1", + "detailsUrl": "https://spdx.org/licenses/PolyForm-Small-Business-1.0.0.json", + "referenceNumber": 426, + "name": "PolyForm Small Business License 1.0.0", + "licenseId": "PolyForm-Small-Business-1.0.0", "seeAlso": [ - "http://www.osetfoundation.org/public-license", - "https://opensource.org/licenses/OPL-2.1" + "https://polyformproject.org/licenses/small-business/1.0.0" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./OSL-1.0.html", + "reference": "https://spdx.org/licenses/GFDL-1.3-invariants-only.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OSL-1.0.json", - "referenceNumber": "85", - "name": "Open Software License 1.0", - "licenseId": "OSL-1.0", + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-invariants-only.json", + "referenceNumber": 427, + "name": "GNU Free Documentation License v1.3 only - invariants", + "licenseId": "GFDL-1.3-invariants-only", "seeAlso": [ - "https://opensource.org/licenses/OSL-1.0" + "https://www.gnu.org/licenses/fdl-1.3.txt" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./OSL-1.1.html", + "reference": "https://spdx.org/licenses/BlueOak-1.0.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OSL-1.1.json", - "referenceNumber": "334", - "name": "Open Software License 1.1", - "licenseId": "OSL-1.1", + "detailsUrl": "https://spdx.org/licenses/BlueOak-1.0.0.json", + "referenceNumber": 428, + "name": "Blue Oak Model License 1.0.0", + "licenseId": "BlueOak-1.0.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/OSL1.1" + "https://blueoakcouncil.org/license/1.0.0" ], "isOsiApproved": false }, { - "reference": "./OSL-2.0.html", + "reference": "https://spdx.org/licenses/MIT-advertising.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OSL-2.0.json", - "referenceNumber": "20", - "name": "Open Software License 2.0", - "licenseId": "OSL-2.0", + "detailsUrl": "https://spdx.org/licenses/MIT-advertising.json", + "referenceNumber": 429, + "name": "Enlightenment License (e16)", + "licenseId": "MIT-advertising", "seeAlso": [ - "http://web.archive.org/web/20041020171434/http://www.rosenlaw.com/osl2.0.html" + "https://fedoraproject.org/wiki/Licensing/MIT_With_Advertising" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./OSL-2.1.html", + "reference": "https://spdx.org/licenses/YPL-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OSL-2.1.json", - "referenceNumber": "24", - "name": "Open Software License 2.1", - "licenseId": "OSL-2.1", + "detailsUrl": "https://spdx.org/licenses/YPL-1.0.json", + "referenceNumber": 430, + "name": "Yahoo! Public License v1.0", + "licenseId": "YPL-1.0", "seeAlso": [ - "http://web.archive.org/web/20050212003940/http://www.rosenlaw.com/osl21.htm", - "https://opensource.org/licenses/OSL-2.1" + "http://www.zimbra.com/license/yahoo_public_license_1.0.html" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./OSL-3.0.html", + "reference": "https://spdx.org/licenses/IJG-short.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OSL-3.0.json", - "referenceNumber": "100", - "name": "Open Software License 3.0", - "licenseId": "OSL-3.0", + "detailsUrl": "https://spdx.org/licenses/IJG-short.json", + "referenceNumber": 431, + "name": "Independent JPEG Group License - short", + "licenseId": "IJG-short", "seeAlso": [ - "https://web.archive.org/web/20120101081418/http://rosenlaw.com:80/OSL3.0.htm", - "https://opensource.org/licenses/OSL-3.0" + "https://sourceforge.net/p/xmedcon/code/ci/master/tree/libs/ljpg/" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./OpenSSL.html", + "reference": "https://spdx.org/licenses/Adobe-Glyph.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/OpenSSL.json", - "referenceNumber": "249", - "name": "OpenSSL License", - "licenseId": "OpenSSL", + "detailsUrl": "https://spdx.org/licenses/Adobe-Glyph.json", + "referenceNumber": 432, + "name": "Adobe Glyph List License", + "licenseId": "Adobe-Glyph", "seeAlso": [ - "http://www.openssl.org/source/license.html" + "https://fedoraproject.org/wiki/Licensing/MIT#AdobeGlyph" ], "isOsiApproved": false }, { - "reference": "./PDDL-1.0.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/PDDL-1.0.json", - "referenceNumber": "14", - "name": "ODC Public Domain Dedication \u0026 License 1.0", - "licenseId": "PDDL-1.0", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-1.0.json", + "referenceNumber": 433, + "name": "Creative Commons Attribution Non Commercial No Derivatives 1.0 Generic", + "licenseId": "CC-BY-NC-ND-1.0", "seeAlso": [ - "http://opendatacommons.org/licenses/pddl/1.0/" + "https://creativecommons.org/licenses/by-nd-nc/1.0/legalcode" ], "isOsiApproved": false }, { - "reference": "./PHP-3.0.html", + "reference": "https://spdx.org/licenses/Glide.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/PHP-3.0.json", - "referenceNumber": "385", - "name": "PHP License v3.0", - "licenseId": "PHP-3.0", + "detailsUrl": "https://spdx.org/licenses/Glide.json", + "referenceNumber": 434, + "name": "3dfx Glide License", + "licenseId": "Glide", "seeAlso": [ - "http://www.php.net/license/3_0.txt", - "https://opensource.org/licenses/PHP-3.0" + "http://www.users.on.net/~triforce/glidexp/COPYING.txt" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./PHP-3.01.html", + "reference": "https://spdx.org/licenses/AMDPLPA.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/PHP-3.01.json", - "referenceNumber": "316", - "name": "PHP License v3.01", - "licenseId": "PHP-3.01", + "detailsUrl": "https://spdx.org/licenses/AMDPLPA.json", + "referenceNumber": 435, + "name": "AMD\u0027s plpa_map.c License", + "licenseId": "AMDPLPA", "seeAlso": [ - "http://www.php.net/license/3_01.txt" + "https://fedoraproject.org/wiki/Licensing/AMD_plpa_map_License" ], "isOsiApproved": false }, { - "reference": "./Parity-6.0.0.html", + "reference": "https://spdx.org/licenses/LZMA-SDK-9.22.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Parity-6.0.0.json", - "referenceNumber": "91", - "name": "The Parity Public License 6.0.0", - "licenseId": "Parity-6.0.0", + "detailsUrl": "https://spdx.org/licenses/LZMA-SDK-9.22.json", + "referenceNumber": 436, + "name": "LZMA SDK License (versions 9.22 and beyond)", + "licenseId": "LZMA-SDK-9.22", "seeAlso": [ - "https://paritylicense.com/versions/6.0.0.html" + "https://www.7-zip.org/sdk.html", + "https://sourceforge.net/projects/sevenzip/files/LZMA%20SDK/" ], "isOsiApproved": false }, { - "reference": "./Plexus.html", + "reference": "https://spdx.org/licenses/CDDL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Plexus.json", - "referenceNumber": "225", - "name": "Plexus Classworlds License", - "licenseId": "Plexus", + "detailsUrl": "https://spdx.org/licenses/CDDL-1.0.json", + "referenceNumber": 437, + "name": "Common Development and Distribution License 1.0", + "licenseId": "CDDL-1.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Plexus_Classworlds_License" + "https://opensource.org/licenses/cddl1" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./PostgreSQL.html", + "reference": "https://spdx.org/licenses/MS-RL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/PostgreSQL.json", - "referenceNumber": "247", - "name": "PostgreSQL License", - "licenseId": "PostgreSQL", + "detailsUrl": "https://spdx.org/licenses/MS-RL.json", + "referenceNumber": 438, + "name": "Microsoft Reciprocal License", + "licenseId": "MS-RL", "seeAlso": [ - "http://www.postgresql.org/about/licence", - "https://opensource.org/licenses/PostgreSQL" + "http://www.microsoft.com/opensource/licenses.mspx", + "https://opensource.org/licenses/MS-RL" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./Python-2.0.html", + "reference": "https://spdx.org/licenses/APSL-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Python-2.0.json", - "referenceNumber": "35", - "name": "Python License 2.0", - "licenseId": "Python-2.0", + "detailsUrl": "https://spdx.org/licenses/APSL-1.0.json", + "referenceNumber": 439, + "name": "Apple Public Source License 1.0", + "licenseId": "APSL-1.0", "seeAlso": [ - "https://opensource.org/licenses/Python-2.0" + "https://fedoraproject.org/wiki/Licensing/Apple_Public_Source_License_1.0" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": false }, { - "reference": "./QPL-1.0.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/QPL-1.0.json", - "referenceNumber": "27", - "name": "Q Public License 1.0", - "licenseId": "QPL-1.0", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.0.json", + "referenceNumber": 440, + "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 Generic", + "licenseId": "CC-BY-NC-SA-2.0", "seeAlso": [ - "http://doc.qt.nokia.com/3.3/license.html", - "https://opensource.org/licenses/QPL-1.0" + "https://creativecommons.org/licenses/by-nc-sa/2.0/legalcode" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./Qhull.html", + "reference": "https://spdx.org/licenses/JSON.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Qhull.json", - "referenceNumber": "67", - "name": "Qhull License", - "licenseId": "Qhull", + "detailsUrl": "https://spdx.org/licenses/JSON.json", + "referenceNumber": 441, + "name": "JSON License", + "licenseId": "JSON", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Qhull" + "http://www.json.org/license.html" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": false }, { - "reference": "./RHeCos-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/RHeCos-1.1.json", - "referenceNumber": "149", - "name": "Red Hat eCos Public License v1.1", - "licenseId": "RHeCos-1.1", + "reference": "https://spdx.org/licenses/GPL-3.0-with-autoconf-exception.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-3.0-with-autoconf-exception.json", + "referenceNumber": 442, + "name": "GNU General Public License v3.0 w/Autoconf exception", + "licenseId": "GPL-3.0-with-autoconf-exception", "seeAlso": [ - "http://ecos.sourceware.org/old-license.html" + "https://www.gnu.org/licenses/autoconf-exception-3.0.html" ], "isOsiApproved": false }, { - "reference": "./RPL-1.1.html", + "reference": "https://spdx.org/licenses/OLDAP-2.6.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/RPL-1.1.json", - "referenceNumber": "269", - "name": "Reciprocal Public License 1.1", - "licenseId": "RPL-1.1", + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.6.json", + "referenceNumber": 443, + "name": "Open LDAP Public License v2.6", + "licenseId": "OLDAP-2.6", "seeAlso": [ - "https://opensource.org/licenses/RPL-1.1" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003d1cae062821881f41b73012ba816434897abf4205" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./RPL-1.5.html", + "reference": "https://spdx.org/licenses/GFDL-1.3-or-later.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/RPL-1.5.json", - "referenceNumber": "227", - "name": "Reciprocal Public License 1.5", - "licenseId": "RPL-1.5", + "detailsUrl": "https://spdx.org/licenses/GFDL-1.3-or-later.json", + "referenceNumber": 444, + "name": "GNU Free Documentation License v1.3 or later", + "licenseId": "GFDL-1.3-or-later", "seeAlso": [ - "https://opensource.org/licenses/RPL-1.5" + "https://www.gnu.org/licenses/fdl-1.3.txt" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./RPSL-1.0.html", + "reference": "https://spdx.org/licenses/SGI-B-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/RPSL-1.0.json", - "referenceNumber": "273", - "name": "RealNetworks Public Source License v1.0", - "licenseId": "RPSL-1.0", + "detailsUrl": "https://spdx.org/licenses/SGI-B-2.0.json", + "referenceNumber": 445, + "name": "SGI Free Software License B v2.0", + "licenseId": "SGI-B-2.0", "seeAlso": [ - "https://helixcommunity.org/content/rpsl", - "https://opensource.org/licenses/RPSL-1.0" + "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.2.0.pdf" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./RSA-MD.html", + "reference": "https://spdx.org/licenses/mplus.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/RSA-MD.json", - "referenceNumber": "82", - "name": "RSA Message-Digest License ", - "licenseId": "RSA-MD", + "detailsUrl": "https://spdx.org/licenses/mplus.json", + "referenceNumber": 446, + "name": "mplus Font License", + "licenseId": "mplus", "seeAlso": [ - "http://www.faqs.org/rfcs/rfc1321.html" + "https://fedoraproject.org/wiki/Licensing:Mplus?rd\u003dLicensing/mplus" ], "isOsiApproved": false }, { - "reference": "./RSCPL.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/RSCPL.json", - "referenceNumber": "211", - "name": "Ricoh Source Code Public License", - "licenseId": "RSCPL", + "reference": "https://spdx.org/licenses/LGPL-2.0+.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/LGPL-2.0+.json", + "referenceNumber": 447, + "name": "GNU Library General Public License v2 or later", + "licenseId": "LGPL-2.0+", "seeAlso": [ - "http://wayback.archive.org/web/20060715140826/http://www.risource.org/RPL/RPL-1.0A.shtml", - "https://opensource.org/licenses/RSCPL" + "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" ], "isOsiApproved": true }, { - "reference": "./Rdisc.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-3.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Rdisc.json", - "referenceNumber": "295", - "name": "Rdisc License", - "licenseId": "Rdisc", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-3.0.json", + "referenceNumber": 448, + "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 Unported", + "licenseId": "CC-BY-NC-ND-3.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Rdisc_License" + "https://creativecommons.org/licenses/by-nc-nd/3.0/legalcode" ], "isOsiApproved": false }, { - "reference": "./Ruby.html", + "reference": "https://spdx.org/licenses/XFree86-1.1.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Ruby.json", - "referenceNumber": "263", - "name": "Ruby License", - "licenseId": "Ruby", + "detailsUrl": "https://spdx.org/licenses/XFree86-1.1.json", + "referenceNumber": 449, + "name": "XFree86 License 1.1", + "licenseId": "XFree86-1.1", "seeAlso": [ - "http://www.ruby-lang.org/en/LICENSE.txt" + "http://www.xfree86.org/current/LICENSE4.html" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./SAX-PD.html", + "reference": "https://spdx.org/licenses/CC-BY-2.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SAX-PD.json", - "referenceNumber": "140", - "name": "Sax Public Domain Notice", - "licenseId": "SAX-PD", + "detailsUrl": "https://spdx.org/licenses/CC-BY-2.0.json", + "referenceNumber": 450, + "name": "Creative Commons Attribution 2.0 Generic", + "licenseId": "CC-BY-2.0", "seeAlso": [ - "http://www.saxproject.org/copying.html" + "https://creativecommons.org/licenses/by/2.0/legalcode" ], "isOsiApproved": false }, { - "reference": "./SCEA.html", + "reference": "https://spdx.org/licenses/UCL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SCEA.json", - "referenceNumber": "16", - "name": "SCEA Shared Source License", - "licenseId": "SCEA", + "detailsUrl": "https://spdx.org/licenses/UCL-1.0.json", + "referenceNumber": 451, + "name": "Upstream Compatibility License v1.0", + "licenseId": "UCL-1.0", "seeAlso": [ - "http://research.scea.com/scea_shared_source_license.html" + "https://opensource.org/licenses/UCL-1.0" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./SGI-B-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SGI-B-1.0.json", - "referenceNumber": "90", - "name": "SGI Free Software License B v1.0", - "licenseId": "SGI-B-1.0", + "reference": "https://spdx.org/licenses/wxWindows.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/wxWindows.json", + "referenceNumber": 452, + "name": "wxWindows Library License", + "licenseId": "wxWindows", "seeAlso": [ - "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.1.0.html" + "https://opensource.org/licenses/WXwindows" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./SGI-B-1.1.html", + "reference": "https://spdx.org/licenses/BSD-4-Clause.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SGI-B-1.1.json", - "referenceNumber": "241", - "name": "SGI Free Software License B v1.1", - "licenseId": "SGI-B-1.1", + "detailsUrl": "https://spdx.org/licenses/BSD-4-Clause.json", + "referenceNumber": 453, + "name": "BSD 4-Clause \"Original\" or \"Old\" License", + "licenseId": "BSD-4-Clause", "seeAlso": [ - "http://oss.sgi.com/projects/FreeB/" + "http://directory.fsf.org/wiki/License:BSD_4Clause" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./SGI-B-2.0.html", + "reference": "https://spdx.org/licenses/GD.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/SGI-B-2.0.json", - "referenceNumber": "272", - "name": "SGI Free Software License B v2.0", - "licenseId": "SGI-B-2.0", + "detailsUrl": "https://spdx.org/licenses/GD.json", + "referenceNumber": 454, + "name": "GD License", + "licenseId": "GD", "seeAlso": [ - "http://oss.sgi.com/projects/FreeB/SGIFreeSWLicB.2.0.pdf" + "https://libgd.github.io/manuals/2.3.0/files/license-txt.html" ], "isOsiApproved": false }, { - "reference": "./SHL-0.5.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SHL-0.5.json", - "referenceNumber": "72", - "name": "Solderpad Hardware License v0.5", - "licenseId": "SHL-0.5", + "reference": "https://spdx.org/licenses/LGPL-3.0+.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/LGPL-3.0+.json", + "referenceNumber": 455, + "name": "GNU Lesser General Public License v3.0 or later", + "licenseId": "LGPL-3.0+", "seeAlso": [ - "https://solderpad.org/licenses/SHL-0.5/" + "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", + "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt", + "https://opensource.org/licenses/LGPL-3.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./SHL-0.51.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-2.5.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SHL-0.51.json", - "referenceNumber": "314", - "name": "Solderpad Hardware License, Version 0.51", - "licenseId": "SHL-0.51", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-2.5.json", + "referenceNumber": 456, + "name": "Creative Commons Attribution Non Commercial 2.5 Generic", + "licenseId": "CC-BY-NC-2.5", "seeAlso": [ - "https://solderpad.org/licenses/SHL-0.51/" + "https://creativecommons.org/licenses/by-nc/2.5/legalcode" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": false }, { - "reference": "./SISSL.html", + "reference": "https://spdx.org/licenses/EPL-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/SISSL.json", - "referenceNumber": "74", - "name": "Sun Industry Standards Source License v1.1", - "licenseId": "SISSL", + "detailsUrl": "https://spdx.org/licenses/EPL-1.0.json", + "referenceNumber": 457, + "name": "Eclipse Public License 1.0", + "licenseId": "EPL-1.0", "seeAlso": [ - "http://www.openoffice.org/licenses/sissl_license.html", - "https://opensource.org/licenses/SISSL" + "http://www.eclipse.org/legal/epl-v10.html", + "https://opensource.org/licenses/EPL-1.0" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./SISSL-1.2.html", + "reference": "https://spdx.org/licenses/copyleft-next-0.3.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SISSL-1.2.json", - "referenceNumber": "7", - "name": "Sun Industry Standards Source License v1.2", - "licenseId": "SISSL-1.2", + "detailsUrl": "https://spdx.org/licenses/copyleft-next-0.3.1.json", + "referenceNumber": 458, + "name": "copyleft-next 0.3.1", + "licenseId": "copyleft-next-0.3.1", "seeAlso": [ - "http://gridscheduler.sourceforge.net/Gridengine_SISSL_license.html" + "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.1" ], "isOsiApproved": false }, { - "reference": "./SMLNJ.html", + "reference": "https://spdx.org/licenses/CECILL-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/SMLNJ.json", - "referenceNumber": "296", - "name": "Standard ML of New Jersey License", - "licenseId": "SMLNJ", + "detailsUrl": "https://spdx.org/licenses/CECILL-1.0.json", + "referenceNumber": 459, + "name": "CeCILL Free Software License Agreement v1.0", + "licenseId": "CECILL-1.0", "seeAlso": [ - "https://www.smlnj.org/license.html" + "http://www.cecill.info/licences/Licence_CeCILL_V1-fr.html" ], "isOsiApproved": false }, { - "reference": "./SMPPL.html", + "reference": "https://spdx.org/licenses/AML.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SMPPL.json", - "referenceNumber": "127", - "name": "Secure Messaging Protocol Public License", - "licenseId": "SMPPL", + "detailsUrl": "https://spdx.org/licenses/AML.json", + "referenceNumber": 460, + "name": "Apple MIT License", + "licenseId": "AML", "seeAlso": [ - "https://github.com/dcblake/SMP/blob/master/Documentation/License.txt" + "https://fedoraproject.org/wiki/Licensing/Apple_MIT_License" ], "isOsiApproved": false }, { - "reference": "./SNIA.html", + "reference": "https://spdx.org/licenses/BSD-Protection.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SNIA.json", - "referenceNumber": "230", - "name": "SNIA Public License 1.1", - "licenseId": "SNIA", + "detailsUrl": "https://spdx.org/licenses/BSD-Protection.json", + "referenceNumber": 461, + "name": "BSD Protection License", + "licenseId": "BSD-Protection", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/SNIA_Public_License" + "https://fedoraproject.org/wiki/Licensing/BSD_Protection_License" ], "isOsiApproved": false }, { - "reference": "./SPL-1.0.html", + "reference": "https://spdx.org/licenses/RHeCos-1.1.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/SPL-1.0.json", - "referenceNumber": "54", - "name": "Sun Public License v1.0", - "licenseId": "SPL-1.0", + "detailsUrl": "https://spdx.org/licenses/RHeCos-1.1.json", + "referenceNumber": 462, + "name": "Red Hat eCos Public License v1.1", + "licenseId": "RHeCos-1.1", "seeAlso": [ - "https://opensource.org/licenses/SPL-1.0" + "http://ecos.sourceware.org/old-license.html" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": false }, { - "reference": "./SSPL-1.0.html", + "reference": "https://spdx.org/licenses/RPSL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SSPL-1.0.json", - "referenceNumber": "356", - "name": "Server Side Public License, v 1", - "licenseId": "SSPL-1.0", + "detailsUrl": "https://spdx.org/licenses/RPSL-1.0.json", + "referenceNumber": 463, + "name": "RealNetworks Public Source License v1.0", + "licenseId": "RPSL-1.0", "seeAlso": [ - "https://www.mongodb.com/licensing/server-side-public-license" + "https://helixcommunity.org/content/rpsl", + "https://opensource.org/licenses/RPSL-1.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./SWL.html", + "reference": "https://spdx.org/licenses/MakeIndex.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SWL.json", - "referenceNumber": "208", - "name": "Scheme Widget Library (SWL) Software License Agreement", - "licenseId": "SWL", + "detailsUrl": "https://spdx.org/licenses/MakeIndex.json", + "referenceNumber": 464, + "name": "MakeIndex License", + "licenseId": "MakeIndex", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/SWL" + "https://fedoraproject.org/wiki/Licensing/MakeIndex" ], "isOsiApproved": false }, { - "reference": "./Saxpath.html", + "reference": "https://spdx.org/licenses/LGPL-2.0-only.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Saxpath.json", - "referenceNumber": "18", - "name": "Saxpath License", - "licenseId": "Saxpath", + "detailsUrl": "https://spdx.org/licenses/LGPL-2.0-only.json", + "referenceNumber": 465, + "name": "GNU Library General Public License v2 only", + "licenseId": "LGPL-2.0-only", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Saxpath_License" + "https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./Sendmail.html", + "reference": "https://spdx.org/licenses/OSL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Sendmail.json", - "referenceNumber": "151", - "name": "Sendmail License", - "licenseId": "Sendmail", + "detailsUrl": "https://spdx.org/licenses/OSL-1.0.json", + "referenceNumber": 466, + "name": "Open Software License 1.0", + "licenseId": "OSL-1.0", "seeAlso": [ - "http://www.sendmail.com/pdfs/open_source/sendmail_license.pdf", - "https://web.archive.org/web/20160322142305/https://www.sendmail.com/pdfs/open_source/sendmail_license.pdf" + "https://opensource.org/licenses/OSL-1.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./Sendmail-8.23.html", + "reference": "https://spdx.org/licenses/MIT-enna.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Sendmail-8.23.json", - "referenceNumber": "41", - "name": "Sendmail License 8.23", - "licenseId": "Sendmail-8.23", + "detailsUrl": "https://spdx.org/licenses/MIT-enna.json", + "referenceNumber": 467, + "name": "enna License", + "licenseId": "MIT-enna", "seeAlso": [ - "https://www.proofpoint.com/sites/default/files/sendmail-license.pdf", - "https://web.archive.org/web/20181003101040/https://www.proofpoint.com/sites/default/files/sendmail-license.pdf" + "https://fedoraproject.org/wiki/Licensing/MIT#enna" ], "isOsiApproved": false }, { - "reference": "./SimPL-2.0.html", + "reference": "https://spdx.org/licenses/Artistic-2.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SimPL-2.0.json", - "referenceNumber": "184", - "name": "Simple Public License 2.0", - "licenseId": "SimPL-2.0", + "detailsUrl": "https://spdx.org/licenses/Artistic-2.0.json", + "referenceNumber": 468, + "name": "Artistic License 2.0", + "licenseId": "Artistic-2.0", "seeAlso": [ - "https://opensource.org/licenses/SimPL-2.0" + "http://www.perlfoundation.org/artistic_license_2_0", + "https://www.perlfoundation.org/artistic-license-20.html", + "https://opensource.org/licenses/artistic-license-2.0" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./Sleepycat.html", + "reference": "https://spdx.org/licenses/GFDL-1.2-no-invariants-only.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Sleepycat.json", - "referenceNumber": "290", - "name": "Sleepycat License", - "licenseId": "Sleepycat", + "detailsUrl": "https://spdx.org/licenses/GFDL-1.2-no-invariants-only.json", + "referenceNumber": 469, + "name": "GNU Free Documentation License v1.2 only - no invariants", + "licenseId": "GFDL-1.2-no-invariants-only", "seeAlso": [ - "https://opensource.org/licenses/Sleepycat" + "https://www.gnu.org/licenses/old-licenses/fdl-1.2.txt" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./Spencer-86.html", + "reference": "https://spdx.org/licenses/Kazlib.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Spencer-86.json", - "referenceNumber": "313", - "name": "Spencer License 86", - "licenseId": "Spencer-86", + "detailsUrl": "https://spdx.org/licenses/Kazlib.json", + "referenceNumber": 470, + "name": "Kazlib License", + "licenseId": "Kazlib", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License" + "http://git.savannah.gnu.org/cgit/kazlib.git/tree/except.c?id\u003d0062df360c2d17d57f6af19b0e444c51feb99036" ], "isOsiApproved": false }, { - "reference": "./Spencer-94.html", + "reference": "https://spdx.org/licenses/CPOL-1.02.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Spencer-94.json", - "referenceNumber": "29", - "name": "Spencer License 94", - "licenseId": "Spencer-94", + "detailsUrl": "https://spdx.org/licenses/CPOL-1.02.json", + "referenceNumber": 471, + "name": "Code Project Open License 1.02", + "licenseId": "CPOL-1.02", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Henry_Spencer_Reg-Ex_Library_License" + "http://www.codeproject.com/info/cpol10.aspx" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": false }, { - "reference": "./Spencer-99.html", + "reference": "https://spdx.org/licenses/NetCDF.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Spencer-99.json", - "referenceNumber": "386", - "name": "Spencer License 99", - "licenseId": "Spencer-99", + "detailsUrl": "https://spdx.org/licenses/NetCDF.json", + "referenceNumber": 472, + "name": "NetCDF license", + "licenseId": "NetCDF", "seeAlso": [ - "http://www.opensource.apple.com/source/tcl/tcl-5/tcl/generic/regfronts.c" + "http://www.unidata.ucar.edu/software/netcdf/copyright.html" ], "isOsiApproved": false }, { - "reference": "./StandardML-NJ.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/StandardML-NJ.json", - "referenceNumber": "219", - "name": "Standard ML of New Jersey License", - "licenseId": "StandardML-NJ", + "reference": "https://spdx.org/licenses/Aladdin.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Aladdin.json", + "referenceNumber": 473, + "name": "Aladdin Free Public License", + "licenseId": "Aladdin", "seeAlso": [ - "http://www.smlnj.org//license.html" + "http://pages.cs.wisc.edu/~ghost/doc/AFPL/6.01/Public.htm" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": false }, { - "reference": "./SugarCRM-1.1.3.html", + "reference": "https://spdx.org/licenses/OML.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/SugarCRM-1.1.3.json", - "referenceNumber": "292", - "name": "SugarCRM Public License v1.1.3", - "licenseId": "SugarCRM-1.1.3", + "detailsUrl": "https://spdx.org/licenses/OML.json", + "referenceNumber": 474, + "name": "Open Market License", + "licenseId": "OML", "seeAlso": [ - "http://www.sugarcrm.com/crm/SPL" + "https://fedoraproject.org/wiki/Licensing/Open_Market_License" ], "isOsiApproved": false }, { - "reference": "./TAPR-OHL-1.0.html", + "reference": "https://spdx.org/licenses/MulanPSL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TAPR-OHL-1.0.json", - "referenceNumber": "267", - "name": "TAPR Open Hardware License v1.0", - "licenseId": "TAPR-OHL-1.0", + "detailsUrl": "https://spdx.org/licenses/MulanPSL-1.0.json", + "referenceNumber": 475, + "name": "Mulan Permissive Software License, Version 1", + "licenseId": "MulanPSL-1.0", "seeAlso": [ - "https://www.tapr.org/OHL" + "https://license.coscl.org.cn/MulanPSL/", + "https://github.com/yuwenlong/longphp/blob/25dfb70cc2a466dc4bb55ba30901cbce08d164b5/LICENSE" ], "isOsiApproved": false }, { - "reference": "./TCL.html", + "reference": "https://spdx.org/licenses/OFL-1.0-RFN.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TCL.json", - "referenceNumber": "265", - "name": "TCL/TK License", - "licenseId": "TCL", + "detailsUrl": "https://spdx.org/licenses/OFL-1.0-RFN.json", + "referenceNumber": 476, + "name": "SIL Open Font License 1.0 with Reserved Font Name", + "licenseId": "OFL-1.0-RFN", "seeAlso": [ - "http://www.tcl.tk/software/tcltk/license.html", - "https://fedoraproject.org/wiki/Licensing/TCL" + "http://scripts.sil.org/cms/scripts/page.php?item_id\u003dOFL10_web" ], "isOsiApproved": false }, { - "reference": "./TCP-wrappers.html", + "reference": "https://spdx.org/licenses/BSD-4-Clause-Shortened.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TCP-wrappers.json", - "referenceNumber": "274", - "name": "TCP Wrappers License", - "licenseId": "TCP-wrappers", + "detailsUrl": "https://spdx.org/licenses/BSD-4-Clause-Shortened.json", + "referenceNumber": 477, + "name": "BSD 4 Clause Shortened", + "licenseId": "BSD-4-Clause-Shortened", "seeAlso": [ - "http://rc.quest.com/topics/openssh/license.php#tcpwrappers" + "https://metadata.ftp-master.debian.org/changelogs//main/a/arpwatch/arpwatch_2.1a15-7_copyright" ], "isOsiApproved": false }, { - "reference": "./TMate.html", + "reference": "https://spdx.org/licenses/LPPL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TMate.json", - "referenceNumber": "253", - "name": "TMate Open Source License", - "licenseId": "TMate", + "detailsUrl": "https://spdx.org/licenses/LPPL-1.0.json", + "referenceNumber": 478, + "name": "LaTeX Project Public License v1.0", + "licenseId": "LPPL-1.0", "seeAlso": [ - "http://svnkit.com/license.html" + "http://www.latex-project.org/lppl/lppl-1-0.txt" ], "isOsiApproved": false }, { - "reference": "./TORQUE-1.1.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TORQUE-1.1.json", - "referenceNumber": "171", - "name": "TORQUE v2.5+ Software License v1.1", - "licenseId": "TORQUE-1.1", + "reference": "https://spdx.org/licenses/GPL-3.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-3.0.json", + "referenceNumber": 479, + "name": "GNU General Public License v3.0 only", + "licenseId": "GPL-3.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/TORQUEv1.1" + "https://www.gnu.org/licenses/gpl-3.0-standalone.html", + "https://opensource.org/licenses/GPL-3.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./TOSL.html", + "reference": "https://spdx.org/licenses/OLDAP-2.3.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TOSL.json", - "referenceNumber": "360", - "name": "Trusster Open Source License", - "licenseId": "TOSL", + "detailsUrl": "https://spdx.org/licenses/OLDAP-2.3.json", + "referenceNumber": 480, + "name": "Open LDAP Public License v2.3", + "licenseId": "OLDAP-2.3", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/TOSL" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003dd32cf54a32d581ab475d23c810b0a7fbaf8d63c3" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./TU-Berlin-1.0.html", + "reference": "https://spdx.org/licenses/psfrag.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TU-Berlin-1.0.json", - "referenceNumber": "373", - "name": "Technische Universitaet Berlin License 1.0", - "licenseId": "TU-Berlin-1.0", + "detailsUrl": "https://spdx.org/licenses/psfrag.json", + "referenceNumber": 481, + "name": "psfrag License", + "licenseId": "psfrag", "seeAlso": [ - "https://github.com/swh/ladspa/blob/7bf6f3799fdba70fda297c2d8fd9f526803d9680/gsm/COPYRIGHT" + "https://fedoraproject.org/wiki/Licensing/psfrag" ], "isOsiApproved": false }, { - "reference": "./TU-Berlin-2.0.html", + "reference": "https://spdx.org/licenses/GFDL-1.1-no-invariants-only.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/TU-Berlin-2.0.json", - "referenceNumber": "391", - "name": "Technische Universitaet Berlin License 2.0", - "licenseId": "TU-Berlin-2.0", + "detailsUrl": "https://spdx.org/licenses/GFDL-1.1-no-invariants-only.json", + "referenceNumber": 482, + "name": "GNU Free Documentation License v1.1 only - no invariants", + "licenseId": "GFDL-1.1-no-invariants-only", "seeAlso": [ - "https://github.com/CorsixTH/deps/blob/fd339a9f526d1d9c9f01ccf39e438a015da50035/licences/libgsm.txt" + "https://www.gnu.org/licenses/old-licenses/fdl-1.1.txt" ], "isOsiApproved": false }, { - "reference": "./UPL-1.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/UPL-1.0.json", - "referenceNumber": "205", - "name": "Universal Permissive License v1.0", - "licenseId": "UPL-1.0", + "reference": "https://spdx.org/licenses/GPL-1.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-1.0.json", + "referenceNumber": 483, + "name": "GNU General Public License v1.0 only", + "licenseId": "GPL-1.0", "seeAlso": [ - "https://opensource.org/licenses/UPL" + "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./Unicode-DFS-2015.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-3.0-IGO.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Unicode-DFS-2015.json", - "referenceNumber": "11", - "name": "Unicode License Agreement - Data Files and Software (2015)", - "licenseId": "Unicode-DFS-2015", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-3.0-IGO.json", + "referenceNumber": 484, + "name": "Creative Commons Attribution Non Commercial No Derivatives 3.0 IGO", + "licenseId": "CC-BY-NC-ND-3.0-IGO", "seeAlso": [ - "https://web.archive.org/web/20151224134844/http://unicode.org/copyright.html" + "https://creativecommons.org/licenses/by-nc-nd/3.0/igo/legalcode" ], "isOsiApproved": false }, { - "reference": "./Unicode-DFS-2016.html", + "reference": "https://spdx.org/licenses/TCL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Unicode-DFS-2016.json", - "referenceNumber": "382", - "name": "Unicode License Agreement - Data Files and Software (2016)", - "licenseId": "Unicode-DFS-2016", + "detailsUrl": "https://spdx.org/licenses/TCL.json", + "referenceNumber": 485, + "name": "TCL/TK License", + "licenseId": "TCL", "seeAlso": [ - "http://www.unicode.org/copyright.html" + "http://www.tcl.tk/software/tcltk/license.html", + "https://fedoraproject.org/wiki/Licensing/TCL" ], "isOsiApproved": false }, { - "reference": "./Unicode-TOU.html", + "reference": "https://spdx.org/licenses/Rdisc.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Unicode-TOU.json", - "referenceNumber": "70", - "name": "Unicode Terms of Use", - "licenseId": "Unicode-TOU", + "detailsUrl": "https://spdx.org/licenses/Rdisc.json", + "referenceNumber": 486, + "name": "Rdisc License", + "licenseId": "Rdisc", "seeAlso": [ - "http://www.unicode.org/copyright.html" + "https://fedoraproject.org/wiki/Licensing/Rdisc_License" ], "isOsiApproved": false }, { - "reference": "./Unlicense.html", + "reference": "https://spdx.org/licenses/Python-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Unlicense.json", - "referenceNumber": "293", - "name": "The Unlicense", - "licenseId": "Unlicense", + "detailsUrl": "https://spdx.org/licenses/Python-2.0.json", + "referenceNumber": 487, + "name": "Python License 2.0", + "licenseId": "Python-2.0", "seeAlso": [ - "http://unlicense.org/" + "https://opensource.org/licenses/Python-2.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./VOSTROM.html", + "reference": "https://spdx.org/licenses/CC-BY-3.0-IGO.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/VOSTROM.json", - "referenceNumber": "228", - "name": "VOSTROM Public License for Open Source", - "licenseId": "VOSTROM", + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-IGO.json", + "referenceNumber": 488, + "name": "Creative Commons Attribution 3.0 IGO", + "licenseId": "CC-BY-3.0-IGO", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/VOSTROM" + "https://creativecommons.org/licenses/by/3.0/igo/legalcode" ], "isOsiApproved": false }, { - "reference": "./VSL-1.0.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/VSL-1.0.json", - "referenceNumber": "180", - "name": "Vovida Software License v1.0", - "licenseId": "VSL-1.0", + "reference": "https://spdx.org/licenses/BSD-2-Clause-FreeBSD.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-FreeBSD.json", + "referenceNumber": 489, + "name": "BSD 2-Clause FreeBSD License", + "licenseId": "BSD-2-Clause-FreeBSD", "seeAlso": [ - "https://opensource.org/licenses/VSL-1.0" + "http://www.freebsd.org/copyright/freebsd-license.html" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./Vim.html", + "reference": "https://spdx.org/licenses/TORQUE-1.1.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Vim.json", - "referenceNumber": "133", - "name": "Vim License", - "licenseId": "Vim", + "detailsUrl": "https://spdx.org/licenses/TORQUE-1.1.json", + "referenceNumber": 490, + "name": "TORQUE v2.5+ Software License v1.1", + "licenseId": "TORQUE-1.1", "seeAlso": [ - "http://vimdoc.sourceforge.net/htmldoc/uganda.html" + "https://fedoraproject.org/wiki/Licensing/TORQUEv1.1" ], "isOsiApproved": false }, { - "reference": "./W3C.html", + "reference": "https://spdx.org/licenses/BSD-3-Clause.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/W3C.json", - "referenceNumber": "351", - "name": "W3C Software Notice and License (2002-12-31)", - "licenseId": "W3C", + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause.json", + "referenceNumber": 491, + "name": "BSD 3-Clause \"New\" or \"Revised\" License", + "licenseId": "BSD-3-Clause", "seeAlso": [ - "http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231.html", - "https://opensource.org/licenses/W3C" + "https://opensource.org/licenses/BSD-3-Clause", + "https://www.eclipse.org/org/documents/edl-v10.php" ], - "isOsiApproved": true + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./W3C-19980720.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-UK.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/W3C-19980720.json", - "referenceNumber": "323", - "name": "W3C Software Notice and License (1998-07-20)", - "licenseId": "W3C-19980720", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-SA-2.0-UK.json", + "referenceNumber": 492, + "name": "Creative Commons Attribution Non Commercial Share Alike 2.0 England and Wales", + "licenseId": "CC-BY-NC-SA-2.0-UK", "seeAlso": [ - "http://www.w3.org/Consortium/Legal/copyright-software-19980720.html" + "https://creativecommons.org/licenses/by-nc-sa/2.0/uk/legalcode" ], "isOsiApproved": false }, { - "reference": "./W3C-20150513.html", + "reference": "https://spdx.org/licenses/libtiff.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/W3C-20150513.json", - "referenceNumber": "51", - "name": "W3C Software Notice and Document License (2015-05-13)", - "licenseId": "W3C-20150513", + "detailsUrl": "https://spdx.org/licenses/libtiff.json", + "referenceNumber": 493, + "name": "libtiff License", + "licenseId": "libtiff", "seeAlso": [ - "https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document" + "https://fedoraproject.org/wiki/Licensing/libtiff" ], "isOsiApproved": false }, { - "reference": "./WTFPL.html", + "reference": "https://spdx.org/licenses/EUPL-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/WTFPL.json", - "referenceNumber": "368", - "name": "Do What The F*ck You Want To Public License", - "licenseId": "WTFPL", + "detailsUrl": "https://spdx.org/licenses/EUPL-1.0.json", + "referenceNumber": 494, + "name": "European Union Public License 1.0", + "licenseId": "EUPL-1.0", "seeAlso": [ - "http://sam.zoy.org/wtfpl/COPYING" + "http://ec.europa.eu/idabc/en/document/7330.html", + "http://ec.europa.eu/idabc/servlets/Doc027f.pdf?id\u003d31096" ], "isOsiApproved": false }, { - "reference": "./Watcom-1.0.html", + "reference": "https://spdx.org/licenses/LPPL-1.2.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Watcom-1.0.json", - "referenceNumber": "177", - "name": "Sybase Open Watcom Public License 1.0", - "licenseId": "Watcom-1.0", + "detailsUrl": "https://spdx.org/licenses/LPPL-1.2.json", + "referenceNumber": 495, + "name": "LaTeX Project Public License v1.2", + "licenseId": "LPPL-1.2", "seeAlso": [ - "https://opensource.org/licenses/Watcom-1.0" + "http://www.latex-project.org/lppl/lppl-1-2.txt" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./Wsuipa.html", + "reference": "https://spdx.org/licenses/AdaCore-doc.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Wsuipa.json", - "referenceNumber": "135", - "name": "Wsuipa License", - "licenseId": "Wsuipa", + "detailsUrl": "https://spdx.org/licenses/AdaCore-doc.json", + "referenceNumber": 496, + "name": "AdaCore Doc License", + "licenseId": "AdaCore-doc", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Wsuipa" + "https://github.com/AdaCore/xmlada/blob/master/docs/index.rst", + "https://github.com/AdaCore/gnatcoll-core/blob/master/docs/index.rst", + "https://github.com/AdaCore/gnatcoll-db/blob/master/docs/index.rst" ], "isOsiApproved": false }, { - "reference": "./X11.html", + "reference": "https://spdx.org/licenses/OSL-1.1.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/X11.json", - "referenceNumber": "188", - "name": "X11 License", - "licenseId": "X11", + "detailsUrl": "https://spdx.org/licenses/OSL-1.1.json", + "referenceNumber": 497, + "name": "Open Software License 1.1", + "licenseId": "OSL-1.1", "seeAlso": [ - "http://www.xfree86.org/3.3.6/COPYRIGHT2.html#3" + "https://fedoraproject.org/wiki/Licensing/OSL1.1" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./XFree86-1.1.html", + "reference": "https://spdx.org/licenses/Multics.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/XFree86-1.1.json", - "referenceNumber": "243", - "name": "XFree86 License 1.1", - "licenseId": "XFree86-1.1", + "detailsUrl": "https://spdx.org/licenses/Multics.json", + "referenceNumber": 498, + "name": "Multics License", + "licenseId": "Multics", "seeAlso": [ - "http://www.xfree86.org/current/LICENSE4.html" + "https://opensource.org/licenses/Multics" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./XSkat.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/XSkat.json", - "referenceNumber": "96", - "name": "XSkat License", - "licenseId": "XSkat", + "reference": "https://spdx.org/licenses/GPL-1.0+.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/GPL-1.0+.json", + "referenceNumber": 499, + "name": "GNU General Public License v1.0 or later", + "licenseId": "GPL-1.0+", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/XSkat_License" + "https://www.gnu.org/licenses/old-licenses/gpl-1.0-standalone.html" ], "isOsiApproved": false }, { - "reference": "./Xerox.html", + "reference": "https://spdx.org/licenses/xlock.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Xerox.json", - "referenceNumber": "163", - "name": "Xerox License", - "licenseId": "Xerox", + "detailsUrl": "https://spdx.org/licenses/xlock.json", + "referenceNumber": 500, + "name": "xlock License", + "licenseId": "xlock", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Xerox" + "https://fossies.org/linux/tiff/contrib/ras/ras2tif.c" ], "isOsiApproved": false }, { - "reference": "./Xnet.html", + "reference": "https://spdx.org/licenses/OLDAP-1.3.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Xnet.json", - "referenceNumber": "388", - "name": "X.Net License", - "licenseId": "Xnet", + "detailsUrl": "https://spdx.org/licenses/OLDAP-1.3.json", + "referenceNumber": 501, + "name": "Open LDAP Public License v1.3", + "licenseId": "OLDAP-1.3", "seeAlso": [ - "https://opensource.org/licenses/Xnet" + "http://www.openldap.org/devel/gitweb.cgi?p\u003dopenldap.git;a\u003dblob;f\u003dLICENSE;hb\u003de5f8117f0ce088d0bd7a8e18ddf37eaa40eb09b1" ], - "isOsiApproved": true + "isOsiApproved": false }, { - "reference": "./YPL-1.0.html", + "reference": "https://spdx.org/licenses/HPND.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/YPL-1.0.json", - "referenceNumber": "174", - "name": "Yahoo! Public License v1.0", - "licenseId": "YPL-1.0", + "detailsUrl": "https://spdx.org/licenses/HPND.json", + "referenceNumber": 502, + "name": "Historical Permission Notice and Disclaimer", + "licenseId": "HPND", "seeAlso": [ - "http://www.zimbra.com/license/yahoo_public_license_1.0.html" + "https://opensource.org/licenses/HPND" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./YPL-1.1.html", + "reference": "https://spdx.org/licenses/Baekmuk.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/YPL-1.1.json", - "referenceNumber": "57", - "name": "Yahoo! Public License v1.1", - "licenseId": "YPL-1.1", + "detailsUrl": "https://spdx.org/licenses/Baekmuk.json", + "referenceNumber": 503, + "name": "Baekmuk License", + "licenseId": "Baekmuk", "seeAlso": [ - "http://www.zimbra.com/license/yahoo_public_license_1.1.html" + "https://fedoraproject.org/wiki/Licensing:Baekmuk?rd\u003dLicensing/Baekmuk" ], "isOsiApproved": false }, { - "reference": "./ZPL-1.1.html", + "reference": "https://spdx.org/licenses/AGPL-3.0-only.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/ZPL-1.1.json", - "referenceNumber": "359", - "name": "Zope Public License 1.1", - "licenseId": "ZPL-1.1", + "detailsUrl": "https://spdx.org/licenses/AGPL-3.0-only.json", + "referenceNumber": 504, + "name": "GNU Affero General Public License v3.0 only", + "licenseId": "AGPL-3.0-only", "seeAlso": [ - "http://old.zope.org/Resources/License/ZPL-1.1" + "https://www.gnu.org/licenses/agpl.txt", + "https://opensource.org/licenses/AGPL-3.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./ZPL-2.0.html", - "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/ZPL-2.0.json", - "referenceNumber": "78", - "name": "Zope Public License 2.0", - "licenseId": "ZPL-2.0", + "reference": "https://spdx.org/licenses/Nunit.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/Nunit.json", + "referenceNumber": 505, + "name": "Nunit License", + "licenseId": "Nunit", "seeAlso": [ - "http://old.zope.org/Resources/License/ZPL-2.0", - "https://opensource.org/licenses/ZPL-2.0" + "https://fedoraproject.org/wiki/Licensing/Nunit" ], - "isOsiApproved": true + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./ZPL-2.1.html", + "reference": "https://spdx.org/licenses/CDLA-Sharing-1.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/ZPL-2.1.json", - "referenceNumber": "345", - "name": "Zope Public License 2.1", - "licenseId": "ZPL-2.1", + "detailsUrl": "https://spdx.org/licenses/CDLA-Sharing-1.0.json", + "referenceNumber": 506, + "name": "Community Data License Agreement Sharing 1.0", + "licenseId": "CDLA-Sharing-1.0", "seeAlso": [ - "http://old.zope.org/Resources/ZPL/" + "https://cdla.io/sharing-1-0" ], "isOsiApproved": false }, { - "reference": "./Zed.html", + "reference": "https://spdx.org/licenses/OGL-UK-3.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Zed.json", - "referenceNumber": "248", - "name": "Zed License", - "licenseId": "Zed", + "detailsUrl": "https://spdx.org/licenses/OGL-UK-3.0.json", + "referenceNumber": 507, + "name": "Open Government Licence v3.0", + "licenseId": "OGL-UK-3.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Zed" + "http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/" ], "isOsiApproved": false }, { - "reference": "./Zend-2.0.html", + "reference": "https://spdx.org/licenses/Noweb.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Zend-2.0.json", - "referenceNumber": "198", - "name": "Zend License v2.0", - "licenseId": "Zend-2.0", + "detailsUrl": "https://spdx.org/licenses/Noweb.json", + "referenceNumber": 508, + "name": "Noweb License", + "licenseId": "Noweb", "seeAlso": [ - "https://web.archive.org/web/20130517195954/http://www.zend.com/license/2_00.txt" + "https://fedoraproject.org/wiki/Licensing/Noweb" ], "isOsiApproved": false }, { - "reference": "./Zimbra-1.3.html", + "reference": "https://spdx.org/licenses/Eurosym.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Zimbra-1.3.json", - "referenceNumber": "40", - "name": "Zimbra Public License v1.3", - "licenseId": "Zimbra-1.3", + "detailsUrl": "https://spdx.org/licenses/Eurosym.json", + "referenceNumber": 509, + "name": "Eurosym License", + "licenseId": "Eurosym", "seeAlso": [ - "http://web.archive.org/web/20100302225219/http://www.zimbra.com/license/zimbra-public-license-1-3.html" + "https://fedoraproject.org/wiki/Licensing/Eurosym" ], "isOsiApproved": false }, { - "reference": "./Zimbra-1.4.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-3.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/Zimbra-1.4.json", - "referenceNumber": "238", - "name": "Zimbra Public License v1.4", - "licenseId": "Zimbra-1.4", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-3.0.json", + "referenceNumber": 510, + "name": "Creative Commons Attribution Non Commercial 3.0 Unported", + "licenseId": "CC-BY-NC-3.0", "seeAlso": [ - "http://www.zimbra.com/legal/zimbra-public-license-1-4" + "https://creativecommons.org/licenses/by-nc/3.0/legalcode" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": false }, { - "reference": "./Zlib.html", + "reference": "https://spdx.org/licenses/CECILL-2.1.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/Zlib.json", - "referenceNumber": "320", - "name": "zlib License", - "licenseId": "Zlib", + "detailsUrl": "https://spdx.org/licenses/CECILL-2.1.json", + "referenceNumber": 511, + "name": "CeCILL Free Software License Agreement v2.1", + "licenseId": "CECILL-2.1", "seeAlso": [ - "http://www.zlib.net/zlib_license.html", - "https://opensource.org/licenses/Zlib" + "http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.html" ], "isOsiApproved": true }, { - "reference": "./blessing.html", + "reference": "https://spdx.org/licenses/TAPR-OHL-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/blessing.json", - "referenceNumber": "331", - "name": "SQLite Blessing", - "licenseId": "blessing", + "detailsUrl": "https://spdx.org/licenses/TAPR-OHL-1.0.json", + "referenceNumber": 512, + "name": "TAPR Open Hardware License v1.0", + "licenseId": "TAPR-OHL-1.0", "seeAlso": [ - "https://www.sqlite.org/src/artifact/e33a4df7e32d742a?ln\u003d4-9", - "https://sqlite.org/src/artifact/df5091916dbb40e6" + "https://www.tapr.org/OHL" ], "isOsiApproved": false }, { - "reference": "./bzip2-1.0.5.html", + "reference": "https://spdx.org/licenses/CC-BY-SA-3.0-DE.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/bzip2-1.0.5.json", - "referenceNumber": "200", - "name": "bzip2 and libbzip2 License v1.0.5", - "licenseId": "bzip2-1.0.5", + "detailsUrl": "https://spdx.org/licenses/CC-BY-SA-3.0-DE.json", + "referenceNumber": 513, + "name": "Creative Commons Attribution Share Alike 3.0 Germany", + "licenseId": "CC-BY-SA-3.0-DE", "seeAlso": [ - "http://bzip.org/1.0.5/bzip2-manual-1.0.5.html" + "https://creativecommons.org/licenses/by-sa/3.0/de/legalcode" ], "isOsiApproved": false }, { - "reference": "./bzip2-1.0.6.html", + "reference": "https://spdx.org/licenses/CC-BY-3.0-NL.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/bzip2-1.0.6.json", - "referenceNumber": "302", - "name": "bzip2 and libbzip2 License v1.0.6", - "licenseId": "bzip2-1.0.6", + "detailsUrl": "https://spdx.org/licenses/CC-BY-3.0-NL.json", + "referenceNumber": 514, + "name": "Creative Commons Attribution 3.0 Netherlands", + "licenseId": "CC-BY-3.0-NL", "seeAlso": [ - "https://github.com/asimonov-im/bzip2/blob/master/LICENSE" + "https://creativecommons.org/licenses/by/3.0/nl/legalcode" ], "isOsiApproved": false }, { - "reference": "./copyleft-next-0.3.0.html", + "reference": "https://spdx.org/licenses/SAX-PD.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/copyleft-next-0.3.0.json", - "referenceNumber": "176", - "name": "copyleft-next 0.3.0", - "licenseId": "copyleft-next-0.3.0", + "detailsUrl": "https://spdx.org/licenses/SAX-PD.json", + "referenceNumber": 515, + "name": "Sax Public Domain Notice", + "licenseId": "SAX-PD", "seeAlso": [ - "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.0" + "http://www.saxproject.org/copying.html" ], "isOsiApproved": false }, { - "reference": "./copyleft-next-0.3.1.html", + "reference": "https://spdx.org/licenses/FreeBSD-DOC.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/copyleft-next-0.3.1.json", - "referenceNumber": "347", - "name": "copyleft-next 0.3.1", - "licenseId": "copyleft-next-0.3.1", + "detailsUrl": "https://spdx.org/licenses/FreeBSD-DOC.json", + "referenceNumber": 516, + "name": "FreeBSD Documentation License", + "licenseId": "FreeBSD-DOC", "seeAlso": [ - "https://github.com/copyleft-next/copyleft-next/blob/master/Releases/copyleft-next-0.3.1" + "https://www.freebsd.org/copyright/freebsd-doc-license/" ], "isOsiApproved": false }, { - "reference": "./curl.html", + "reference": "https://spdx.org/licenses/BSD-1-Clause.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/curl.json", - "referenceNumber": "260", - "name": "curl License", - "licenseId": "curl", + "detailsUrl": "https://spdx.org/licenses/BSD-1-Clause.json", + "referenceNumber": 517, + "name": "BSD 1-Clause License", + "licenseId": "BSD-1-Clause", "seeAlso": [ - "https://github.com/bagder/curl/blob/master/COPYING" + "https://svnweb.freebsd.org/base/head/include/ifaddrs.h?revision\u003d326823" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./diffmark.html", + "reference": "https://spdx.org/licenses/CC-BY-NC-ND-4.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/diffmark.json", - "referenceNumber": "367", - "name": "diffmark license", - "licenseId": "diffmark", + "detailsUrl": "https://spdx.org/licenses/CC-BY-NC-ND-4.0.json", + "referenceNumber": 518, + "name": "Creative Commons Attribution Non Commercial No Derivatives 4.0 International", + "licenseId": "CC-BY-NC-ND-4.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/diffmark" + "https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode" ], "isOsiApproved": false }, { - "reference": "./dvipdfm.html", + "reference": "https://spdx.org/licenses/LPPL-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/dvipdfm.json", - "referenceNumber": "143", - "name": "dvipdfm License", - "licenseId": "dvipdfm", + "detailsUrl": "https://spdx.org/licenses/LPPL-1.1.json", + "referenceNumber": 519, + "name": "LaTeX Project Public License v1.1", + "licenseId": "LPPL-1.1", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/dvipdfm" + "http://www.latex-project.org/lppl/lppl-1-1.txt" ], "isOsiApproved": false }, { - "reference": "./eCos-2.0.html", - "isDeprecatedLicenseId": true, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/eCos-2.0.json", - "referenceNumber": "329", - "name": "eCos license version 2.0", - "licenseId": "eCos-2.0", + "reference": "https://spdx.org/licenses/Interbase-1.0.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/Interbase-1.0.json", + "referenceNumber": 520, + "name": "Interbase Public License v1.0", + "licenseId": "Interbase-1.0", "seeAlso": [ - "https://www.gnu.org/licenses/ecos-license.html" + "https://web.archive.org/web/20060319014854/http://info.borland.com/devsupport/interbase/opensource/IPL.html" ], "isOsiApproved": false }, { - "reference": "./eGenix.html", + "reference": "https://spdx.org/licenses/Martin-Birgmeier.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/eGenix.json", - "referenceNumber": "204", - "name": "eGenix.com Public License 1.1.0", - "licenseId": "eGenix", + "detailsUrl": "https://spdx.org/licenses/Martin-Birgmeier.json", + "referenceNumber": 521, + "name": "Martin Birgmeier License", + "licenseId": "Martin-Birgmeier", "seeAlso": [ - "http://www.egenix.com/products/eGenix.com-Public-License-1.1.0.pdf", - "https://fedoraproject.org/wiki/Licensing/eGenix.com_Public_License_1.1.0" + "https://github.com/Perl/perl5/blob/blead/util.c#L6136" ], "isOsiApproved": false }, { - "reference": "./gSOAP-1.3b.html", + "reference": "https://spdx.org/licenses/BSD-3-Clause-Clear.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/gSOAP-1.3b.json", - "referenceNumber": "346", - "name": "gSOAP Public License v1.3b", - "licenseId": "gSOAP-1.3b", + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Clear.json", + "referenceNumber": 522, + "name": "BSD 3-Clause Clear License", + "licenseId": "BSD-3-Clause-Clear", "seeAlso": [ - "http://www.cs.fsu.edu/~engelen/license.html" + "http://labs.metacarta.com/license-explanation.html#license" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./gnuplot.html", + "reference": "https://spdx.org/licenses/SimPL-2.0.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/gnuplot.json", - "referenceNumber": "10", - "name": "gnuplot License", - "licenseId": "gnuplot", + "detailsUrl": "https://spdx.org/licenses/SimPL-2.0.json", + "referenceNumber": 523, + "name": "Simple Public License 2.0", + "licenseId": "SimPL-2.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Gnuplot" + "https://opensource.org/licenses/SimPL-2.0" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./iMatix.html", + "reference": "https://spdx.org/licenses/mpich2.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/iMatix.json", - "referenceNumber": "342", - "name": "iMatix Standard Function Library Agreement", - "licenseId": "iMatix", + "detailsUrl": "https://spdx.org/licenses/mpich2.json", + "referenceNumber": 524, + "name": "mpich2 License", + "licenseId": "mpich2", "seeAlso": [ - "http://legacy.imatix.com/html/sfl/sfl4.htm#license" + "https://fedoraproject.org/wiki/Licensing/MIT" ], "isOsiApproved": false }, { - "reference": "./libpng-2.0.html", + "reference": "https://spdx.org/licenses/Apache-1.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/libpng-2.0.json", - "referenceNumber": "76", - "name": "PNG Reference Library version 2", - "licenseId": "libpng-2.0", + "detailsUrl": "https://spdx.org/licenses/Apache-1.0.json", + "referenceNumber": 525, + "name": "Apache License 1.0", + "licenseId": "Apache-1.0", "seeAlso": [ - "http://www.libpng.org/pub/png/src/libpng-LICENSE.txt" + "http://www.apache.org/licenses/LICENSE-1.0" ], - "isOsiApproved": false + "isOsiApproved": false, + "isFsfLibre": true }, { - "reference": "./libtiff.html", + "reference": "https://spdx.org/licenses/EUPL-1.1.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/libtiff.json", - "referenceNumber": "220", - "name": "libtiff License", - "licenseId": "libtiff", + "detailsUrl": "https://spdx.org/licenses/EUPL-1.1.json", + "referenceNumber": 526, + "name": "European Union Public License 1.1", + "licenseId": "EUPL-1.1", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/libtiff" + "https://joinup.ec.europa.eu/software/page/eupl/licence-eupl", + "https://joinup.ec.europa.eu/sites/default/files/custom-page/attachment/eupl1.1.-licence-en_0.pdf", + "https://opensource.org/licenses/EUPL-1.1" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./mpich2.html", + "reference": "https://spdx.org/licenses/BSD-3-Clause-Modification.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/mpich2.json", - "referenceNumber": "318", - "name": "mpich2 License", - "licenseId": "mpich2", + "detailsUrl": "https://spdx.org/licenses/BSD-3-Clause-Modification.json", + "referenceNumber": 527, + "name": "BSD 3-Clause Modification", + "licenseId": "BSD-3-Clause-Modification", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/MIT" + "https://fedoraproject.org/wiki/Licensing:BSD#Modification_Variant" ], "isOsiApproved": false }, { - "reference": "./psfrag.html", - "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/psfrag.json", - "referenceNumber": "245", - "name": "psfrag License", - "licenseId": "psfrag", + "reference": "https://spdx.org/licenses/LGPL-3.0.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/LGPL-3.0.json", + "referenceNumber": 528, + "name": "GNU Lesser General Public License v3.0 only", + "licenseId": "LGPL-3.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/psfrag" + "https://www.gnu.org/licenses/lgpl-3.0-standalone.html", + "https://www.gnu.org/licenses/lgpl+gpl-3.0.txt", + "https://opensource.org/licenses/LGPL-3.0" ], - "isOsiApproved": false + "isOsiApproved": true, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/LGPL-2.1.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/LGPL-2.1.json", + "referenceNumber": 529, + "name": "GNU Lesser General Public License v2.1 only", + "licenseId": "LGPL-2.1", + "seeAlso": [ + "https://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html", + "https://opensource.org/licenses/LGPL-2.1" + ], + "isOsiApproved": true, + "isFsfLibre": true }, { - "reference": "./psutils.html", + "reference": "https://spdx.org/licenses/Artistic-1.0-Perl.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/psutils.json", - "referenceNumber": "126", - "name": "psutils License", - "licenseId": "psutils", + "detailsUrl": "https://spdx.org/licenses/Artistic-1.0-Perl.json", + "referenceNumber": 530, + "name": "Artistic License 1.0 (Perl)", + "licenseId": "Artistic-1.0-Perl", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/psutils" + "http://dev.perl.org/licenses/artistic.html" ], - "isOsiApproved": false + "isOsiApproved": true }, { - "reference": "./wxWindows.html", - "isDeprecatedLicenseId": true, - "detailsUrl": "http://spdx.org/licenses/wxWindows.json", - "referenceNumber": "86", - "name": "wxWindows Library License", - "licenseId": "wxWindows", + "reference": "https://spdx.org/licenses/BSD-2-Clause-Views.html", + "isDeprecatedLicenseId": false, + "detailsUrl": "https://spdx.org/licenses/BSD-2-Clause-Views.json", + "referenceNumber": 531, + "name": "BSD 2-Clause with views sentence", + "licenseId": "BSD-2-Clause-Views", "seeAlso": [ - "https://opensource.org/licenses/WXwindows" + "http://www.freebsd.org/copyright/freebsd-license.html", + "https://people.freebsd.org/~ivoras/wine/patch-wine-nvidia.sh", + "https://github.com/protegeproject/protege/blob/master/license.txt" ], "isOsiApproved": false }, { - "reference": "./xinetd.html", + "reference": "https://spdx.org/licenses/gSOAP-1.3b.html", "isDeprecatedLicenseId": false, - "isFsfLibre": true, - "detailsUrl": "http://spdx.org/licenses/xinetd.json", - "referenceNumber": "146", - "name": "xinetd License", - "licenseId": "xinetd", + "detailsUrl": "https://spdx.org/licenses/gSOAP-1.3b.json", + "referenceNumber": 532, + "name": "gSOAP Public License v1.3b", + "licenseId": "gSOAP-1.3b", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/Xinetd_License" + "http://www.cs.fsu.edu/~engelen/license.html" ], "isOsiApproved": false }, { - "reference": "./xpp.html", + "reference": "https://spdx.org/licenses/Minpack.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/xpp.json", - "referenceNumber": "275", - "name": "XPP License", - "licenseId": "xpp", + "detailsUrl": "https://spdx.org/licenses/Minpack.json", + "referenceNumber": 533, + "name": "Minpack License", + "licenseId": "Minpack", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/xpp" + "http://www.netlib.org/minpack/disclaimer", + "https://gitlab.com/libeigen/eigen/-/blob/master/COPYING.MINPACK" ], "isOsiApproved": false }, { - "reference": "./zlib-acknowledgement.html", + "reference": "https://spdx.org/licenses/StandardML-NJ.html", + "isDeprecatedLicenseId": true, + "detailsUrl": "https://spdx.org/licenses/StandardML-NJ.json", + "referenceNumber": 534, + "name": "Standard ML of New Jersey License", + "licenseId": "StandardML-NJ", + "seeAlso": [ + "https://www.smlnj.org/license.html" + ], + "isOsiApproved": false, + "isFsfLibre": true + }, + { + "reference": "https://spdx.org/licenses/NPOSL-3.0.html", "isDeprecatedLicenseId": false, - "detailsUrl": "http://spdx.org/licenses/zlib-acknowledgement.json", - "referenceNumber": "321", - "name": "zlib/libpng License with Acknowledgement", - "licenseId": "zlib-acknowledgement", + "detailsUrl": "https://spdx.org/licenses/NPOSL-3.0.json", + "referenceNumber": 535, + "name": "Non-Profit Open Software License 3.0", + "licenseId": "NPOSL-3.0", "seeAlso": [ - "https://fedoraproject.org/wiki/Licensing/ZlibWithAcknowledgement" + "https://opensource.org/licenses/NOSL3.0" ], - "isOsiApproved": false + "isOsiApproved": true } ], - "releaseDate": "2019-07-10" + "releaseDate": "2023-02-17" } \ No newline at end of file diff --git a/tests/data/doc_write/json-simple-multi-package.json b/tests/data/doc_write/json-simple-multi-package.json index 61e221c7e..df012cda1 100644 --- a/tests/data/doc_write/json-simple-multi-package.json +++ b/tests/data/doc_write/json-simple-multi-package.json @@ -6,7 +6,7 @@ "Tool: ScanCode" ], "created": "2021-10-21T17:09:37Z", - "licenseListVersion": "3.6" + "licenseListVersion": "3.20" }, "dataLicense": "CC0-1.0", "SPDXID": "SPDXRef-DOCUMENT", diff --git a/tests/data/doc_write/json-simple-plus.json b/tests/data/doc_write/json-simple-plus.json index e9be761eb..ae6cff652 100644 --- a/tests/data/doc_write/json-simple-plus.json +++ b/tests/data/doc_write/json-simple-plus.json @@ -9,7 +9,7 @@ "Organization: SPDX" ], "created": "2021-11-15T00:00:00Z", - "licenseListVersion": "3.6" + "licenseListVersion": "3.20" }, "documentDescribes": [ "SPDXRef-Package" diff --git a/tests/data/doc_write/json-simple.json b/tests/data/doc_write/json-simple.json index 30c1b8943..4675599d1 100644 --- a/tests/data/doc_write/json-simple.json +++ b/tests/data/doc_write/json-simple.json @@ -9,7 +9,7 @@ "Organization: SPDX" ], "created": "2021-11-15T00:00:00Z", - "licenseListVersion": "3.6" + "licenseListVersion": "3.20" }, "documentDescribes": [ "SPDXRef-Package" diff --git a/tests/data/doc_write/tv-mini.tv b/tests/data/doc_write/tv-mini.tv index 368682998..631d2eda8 100644 --- a/tests/data/doc_write/tv-mini.tv +++ b/tests/data/doc_write/tv-mini.tv @@ -1,7 +1,7 @@ # Document Information SPDXVersion: SPDX-2.1 DataLicense: CC0-1.0 -LicenseListVersion: 3.6 +LicenseListVersion: 3.20 SPDXID: SPDXRef-DOCUMENT # Creation Info diff --git a/tests/data/doc_write/tv-simple-plus.tv b/tests/data/doc_write/tv-simple-plus.tv index 8e4d5356d..75552bd94 100644 --- a/tests/data/doc_write/tv-simple-plus.tv +++ b/tests/data/doc_write/tv-simple-plus.tv @@ -3,7 +3,7 @@ SPDXVersion: SPDX-2.1 DataLicense: CC0-1.0 DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 DocumentName: Sample_Document-V2.1 -LicenseListVersion: 3.6 +LicenseListVersion: 3.20 SPDXID: SPDXRef-DOCUMENT # Creation Info # Relationships diff --git a/tests/data/doc_write/tv-simple.tv b/tests/data/doc_write/tv-simple.tv index 1190f444f..b98af262f 100644 --- a/tests/data/doc_write/tv-simple.tv +++ b/tests/data/doc_write/tv-simple.tv @@ -3,7 +3,7 @@ SPDXVersion: SPDX-2.1 DataLicense: CC0-1.0 DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 DocumentName: Sample_Document-V2.1 -LicenseListVersion: 3.6 +LicenseListVersion: 3.20 SPDXID: SPDXRef-DOCUMENT # Creation Info # Relationships diff --git a/tests/data/doc_write/xml-simple-multi-package.xml b/tests/data/doc_write/xml-simple-multi-package.xml index 7552c6dcc..94d60f73b 100644 --- a/tests/data/doc_write/xml-simple-multi-package.xml +++ b/tests/data/doc_write/xml-simple-multi-package.xml @@ -5,7 +5,7 @@ Tool: ScanCode 2021-10-21T17:02:23Z - 3.6 + 3.20 CC0-1.0 SPDXRef-DOCUMENT diff --git a/tests/data/doc_write/yaml-simple-multi-package.yaml b/tests/data/doc_write/yaml-simple-multi-package.yaml index a6d10db5c..ce8cab970 100644 --- a/tests/data/doc_write/yaml-simple-multi-package.yaml +++ b/tests/data/doc_write/yaml-simple-multi-package.yaml @@ -3,7 +3,7 @@ creationInfo: created: '2021-10-21T16:46:56Z' creators: - 'Tool: ScanCode' - licenseListVersion: '3.6' + licenseListVersion: '3.20' dataLicense: CC0-1.0 documentDescribes: - SPDXRef-Package1 @@ -51,4 +51,4 @@ files: licenseConcluded: NOASSERTION licenseInfoInFiles: - LGPL-2.1-or-later - fileName: ./some/path/tofile \ No newline at end of file + fileName: ./some/path/tofile diff --git a/tests/data/doc_write/yaml-simple-plus.yaml b/tests/data/doc_write/yaml-simple-plus.yaml index 007d6cdd9..d4e8f2cbb 100644 --- a/tests/data/doc_write/yaml-simple-plus.yaml +++ b/tests/data/doc_write/yaml-simple-plus.yaml @@ -3,7 +3,7 @@ creationInfo: created: '2021-11-15T00:00:00Z' creators: - 'Organization: SPDX' - licenseListVersion: '3.6' + licenseListVersion: '3.20' dataLicense: CC0-1.0 documentDescribes: - SPDXRef-Package diff --git a/tests/data/doc_write/yaml-simple.yaml b/tests/data/doc_write/yaml-simple.yaml index 98e6edb42..fe9258912 100644 --- a/tests/data/doc_write/yaml-simple.yaml +++ b/tests/data/doc_write/yaml-simple.yaml @@ -3,7 +3,7 @@ creationInfo: created: '2021-11-15T00:00:00Z' creators: - 'Organization: SPDX' - licenseListVersion: '3.6' + licenseListVersion: '3.20' dataLicense: CC0-1.0 documentDescribes: - SPDXRef-Package diff --git a/tests/data/formats/SPDXJsonExample.json b/tests/data/formats/SPDXJsonExample.json index e87a4ea70..57c2fb239 100644 --- a/tests/data/formats/SPDXJsonExample.json +++ b/tests/data/formats/SPDXJsonExample.json @@ -115,7 +115,7 @@ "Person: Gary O'Neall", "Organization: Source Auditor Inc." ], - "licenseListVersion": "3.6", + "licenseListVersion": "3.20", "created": "2010-02-03T00:00:00Z" }, "externalDocumentRefs": [ diff --git a/tests/data/formats/SPDXJsonExampleEmptyArrays.json b/tests/data/formats/SPDXJsonExampleEmptyArrays.json index 261c31e8f..5d8cee207 100644 --- a/tests/data/formats/SPDXJsonExampleEmptyArrays.json +++ b/tests/data/formats/SPDXJsonExampleEmptyArrays.json @@ -53,7 +53,7 @@ "Person: Gary O'Neall", "Organization: Source Auditor Inc." ], - "licenseListVersion": "3.6", + "licenseListVersion": "3.20", "created": "2010-02-03T00:00:00Z" }, "documentNamespace": "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", diff --git a/tests/data/formats/SPDXXmlExample.xml b/tests/data/formats/SPDXXmlExample.xml index d65321351..5ecd8d24a 100644 --- a/tests/data/formats/SPDXXmlExample.xml +++ b/tests/data/formats/SPDXXmlExample.xml @@ -47,7 +47,7 @@ Tool: SourceAuditor-V1.2 Person: Gary O'Neall Organization: Source Auditor Inc. - 3.6 + 3.20 2010-02-03T00:00:00Z diff --git a/tests/data/formats/SPDXYamlExample.yaml b/tests/data/formats/SPDXYamlExample.yaml index 854fdb7a7..4d0bd63cf 100644 --- a/tests/data/formats/SPDXYamlExample.yaml +++ b/tests/data/formats/SPDXYamlExample.yaml @@ -13,7 +13,7 @@ Document: - 'Tool: SourceAuditor-V1.2' - 'Organization: Source Auditor Inc.' - 'Person: Gary O''Neall' - licenseListVersion: '3.6' + licenseListVersion: '3.20' dataLicense: CC0-1.0 documentDescribes: - SPDXRef-Package diff --git a/tests/test_config.py b/tests/test_config.py index 718c3885b..28dab95b3 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -21,7 +21,7 @@ class TestLicenseList(TestCase): def test_load_license_list(self): version, licenses_map = config.load_license_list(config._licenses) - assert version == ('3', '6') + assert version == ('3', '20') # Test some instances in licenses_map assert licenses_map['MIT License'] == 'MIT' assert licenses_map['MIT'] == 'MIT License' @@ -31,11 +31,11 @@ def test_load_license_list(self): assert licenses_map['GPL-3.0-only'] == 'GNU General Public License v3.0 only' def test_config_license_list_version_constant(self): - assert config.LICENSE_LIST_VERSION == Version(major=3, minor=6) + assert config.LICENSE_LIST_VERSION == Version(major=3, minor=20) def test_load_exception_list(self): version, exception_map = config.load_exception_list(config._exceptions) - assert version == ('3', '6') + assert version == ('3', '20') # Test some instances in exception_map assert exception_map['Bison exception 2.2'] == 'Bison-exception-2.2' assert exception_map['Bison-exception-2.2'] == 'Bison exception 2.2' From a033bc9dbdbc5026612895f7fd4b5149bf5d66eb Mon Sep 17 00:00:00 2001 From: Marc-Etienne Vargenau Date: Thu, 23 Feb 2023 12:04:04 +0100 Subject: [PATCH 012/354] Fix tests Signed-off-by: Marc-Etienne Vargenau --- tests/data/doc_parse/expected.json | 2 +- tests/data/doc_parse/spdx-expected.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/data/doc_parse/expected.json b/tests/data/doc_parse/expected.json index 84f6689d1..febfd92a4 100644 --- a/tests/data/doc_parse/expected.json +++ b/tests/data/doc_parse/expected.json @@ -14,7 +14,7 @@ }, "licenseListVersion": { "major": 3, - "minor": 6 + "minor": 20 }, "creators": [ { diff --git a/tests/data/doc_parse/spdx-expected.json b/tests/data/doc_parse/spdx-expected.json index fce55cb2c..8eae8942d 100644 --- a/tests/data/doc_parse/spdx-expected.json +++ b/tests/data/doc_parse/spdx-expected.json @@ -14,7 +14,7 @@ }, "licenseListVersion": { "major": 3, - "minor": 6 + "minor": 20 }, "creators": [ { From 3838ef18317ca20626387f5aa05a506d71cf606a Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 28 Feb 2023 11:57:12 +0100 Subject: [PATCH 013/354] [issue-464] fix rdf parser: package supplier and originator could be NOASSERTION Signed-off-by: Meret Behrens --- spdx/parsers/rdf.py | 20 +++++++++++--------- tests/data/doc_parse/spdx-expected.json | 6 +----- tests/data/formats/SPDXRdfExample.rdf | 2 +- tests/utils_test.py | 2 ++ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/spdx/parsers/rdf.py b/spdx/parsers/rdf.py index c78d3ca56..94841127d 100644 --- a/spdx/parsers/rdf.py +++ b/spdx/parsers/rdf.py @@ -114,11 +114,11 @@ def to_special_value(self, value): NONE, NOASSERTION or UNKNOWN if so returns proper model. else returns value """ - if value == self.spdx_namespace.none: + if value == self.spdx_namespace.none or str(value) == "NONE": return utils.SPDXNone() - elif value == self.spdx_namespace.noassertion: + elif value == self.spdx_namespace.noassertion or str(value) == "NOASSERTION": return utils.NoAssert() - elif value == self.spdx_namespace.unknown: + elif value == self.spdx_namespace.unknown or str(value) == "UNKNOWN": return utils.UnKnown() else: return str(value) @@ -561,10 +561,11 @@ def p_pkg_files_analyzed(self, p_term, predicate): def p_pkg_originator(self, p_term, predicate): for _s, _p, o in self.graph.triples((p_term, predicate, None)): try: - if o == "NOASSERTION": - self.builder.set_pkg_originator(self.doc, utils.NoAssert()) + originator = self.to_special_value(o) + if isinstance(originator, (utils.NoAssert, utils.SPDXNone, utils.UnKnown)): + self.builder.set_pkg_originator(self.doc, originator) else: - ent = self.builder.create_entity(self.doc, str(o)) + ent = self.builder.create_entity(self.doc, originator) self.builder.set_pkg_originator(self.doc, ent) except CardinalityError: self.more_than_one_error("Package originator") @@ -575,10 +576,11 @@ def p_pkg_originator(self, p_term, predicate): def p_pkg_suppl(self, p_term, predicate): for _s, _p, o in self.graph.triples((p_term, predicate, None)): try: - if o == "NOASSERTION": - self.builder.set_pkg_supplier(self.doc, utils.NoAssert()) + supplier = self.to_special_value(o) + if isinstance(supplier, (utils.NoAssert, utils.SPDXNone, utils.UnKnown)): + self.builder.set_pkg_supplier(self.doc, supplier) else: - ent = self.builder.create_entity(self.doc, str(o)) + ent = self.builder.create_entity(self.doc, supplier) self.builder.set_pkg_supplier(self.doc, ent) except CardinalityError: self.more_than_one_error("Package supplier") diff --git a/tests/data/doc_parse/spdx-expected.json b/tests/data/doc_parse/spdx-expected.json index 8eae8942d..556950a28 100644 --- a/tests/data/doc_parse/spdx-expected.json +++ b/tests/data/doc_parse/spdx-expected.json @@ -128,11 +128,7 @@ "email": null, "type": "Organization" }, - "supplier": { - "name": "Linux Foundation", - "email": null, - "type": "Organization" - }, + "supplier": "NOASSERTION", "licenseConcluded": { "type": "Conjunction", "identifier": [ diff --git a/tests/data/formats/SPDXRdfExample.rdf b/tests/data/formats/SPDXRdfExample.rdf index d5912d8a8..abe96a2a5 100644 --- a/tests/data/formats/SPDXRdfExample.rdf +++ b/tests/data/formats/SPDXRdfExample.rdf @@ -155,7 +155,7 @@ http://www.spdx.org/tools true - Organization:Linux Foundation + NOASSERTION diff --git a/tests/utils_test.py b/tests/utils_test.py index 48b262b2c..c1a7b8abb 100644 --- a/tests/utils_test.py +++ b/tests/utils_test.py @@ -313,6 +313,8 @@ def entity_to_dict(cls, entity): """ if entity is None: return None + if isinstance(entity, utils.NoAssert): + return entity.to_value() entity_dict = OrderedDict(name=entity.name) if isinstance(entity, spdx.creationinfo.Tool): From c73ad31b4b7acea7bf728c83c914d188214fc309 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 14 Feb 2023 15:08:30 +0100 Subject: [PATCH 014/354] add missing error messages for LicenseListVersion Signed-off-by: Meret Behrens --- spdx/parsers/tagvalue.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spdx/parsers/tagvalue.py b/spdx/parsers/tagvalue.py index bf2e937af..e3ecffd7e 100644 --- a/spdx/parsers/tagvalue.py +++ b/spdx/parsers/tagvalue.py @@ -37,6 +37,8 @@ "DOC_VERSION_VALUE_TYPE": "Invalid SPDXVersion value, must be SPDX-M.N where M and N are numbers. Line: {0}", "DOC_NAME_VALUE": "DocumentName must be single line of text, line: {0}", "DOC_SPDX_ID_VALUE": "Invalid SPDXID value, SPDXID must be SPDXRef-DOCUMENT, line: {0}", + "LIC_LIST_VER_VALUE": "Invalid LicenseListVersion '{0}', must be of type M.N where M and N are numbers. Line: {1}", + "LIC_LIST_VER_VALUE_TYPE": "Could not read value after LicenseListVersion-tag. Line{0}", "EXT_DOC_REF_VALUE": "ExternalDocumentRef must contain External Document ID, SPDX Document URI and Checksum" "in the standard format, line:{0}.", "DOC_COMMENT_VALUE_TYPE": "DocumentComment value must be free form text between tags" From 9858d218dfa1f5e7ae560f78bad59bfd28961c25 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 14 Feb 2023 15:11:14 +0100 Subject: [PATCH 015/354] fix parsing of whitespaces Without this fix lines that contain a whitespace and a line break were not taken into account when counting the lines. This lead to a mismatch in the line number printed within the error message and the actual falsy line. Signed-off-by: Meret Behrens --- spdx/parsers/lexers/tagvalue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spdx/parsers/lexers/tagvalue.py b/spdx/parsers/lexers/tagvalue.py index 61a99adff..e67ff366e 100644 --- a/spdx/parsers/lexers/tagvalue.py +++ b/spdx/parsers/lexers/tagvalue.py @@ -235,7 +235,7 @@ def t_newline(self, t): t.lexer.lineno += len(t.value) def t_whitespace(self, t): - r"\s+" + r"\s" pass def build(self, **kwargs): From f12b5f8d8630bd52a18f9268c8b18f73768cf8bf Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 15 Feb 2023 12:44:04 +0100 Subject: [PATCH 016/354] [issue-465] correct regex to match spaces or tabs and add a test for this Signed-off-by: Meret Behrens --- spdx/parsers/lexers/tagvalue.py | 2 +- tests/test_tag_value_parser.py | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/spdx/parsers/lexers/tagvalue.py b/spdx/parsers/lexers/tagvalue.py index e67ff366e..4421bae63 100644 --- a/spdx/parsers/lexers/tagvalue.py +++ b/spdx/parsers/lexers/tagvalue.py @@ -235,7 +235,7 @@ def t_newline(self, t): t.lexer.lineno += len(t.value) def t_whitespace(self, t): - r"\s" + r"[ \t]+" pass def build(self, **kwargs): diff --git a/tests/test_tag_value_parser.py b/tests/test_tag_value_parser.py index 6ce4af7c9..00be54bb9 100644 --- a/tests/test_tag_value_parser.py +++ b/tests/test_tag_value_parser.py @@ -115,6 +115,9 @@ 'SPDXREF: SPDXRef-DOCUMENT' ]) +document_str_with_empty_line = "\n".join( + ['SPDXVersion: SPDX-2.1', ' ', 'DataLicense: CC0-1.0']) + class TestLexer(TestCase): maxDiff = None @@ -291,6 +294,14 @@ def test_annotation(self): self.token_assert_helper(self.l.token(), 'ANNOTATION_SPDX_ID', 'SPDXREF', 5) self.token_assert_helper(self.l.token(), 'LINE', 'SPDXRef-DOCUMENT', 5) + def test_correct_line_number_with_empty_line_between(self): + data = document_str_with_empty_line + self.l.input(data) + self.token_assert_helper(self.l.token(), 'DOC_VERSION', 'SPDXVersion', 1) + self.token_assert_helper(self.l.token(), 'LINE', 'SPDX-2.1', 1) + self.token_assert_helper(self.l.token(), 'DOC_LICENSE', 'DataLicense', 3) + self.token_assert_helper(self.l.token(), 'LINE', 'CC0-1.0', 3) + def token_assert_helper(self, token, ttype, value, line): assert token.type == ttype assert token.value == value From c2fe2375988f9066b678fb14ea015138772f290f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 1 Mar 2023 12:34:14 +0100 Subject: [PATCH 017/354] [issue-496] fix SPDXJsonExampleEmptyArrays.json test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../formats/SPDXJsonExampleEmptyArrays.json | 25 +++---------------- tests/test_write_anything.py | 5 +--- 2 files changed, 4 insertions(+), 26 deletions(-) diff --git a/tests/data/formats/SPDXJsonExampleEmptyArrays.json b/tests/data/formats/SPDXJsonExampleEmptyArrays.json index 5d8cee207..c9b84decb 100644 --- a/tests/data/formats/SPDXJsonExampleEmptyArrays.json +++ b/tests/data/formats/SPDXJsonExampleEmptyArrays.json @@ -15,34 +15,15 @@ "description" : "Coverlet is a cross platform code coverage library for .NET, with support for line, branch and method coverage.", "downloadLocation" : "https://api.nuget.org/packages/coverlet.collector.3.2.0.nupkg", "filesAnalyzed" : false, - "hasFiles" : [ ], + "hasFiles" : [], "homepage" : "https://github.com/coverlet-coverage/coverlet", "licenseConcluded" : "(MIT)", "licenseDeclared" : "(MIT)", - "licenseInfoFromFiles" : [ ], + "licenseInfoFromFiles" : [], "name" : "coverlet.collector.3.2.0.nupkg", "originator" : "Organization: tonerdo", "packageFileName" : "coverlet.collector.3.2.0.nupkg", - "supplier" : "Organization: tonerdo", - "versionInfo" : "3.2.0" - }, - { - "SPDXID" : "SPDXRef-2269-coverlet.collector.3.2.0.nupkg", - "checksums" : [ { - "algorithm" : "SHA1", - "checksumValue" : "0cf7564fcbdee13f6313edd8bc261ca0564a4bf7" - } ], - "copyrightText" : "NOASSERTION", - "description" : "Coverlet is a cross platform code coverage library for .NET, with support for line, branch and method coverage.", - "downloadLocation" : "https://api.nuget.org/packages/coverlet.collector.3.2.0.nupkg", - "filesAnalyzed" : false, - "homepage" : "https://github.com/coverlet-coverage/coverlet", - "licenseConcluded" : "(MIT)", - "licenseDeclared" : "(MIT)", - "name" : "coverlet.collector.3.2.0.nupkg", - "originator" : "Organization: tonerdo", - "packageFileName" : "coverlet.collector.3.2.0.nupkg", - "supplier" : "Organization: tonerdo", + "supplier" : "NOASSERTION", "versionInfo" : "3.2.0" } ], diff --git a/tests/test_write_anything.py b/tests/test_write_anything.py index 5fe034dd9..5f3c8b915 100644 --- a/tests/test_write_anything.py +++ b/tests/test_write_anything.py @@ -35,10 +35,7 @@ "SPDXXMLExample-v2.2.spdx.xml-tag", "SPDXYAMLExample-2.3.spdx.yaml-tag", "SPDXJSONExample-v2.3.spdx.json-tag", - "SPDXXMLExample-v2.3.spdx.xml-tag", - "SPDXJsonExampleEmptyArrays.json-json", - "SPDXJsonExampleEmptyArrays.json-xml", - "SPDXJsonExampleEmptyArrays.json-yaml" + "SPDXXMLExample-v2.3.spdx.xml-tag" } From bbf101f1dd895f0960f413a7d93c35cca378da2d Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 1 Mar 2023 13:53:13 +0100 Subject: [PATCH 018/354] [issue-479] fix parsing of package version that looks like a range value Signed-off-by: Meret Behrens --- spdx/parsers/lexers/tagvalue.py | 4 ---- spdx/parsers/tagvalue.py | 8 ++++---- spdx/parsers/tagvaluebuilders.py | 14 ++++++++++---- tests/test_builder.py | 10 ++++++++++ tests/test_tag_value_parser.py | 12 ++++++------ 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/spdx/parsers/lexers/tagvalue.py b/spdx/parsers/lexers/tagvalue.py index 4421bae63..deafd7186 100644 --- a/spdx/parsers/lexers/tagvalue.py +++ b/spdx/parsers/lexers/tagvalue.py @@ -137,7 +137,6 @@ class Lexer(object): "PERSON_VALUE", "DATE", "LINE", - "RANGE", "CHKSUM", "DOC_REF_ID", "DOC_URI", @@ -219,9 +218,6 @@ def t_LINE_OR_KEYWORD_VALUE(self, t): if t.value in self.reserved.keys(): t.type = self.reserved[t.value] return t - range_pattern = re.compile("\d+:\d(?!\D)") - if range_pattern.match(t.value): - t.type = "RANGE" else: t.type = "LINE" return t diff --git a/spdx/parsers/tagvalue.py b/spdx/parsers/tagvalue.py index e3ecffd7e..8a3b0d170 100644 --- a/spdx/parsers/tagvalue.py +++ b/spdx/parsers/tagvalue.py @@ -1393,9 +1393,9 @@ def p_snippet_lics_info_1(self, p): self.logger.log(msg) def p_snippet_byte_range(self, p): - """snip_byte_range : SNIPPET_BYTE_RANGE RANGE""" + """snip_byte_range : SNIPPET_BYTE_RANGE LINE""" try: - self.builder.set_snippet_byte_range(self.document, p[2]) + self.builder.set_snippet_byte_range(self.document, p[2].strip()) except OrderError: self.order_error("SnippetByteRange", "SnippetSPDXID", p.lineno(1)) except SPDXValueError: @@ -1411,9 +1411,9 @@ def p_snippet_byte_range_1(self, p): self.logger.log(msg) def p_snippet_line_range(self, p): - """snip_line_range : SNIPPET_LINE_RANGE RANGE""" + """snip_line_range : SNIPPET_LINE_RANGE LINE""" try: - self.builder.set_snippet_line_range(self.document, p[2]) + self.builder.set_snippet_line_range(self.document, p[2].strip()) except OrderError: self.order_error("SnippetLineRange", "SnippetSPDXID", p.lineno(1)) except SPDXValueError: diff --git a/spdx/parsers/tagvaluebuilders.py b/spdx/parsers/tagvaluebuilders.py index 2d380ead6..f99fde3e8 100644 --- a/spdx/parsers/tagvaluebuilders.py +++ b/spdx/parsers/tagvaluebuilders.py @@ -1614,8 +1614,11 @@ def set_snippet_byte_range(self, doc, parsed): Raise SPDXValueError if the data is malformed. """ self.assert_snippet_exists() - startpoint = int(parsed.split(":")[0]) - endpoint = int(parsed.split(":")[-1]) + range_re = re.compile(r"^(\d+):(\d+)$", re.UNICODE) + if not range_re.match(parsed): + raise SPDXValueError("Snippet:ByteRange") + startpoint = int(range_re.match(parsed).group(1)) + endpoint = int(range_re.match(parsed).group(2)) if startpoint <= endpoint: doc.snippet[-1].byte_range = (startpoint, endpoint) else: @@ -1627,8 +1630,11 @@ def set_snippet_line_range(self, doc, parsed): Raise SPDXValueError if the data is malformed. """ self.assert_snippet_exists() - startpoint = int(parsed.split(":")[0]) - endpoint = int(parsed.split(":")[-1]) + range_re = re.compile(r"^(\d+):(\d+)$", re.UNICODE) + if not range_re.match(parsed): + raise SPDXValueError("Snippet:LineRange") + startpoint = int(range_re.match(parsed).group(1)) + endpoint = int(range_re.match(parsed).group(2)) if startpoint <= endpoint: doc.snippet[-1].line_range = (startpoint, endpoint) else: diff --git a/tests/test_builder.py b/tests/test_builder.py index d88024d31..50c6cf7f4 100644 --- a/tests/test_builder.py +++ b/tests/test_builder.py @@ -823,6 +823,11 @@ def test_snippet_byte_range_value(self): self.builder.create_snippet(self.document, "SPDXRef-Snippet") self.builder.set_snippet_byte_range(self.document, "310:30") + @testing_utils.raises(builders.SPDXValueError) + def test_snippet_byte_range_value_wrong_format(self): + self.builder.create_snippet(self.document, "SPDXRef-Snippet") + self.builder.set_snippet_byte_range(self.document, "30") + def test_snippet_line_range(self): self.builder.create_snippet(self.document, "SPDXRef-Snippet") self.builder.set_snippet_line_range(self.document, "5:23") @@ -835,3 +840,8 @@ def test_snippet_line_range_order(self): def test_snippet_line_range_value(self): self.builder.create_snippet(self.document, "SPDXRef-Snippet") self.builder.set_snippet_line_range(self.document, "23:5") + + @testing_utils.raises(builders.SPDXValueError) + def test_snippet_line_range_value_wrong_format(self): + self.builder.create_snippet(self.document, "SPDXRef-Snippet") + self.builder.set_snippet_line_range(self.document, "5:23d") diff --git a/tests/test_tag_value_parser.py b/tests/test_tag_value_parser.py index 00be54bb9..2c5ad293b 100644 --- a/tests/test_tag_value_parser.py +++ b/tests/test_tag_value_parser.py @@ -50,7 +50,7 @@ package_str = '\n'.join([ 'PackageName: Test', 'SPDXID: SPDXRef-Package', - 'PackageVersion: 1:2.36.1-8+deb11u1', + 'PackageVersion: 1:22.36.1-8+deb11u1', 'PackageDownloadLocation: http://example.com/test', 'FilesAnalyzed: True', 'PackageSummary: Test package', @@ -103,7 +103,7 @@ 'SnippetFromFileSPDXID: SPDXRef-DoapSource', 'SnippetLicenseConcluded: Apache-2.0', 'LicenseInfoInSnippet: Apache-2.0', - 'SnippetByteRange: 310:420', + 'SnippetByteRange: 310:420 ', 'SnippetLineRange: 5:7', ]) @@ -198,7 +198,7 @@ def test_package(self): self.token_assert_helper(self.l.token(), 'SPDX_ID', 'SPDXID', 2) self.token_assert_helper(self.l.token(), 'LINE', 'SPDXRef-Package', 2) self.token_assert_helper(self.l.token(), 'PKG_VERSION', 'PackageVersion', 3) - self.token_assert_helper(self.l.token(), 'LINE', '1:2.36.1-8+deb11u1', 3) + self.token_assert_helper(self.l.token(), 'LINE', '1:22.36.1-8+deb11u1', 3) self.token_assert_helper(self.l.token(), 'PKG_DOWN', 'PackageDownloadLocation', 4) self.token_assert_helper(self.l.token(), 'LINE', 'http://example.com/test', 4) self.token_assert_helper(self.l.token(), 'PKG_FILES_ANALYZED', 'FilesAnalyzed', 5) @@ -276,9 +276,9 @@ def test_snippet(self): 'LicenseInfoInSnippet', 8) self.token_assert_helper(self.l.token(), 'LINE', 'Apache-2.0', 8) self.token_assert_helper(self.l.token(), 'SNIPPET_BYTE_RANGE', 'SnippetByteRange', 9) - self.token_assert_helper(self.l.token(), 'RANGE', '310:420', 9) + self.token_assert_helper(self.l.token(), 'LINE', '310:420', 9) self.token_assert_helper(self.l.token(), 'SNIPPET_LINE_RANGE', 'SnippetLineRange', 10) - self.token_assert_helper(self.l.token(), 'RANGE', '5:7', 10) + self.token_assert_helper(self.l.token(), 'LINE', '5:7', 10) def test_annotation(self): data = annotation_str @@ -348,7 +348,7 @@ def test_package(self): assert not error assert document.package.name == 'Test' assert document.package.spdx_id == 'SPDXRef-Package' - assert document.package.version == '1:2.36.1-8+deb11u1' + assert document.package.version == '1:22.36.1-8+deb11u1' assert len(document.package.licenses_from_files) == 2 assert (document.package.conc_lics.identifier == 'LicenseRef-2.0 AND Apache-2.0') assert document.package.files_analyzed is True From 94647984a0d0a949ad193523578cc7f29d5f0782 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 15 Feb 2023 14:39:09 +0100 Subject: [PATCH 019/354] add GitHub Actions workflow Signed-off-by: Meret Behrens --- .github/workflows/install_and_test.yml | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/install_and_test.yml diff --git a/.github/workflows/install_and_test.yml b/.github/workflows/install_and_test.yml new file mode 100644 index 000000000..c8ceae43e --- /dev/null +++ b/.github/workflows/install_and_test.yml @@ -0,0 +1,32 @@ +name: Install and Test + +on: [ workflow_dispatch, pull_request ] + +jobs: + install_and_test: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-latest, macos-latest, windows-latest ] + python-version: [ "3.7", "3.8", "3.9", "3.10" ] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Installation + run: | + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools wheel setuptools_scm build + python -m build -nwx . + python -m pip install --upgrade ./dist/*.whl + python -m pip install pytest + shell: bash + - name: Run tests + run: pytest + - name: Run CLI + run: | + pyspdxtools_parser --file ./tests/data/formats/SPDXJSONExample-v2.3.spdx.json + pyspdxtools_convertor --infile ./tests/data/formats/SPDXTagExample-v2.3.spdx -o temp.json From 2c8e46b079dfbaa985d849fe4585714e1a9efd19 Mon Sep 17 00:00:00 2001 From: Maximilian Huber Date: Fri, 3 Mar 2023 14:35:40 +0100 Subject: [PATCH 020/354] add more maintainers and authors to pyproject.toml Signed-off-by: Maximilian Huber --- pyproject.toml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 64b45b806..5605ad7c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,9 +4,16 @@ build-backend = "setuptools.build_meta" [project] name = "spdx-tools" -authors = [{name = "Ahmed H. Ismail", email = "ahm3d.hisham@gmail.com"}] +authors = [ + {name = "Ahmed H. Ismail", email = "ahm3d.hisham@gmail.com"}, + {name = "Armin Tänzer", email = "armin.taenzer@tngtech.com"}, + {name = "Meret Behrens", email = "meret.behrens@tngtech.com"}, + {name = "Maximilian Huber", email = "maximilian.huber@tngtech.com"} +] maintainers = [ {name = "Philippe Ombredanne", email = "pombredanne@gmail.com"}, + {name = "Maximilian Huber", email = "maximilian.huber@tngtech.com"}, + {name = "Jeff Licquia", email = "licquia@linuxfoundation.org"}, {name = "SPDX group at the Linux Foundation and others"}, ] license = {text = "Apache-2.0"} From df258b2d2e6d33b518286e51858d7d749cca4c97 Mon Sep 17 00:00:00 2001 From: Marc-Etienne Vargenau Date: Tue, 7 Mar 2023 11:38:27 +0100 Subject: [PATCH 021/354] Remove multiple identical LicenseInfoInFile Fix #508 Signed-off-by: Marc-Etienne Vargenau --- spdx/writers/tagvalue.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spdx/writers/tagvalue.py b/spdx/writers/tagvalue.py index 8e734bf7f..dca2b2a17 100644 --- a/spdx/writers/tagvalue.py +++ b/spdx/writers/tagvalue.py @@ -135,8 +135,11 @@ def write_file(spdx_file, out): else: write_value("LicenseConcluded", spdx_file.conc_lics, out) + # remove duplicates + lics_in_file = [] + [lics_in_file.append(x) for x in spdx_file.licenses_in_file if x not in lics_in_file] # write sorted list - for lics in sorted(spdx_file.licenses_in_file): + for lics in sorted(lics_in_file): write_value("LicenseInfoInFile", lics, out) if spdx_file.has_optional_field("copyright"): From b0d946b354045ae4e01398f416ee7abbabfe8443 Mon Sep 17 00:00:00 2001 From: Marc-Etienne Vargenau Date: Tue, 7 Mar 2023 13:06:09 +0100 Subject: [PATCH 022/354] Adding SPDX-License-Identifier in source code files. Fix #511 Signed-off-by: Marc-Etienne Vargenau --- examples/__init__.py | 1 + examples/tv_to_rdf.py | 2 +- spdx/annotation.py | 1 + spdx/checksum.py | 1 + spdx/cli_tools/__init__.py | 1 + spdx/cli_tools/convertor.py | 1 + spdx/cli_tools/parser.py | 1 + spdx/config.py | 1 + spdx/creationinfo.py | 1 + spdx/document.py | 1 + spdx/file.py | 1 + spdx/license.py | 1 + spdx/package.py | 1 + spdx/parsers/__init__.py | 1 + spdx/parsers/builderexceptions.py | 1 + spdx/parsers/jsonparser.py | 1 + spdx/parsers/jsonyamlxml.py | 1 + spdx/parsers/jsonyamlxmlbuilders.py | 1 + spdx/parsers/lexers/tagvalue.py | 1 + spdx/parsers/loggers.py | 1 + spdx/parsers/parse_anything.py | 1 + spdx/parsers/rdf.py | 1 + spdx/parsers/rdfbuilders.py | 1 + spdx/parsers/tagvalue.py | 1 + spdx/parsers/tagvaluebuilders.py | 1 + spdx/parsers/validations.py | 1 + spdx/parsers/xmlparser.py | 1 + spdx/parsers/yamlparser.py | 1 + spdx/relationship.py | 2 +- spdx/review.py | 1 + spdx/snippet.py | 1 + spdx/utils.py | 1 + spdx/version.py | 1 + spdx/writers/json.py | 1 + spdx/writers/jsonyamlxml.py | 1 + spdx/writers/rdf.py | 1 + spdx/writers/tagvalue.py | 1 + spdx/writers/write_anything.py | 1 + spdx/writers/xml.py | 1 + spdx/writers/yaml.py | 1 + tests/test_builder.py | 1 + tests/test_checksum.py | 1 + tests/test_cli_convertor.py | 1 + tests/test_config.py | 2 +- tests/test_conversion.py | 2 +- tests/test_creationinfo.py | 2 +- tests/test_document.py | 1 + tests/test_error_messages.py | 1 + tests/test_jsonyamlxml_parser.py | 2 +- tests/test_package.py | 1 + tests/test_parse_anything.py | 1 + tests/test_parsers_validation.py | 2 +- tests/test_rdf_parser.py | 2 +- tests/test_tag_value_parser.py | 1 + tests/test_write_anything.py | 1 + tests/testing_utils.py | 1 + tests/utils_test.py | 1 + 57 files changed, 57 insertions(+), 8 deletions(-) diff --git a/examples/__init__.py b/examples/__init__.py index 1f63eb496..c556ae14f 100644 --- a/examples/__init__.py +++ b/examples/__init__.py @@ -1,4 +1,5 @@ # Copyright (c) 2020 Yash Varshney +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/examples/tv_to_rdf.py b/examples/tv_to_rdf.py index db890961e..d73c80ce5 100755 --- a/examples/tv_to_rdf.py +++ b/examples/tv_to_rdf.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (C) 2017 BMW AG # Author: Thomas Hafner -# +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/annotation.py b/spdx/annotation.py index 51cff82d9..7e4b0fefa 100644 --- a/spdx/annotation.py +++ b/spdx/annotation.py @@ -1,4 +1,5 @@ # Copyright (c) 2018 Yash M. Nisar +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/checksum.py b/spdx/checksum.py index 634a59ad5..73bb79de3 100644 --- a/spdx/checksum.py +++ b/spdx/checksum.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/cli_tools/__init__.py b/spdx/cli_tools/__init__.py index 1f63eb496..c556ae14f 100644 --- a/spdx/cli_tools/__init__.py +++ b/spdx/cli_tools/__init__.py @@ -1,4 +1,5 @@ # Copyright (c) 2020 Yash Varshney +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/cli_tools/convertor.py b/spdx/cli_tools/convertor.py index 04e96af72..261ba1c14 100644 --- a/spdx/cli_tools/convertor.py +++ b/spdx/cli_tools/convertor.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2020 Yash Varshney +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/cli_tools/parser.py b/spdx/cli_tools/parser.py index aad96d1c2..e458b6e3e 100755 --- a/spdx/cli_tools/parser.py +++ b/spdx/cli_tools/parser.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2020 Yash Varshney +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/config.py b/spdx/config.py index a10582043..0eb2efed1 100644 --- a/spdx/config.py +++ b/spdx/config.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/creationinfo.py b/spdx/creationinfo.py index eca9cbe37..6e71c2e90 100644 --- a/spdx/creationinfo.py +++ b/spdx/creationinfo.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/document.py b/spdx/document.py index 3175df40e..e610a5081 100644 --- a/spdx/document.py +++ b/spdx/document.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/file.py b/spdx/file.py index bab50e2ad..d63e40e06 100644 --- a/spdx/file.py +++ b/spdx/file.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/license.py b/spdx/license.py index ea973f5fd..08fc596fe 100644 --- a/spdx/license.py +++ b/spdx/license.py @@ -1,4 +1,5 @@ # Copyright (c) 2022 spdx contributors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/package.py b/spdx/package.py index 93b62e2cd..4e96e1b53 100644 --- a/spdx/package.py +++ b/spdx/package.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/__init__.py b/spdx/parsers/__init__.py index 588b404ec..1d59a27e0 100644 --- a/spdx/parsers/__init__.py +++ b/spdx/parsers/__init__.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/builderexceptions.py b/spdx/parsers/builderexceptions.py index fe03f8d51..b70aa93de 100644 --- a/spdx/parsers/builderexceptions.py +++ b/spdx/parsers/builderexceptions.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/jsonparser.py b/spdx/parsers/jsonparser.py index 5436a6798..d9e404cce 100644 --- a/spdx/parsers/jsonparser.py +++ b/spdx/parsers/jsonparser.py @@ -1,4 +1,5 @@ # Copyright (c) Xavier Figueroa +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/jsonyamlxml.py b/spdx/parsers/jsonyamlxml.py index 5d27ae9a9..0220c69c1 100644 --- a/spdx/parsers/jsonyamlxml.py +++ b/spdx/parsers/jsonyamlxml.py @@ -1,4 +1,5 @@ # Copyright (c) Xavier Figueroa +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/jsonyamlxmlbuilders.py b/spdx/parsers/jsonyamlxmlbuilders.py index 94d464edc..306b84990 100644 --- a/spdx/parsers/jsonyamlxmlbuilders.py +++ b/spdx/parsers/jsonyamlxmlbuilders.py @@ -1,4 +1,5 @@ # Copyright (c) Xavier Figueroa +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/lexers/tagvalue.py b/spdx/parsers/lexers/tagvalue.py index deafd7186..5368587db 100644 --- a/spdx/parsers/lexers/tagvalue.py +++ b/spdx/parsers/lexers/tagvalue.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/loggers.py b/spdx/parsers/loggers.py index a74715f77..c22acb120 100644 --- a/spdx/parsers/loggers.py +++ b/spdx/parsers/loggers.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/parse_anything.py b/spdx/parsers/parse_anything.py index 906337fff..523caebbe 100644 --- a/spdx/parsers/parse_anything.py +++ b/spdx/parsers/parse_anything.py @@ -1,4 +1,5 @@ # Copyright (c) spdx contributors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/rdf.py b/spdx/parsers/rdf.py index 94841127d..9580ed02a 100644 --- a/spdx/parsers/rdf.py +++ b/spdx/parsers/rdf.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/rdfbuilders.py b/spdx/parsers/rdfbuilders.py index c7845ae4d..cc5afdf84 100644 --- a/spdx/parsers/rdfbuilders.py +++ b/spdx/parsers/rdfbuilders.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/tagvalue.py b/spdx/parsers/tagvalue.py index 8a3b0d170..23b71779a 100644 --- a/spdx/parsers/tagvalue.py +++ b/spdx/parsers/tagvalue.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/tagvaluebuilders.py b/spdx/parsers/tagvaluebuilders.py index f99fde3e8..77c98d9e8 100644 --- a/spdx/parsers/tagvaluebuilders.py +++ b/spdx/parsers/tagvaluebuilders.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/validations.py b/spdx/parsers/validations.py index f93112306..f910795f3 100644 --- a/spdx/parsers/validations.py +++ b/spdx/parsers/validations.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/xmlparser.py b/spdx/parsers/xmlparser.py index d57d8175e..58b8befc4 100644 --- a/spdx/parsers/xmlparser.py +++ b/spdx/parsers/xmlparser.py @@ -1,4 +1,5 @@ # Copyright (c) Xavier Figueroa +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/parsers/yamlparser.py b/spdx/parsers/yamlparser.py index 1130e1ca7..a624d6085 100644 --- a/spdx/parsers/yamlparser.py +++ b/spdx/parsers/yamlparser.py @@ -1,4 +1,5 @@ # Copyright (c) Xavier Figueroa +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/relationship.py b/spdx/relationship.py index 5eaa62fa3..9fbceec86 100644 --- a/spdx/relationship.py +++ b/spdx/relationship.py @@ -1,5 +1,5 @@ # Copyright (c) 2020 Yash Varshney - +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/review.py b/spdx/review.py index 42c4982ee..deec8b705 100644 --- a/spdx/review.py +++ b/spdx/review.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/snippet.py b/spdx/snippet.py index cd79e3b55..1129c4ad3 100644 --- a/spdx/snippet.py +++ b/spdx/snippet.py @@ -1,4 +1,5 @@ # Copyright (c) 2018 Yash M. Nisar +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/utils.py b/spdx/utils.py index 3695cd0bd..ebce59285 100644 --- a/spdx/utils.py +++ b/spdx/utils.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/version.py b/spdx/version.py index 8be8e7ddc..dae2ffe6b 100644 --- a/spdx/version.py +++ b/spdx/version.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/writers/json.py b/spdx/writers/json.py index a2b226fdf..745b5b5e0 100644 --- a/spdx/writers/json.py +++ b/spdx/writers/json.py @@ -1,4 +1,5 @@ # Copyright (c) Xavier Figueroa +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/writers/jsonyamlxml.py b/spdx/writers/jsonyamlxml.py index d36e21112..bb4bd44e3 100644 --- a/spdx/writers/jsonyamlxml.py +++ b/spdx/writers/jsonyamlxml.py @@ -1,4 +1,5 @@ # Copyright (c) Xavier Figueroa +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/writers/rdf.py b/spdx/writers/rdf.py index 7e2b898f7..6622072be 100644 --- a/spdx/writers/rdf.py +++ b/spdx/writers/rdf.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/writers/tagvalue.py b/spdx/writers/tagvalue.py index dca2b2a17..66ed212c8 100644 --- a/spdx/writers/tagvalue.py +++ b/spdx/writers/tagvalue.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/writers/write_anything.py b/spdx/writers/write_anything.py index 63a4f4c3b..94ed8f06a 100644 --- a/spdx/writers/write_anything.py +++ b/spdx/writers/write_anything.py @@ -1,4 +1,5 @@ # Copyright (c) spdx contributors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/writers/xml.py b/spdx/writers/xml.py index 14bbd4b99..3e280eece 100644 --- a/spdx/writers/xml.py +++ b/spdx/writers/xml.py @@ -1,4 +1,5 @@ # Copyright (c) the SPDX tools authors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/spdx/writers/yaml.py b/spdx/writers/yaml.py index 2ccc6884d..37092d309 100644 --- a/spdx/writers/yaml.py +++ b/spdx/writers/yaml.py @@ -1,4 +1,5 @@ # Copyright (c) Xavier Figueroa +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_builder.py b/tests/test_builder.py index 50c6cf7f4..bf72626e5 100644 --- a/tests/test_builder.py +++ b/tests/test_builder.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_checksum.py b/tests/test_checksum.py index befba2033..b484e7441 100644 --- a/tests/test_checksum.py +++ b/tests/test_checksum.py @@ -1,4 +1,5 @@ # Copyright (c) 2022 spdx contributors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_cli_convertor.py b/tests/test_cli_convertor.py index 11413b933..00b2e0482 100644 --- a/tests/test_cli_convertor.py +++ b/tests/test_cli_convertor.py @@ -1,4 +1,5 @@ # Copyright (c) 2022 spdx tool contributors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_config.py b/tests/test_config.py index 28dab95b3..940f858e7 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -1,5 +1,5 @@ - # Copyright (c) the SPDX tools authors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_conversion.py b/tests/test_conversion.py index 4d61300d1..793d1951d 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -1,5 +1,5 @@ - # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_creationinfo.py b/tests/test_creationinfo.py index 16201829c..ed8048bcf 100644 --- a/tests/test_creationinfo.py +++ b/tests/test_creationinfo.py @@ -1,5 +1,5 @@ - # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_document.py b/tests/test_document.py index 85167ae4b..949014917 100644 --- a/tests/test_document.py +++ b/tests/test_document.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_error_messages.py b/tests/test_error_messages.py index fa57f136a..9c6141e4d 100644 --- a/tests/test_error_messages.py +++ b/tests/test_error_messages.py @@ -1,4 +1,5 @@ # Copyright (c) 2021 spdx tool contributors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_jsonyamlxml_parser.py b/tests/test_jsonyamlxml_parser.py index 4198b8eff..5a1c2d1d0 100644 --- a/tests/test_jsonyamlxml_parser.py +++ b/tests/test_jsonyamlxml_parser.py @@ -1,5 +1,5 @@ - # Copyright (c) Xavier Figueroa +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_package.py b/tests/test_package.py index 3b8325b02..6b97ea7ff 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_parse_anything.py b/tests/test_parse_anything.py index c133f9b0b..f40a0bec1 100644 --- a/tests/test_parse_anything.py +++ b/tests/test_parse_anything.py @@ -1,4 +1,5 @@ # Copyright (c) 2021 spdx tool contributors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_parsers_validation.py b/tests/test_parsers_validation.py index 4795fb6d5..3d1460b31 100644 --- a/tests/test_parsers_validation.py +++ b/tests/test_parsers_validation.py @@ -1,5 +1,5 @@ - # Copyright (c) SPDX Python tools authors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_rdf_parser.py b/tests/test_rdf_parser.py index 7963781fa..6d581b6dd 100644 --- a/tests/test_rdf_parser.py +++ b/tests/test_rdf_parser.py @@ -1,5 +1,5 @@ - # Copyright (c) the SPDX tools authors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_tag_value_parser.py b/tests/test_tag_value_parser.py index 2c5ad293b..c883c2d37 100644 --- a/tests/test_tag_value_parser.py +++ b/tests/test_tag_value_parser.py @@ -1,4 +1,5 @@ # Copyright (c) 2014 Ahmed H. Ismail +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/test_write_anything.py b/tests/test_write_anything.py index 5f3c8b915..bbfde4628 100644 --- a/tests/test_write_anything.py +++ b/tests/test_write_anything.py @@ -1,4 +1,5 @@ # Copyright (c) 2021 spdx tool contributors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/tests/testing_utils.py b/tests/testing_utils.py index 825276545..0e38221a9 100644 --- a/tests/testing_utils.py +++ b/tests/testing_utils.py @@ -3,6 +3,7 @@ # https://raw.githubusercontent.com/nose-devs/nose/7c26ad1e6b7d308cafa328ad34736d34028c122a/nose/tools/nontrivial.py # Copyright (c) 2005-2009 Jason Pellerin and others. # +# SPDX-License-Identifier: GPL-2.0-or-later # This program is free software; you can redistribute it and/or modify it under the # terms of the GNU Lesser General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later version. diff --git a/tests/utils_test.py b/tests/utils_test.py index c1a7b8abb..5e6ada81c 100644 --- a/tests/utils_test.py +++ b/tests/utils_test.py @@ -1,4 +1,5 @@ # Copyright (c) the SPDX tools authors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at From 172e4b2ac1c8af9f24dc7766f693b80aa5f0f1f4 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 10 Mar 2023 16:34:46 +0100 Subject: [PATCH 023/354] [issue-514] fix writing of multiple packages to rdf files Signed-off-by: Meret Behrens --- spdx/writers/rdf.py | 11 +------ tests/data/doc_write/rdf-simple-plus.json | 3 -- tests/data/doc_write/rdf-simple.json | 3 -- tests/test_rdf_writer.py | 39 +++++++++++++++++++++++ 4 files changed, 40 insertions(+), 16 deletions(-) diff --git a/spdx/writers/rdf.py b/spdx/writers/rdf.py index 6622072be..c64b36bc5 100644 --- a/spdx/writers/rdf.py +++ b/spdx/writers/rdf.py @@ -793,18 +793,9 @@ def create_package_node(self, package): Return a Node representing the package. Files must have been added to the graph before this method is called. """ - package_node = URIRef("http://www.spdx.org/tools#SPDXRef-Package") + package_node = URIRef(f"http://www.spdx.org/tools#{package.spdx_id}") type_triple = (package_node, RDF.type, self.spdx_namespace.Package) self.graph.add(type_triple) - # Package SPDXID - if package.spdx_id: - pkg_spdx_id = URIRef(package.spdx_id) - pkg_spdx_id_triple = ( - package_node, - self.spdx_namespace.Package, - pkg_spdx_id, - ) - self.graph.add(pkg_spdx_id_triple) # Handle optional fields: self.handle_pkg_optional_fields(package, package_node) # package name diff --git a/tests/data/doc_write/rdf-simple-plus.json b/tests/data/doc_write/rdf-simple-plus.json index d2b65aeed..9a5001156 100644 --- a/tests/data/doc_write/rdf-simple-plus.json +++ b/tests/data/doc_write/rdf-simple-plus.json @@ -6,9 +6,6 @@ "ns1:describesPackage": { "ns1:Package": { "@rdf:about": "http://www.spdx.org/tools#SPDXRef-Package", - "ns1:Package": { - "@rdf:resource": "SPDXRef-Package" - }, "ns1:hasFile": { "@rdf:resource": "http://www.spdx.org/files#SPDXRef-File" }, diff --git a/tests/data/doc_write/rdf-simple.json b/tests/data/doc_write/rdf-simple.json index 00064a345..6b1ac2dfe 100644 --- a/tests/data/doc_write/rdf-simple.json +++ b/tests/data/doc_write/rdf-simple.json @@ -6,9 +6,6 @@ "ns1:describesPackage": { "ns1:Package": { "@rdf:about": "http://www.spdx.org/tools#SPDXRef-Package", - "ns1:Package": { - "@rdf:resource": "SPDXRef-Package" - }, "ns1:hasFile": { "@rdf:resource": "http://www.spdx.org/files#SPDXRef-File" }, diff --git a/tests/test_rdf_writer.py b/tests/test_rdf_writer.py index 9153dbac6..65b03478b 100644 --- a/tests/test_rdf_writer.py +++ b/tests/test_rdf_writer.py @@ -1,4 +1,6 @@ import os +from typing import Optional +from unittest import TestCase import pytest from rdflib import URIRef @@ -62,6 +64,35 @@ def test_external_package_references(temporary_file_path) -> None: assert second_ref.category in parsed_reference_categories +# This test is really clunky since it's hard to isolate features of the rdf writer to test. Should be improved when +# that part is refactored. +def test_multiple_packages_in_one_document(temporary_file_path) -> None: + doc_node = URIRef("http://www.spdx.org/tools#SPDXRef-DOCUMENT") + document = Document() + document.creation_info.set_created_now() + package = Package() + package.spdx_id = "SPDXRef-Package" + package.version = "2.1" + document.add_package(package) + package2 = Package() + package2.spdx_id = "SPDXRef-Another-Package" + package2.version = "2.3" + document.add_package(package2) + + with open(temporary_file_path, "wb") as out: + writer = Writer(document, out) + writer.write(doc_node) + parser = Parser(Builder(), StandardLogger()) + with open(temporary_file_path, "r") as file: + parsed_document: Document = parser.parse(file)[0] + + assert len(parsed_document.packages) == 2 + first_package = get_package_by_spdx_id("SPDXRef-Package", document) + assert first_package.version == "2.1" + second_package = get_package_by_spdx_id("SPDXRef-Another-Package", document) + assert second_package.version == "2.3" + + def minimal_document_with_package() -> Document: document = Document(data_license=License.from_identifier('CC0-1.0')) document.creation_info.set_created_now() @@ -72,7 +103,15 @@ def minimal_document_with_package() -> Document: def minimal_package() -> Package: package = Package() + package.spdx_id = "SPDXRef-Package" package.conc_lics = NoAssert() package.license_declared = NoAssert() package.add_lics_from_file(NoAssert()) return package + + +def get_package_by_spdx_id(package_spdx_id: str, document: Document) -> Optional[Package]: + for package in document.packages: + if package.spdx_id == package_spdx_id: + return package + return None From 613982b7a66c0a3dd6fe58366359e17d2d99884e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 14 Mar 2023 11:38:20 +0100 Subject: [PATCH 024/354] update changelog for v0.7.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- CHANGELOG.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee72fb020..81dc51c9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,35 @@ # Changelog +## v0.7.1 (2023-03-14) + +### New features and changes + +* added GitHub Actions workflow +* added requirements.txt +* added uritools for URI validation +* Python >= 3.7 is now required +* json/yaml/xml: added support for empty arrays for hasFiles and licenseInfoFromFiles +* rdf: fixed writing of multiple packages +* tag-value: enhanced parsing of snippet ranges to not mix it up with package version +* tag-value: fixed parsing of whitespaces +* tag-value: duplicates in LicenseInfoInFile are now removed during writing +* account for supplier and originator to be NOASSERTION +* checksum validation now requires lowercase values +* during writing of a file, the encoding can be set (default is utf-8) +* license list updated to version 3.20 + +### Contributors + +This release was made possible by the following contributors. Thank you very much! + +* Christian Decker @chrisdecker1201 +* Marc-Etienne Vargenau @vargenau +* John Vandenberg @jayvdb +* Nicolaus Weidner @nicoweidner +* Meret Behrens @meretp +* Armin Tänzer @armintaenzertng +* Maximilian Huber @maxhbr + ## v0.7.0 (2022-12-08) From 0f72105af880e112e3ace20cb9667c4305b9ba61 Mon Sep 17 00:00:00 2001 From: John Speed Meyers Date: Tue, 21 Mar 2023 08:54:21 -0400 Subject: [PATCH 025/354] Change error messages related to ISO 8601 Because the SPDX specification uses a subset of ISO-8601 for datetime values, error messages that request the user use ISO-8601 dates are incorrect. These changes make clear to the user the exact format, as dictated by the SPDX spec, that dates should be specified in. Signed-off-by: John Speed Meyers --- spdx/parsers/rdf.py | 6 +++--- spdx/parsers/tagvalue.py | 12 ++++++------ spdx/utils.py | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/spdx/parsers/rdf.py b/spdx/parsers/rdf.py index 9580ed02a..1d2709fcb 100644 --- a/spdx/parsers/rdf.py +++ b/spdx/parsers/rdf.py @@ -36,7 +36,7 @@ "DOC_NAMESPACE_VALUE": 'Invalid DocumentNamespace value {0}, must contain a scheme (e.g. "https:") ' 'and should not contain the "#" delimiter.', "LL_VALUE": "Invalid licenseListVersion '{0}' must be of the format N.N where N is a number", - "CREATED_VALUE": "Invalid created value '{0}' must be date in ISO 8601 format.", + "CREATED_VALUE": "Invalid created value '{0}' is not in 'YYYY-MM-DDThh:mm:ssZ' format.", "CREATOR_VALUE": "Invalid creator value '{0}' must be Organization, Tool or Person.", "EXT_DOC_REF_VALUE": "Failed to extract {0} from ExternalDocumentRef.", "PKG_SPDX_ID_VALUE": 'SPDXID must be "SPDXRef-[idstring]" where [idstring] is a unique string containing ' @@ -56,9 +56,9 @@ "FILE_TYPE": "Unknown file type.", "FILE_SINGLE_LICS": "File concluded license must be a license url or spdx:noassertion or spdx:none.", "REVIEWER_VALUE": "Invalid reviewer value '{0}' must be Organization, Tool or Person.", - "REVIEW_DATE": "Invalid review date value '{0}' must be date in ISO 8601 format.", + "REVIEW_DATE": "Invalid review date value '{0}' is not in 'YYYY-MM-DDThh:mm:ssZ' format.", "ANNOTATOR_VALUE": "Invalid annotator value '{0}' must be Organization, Tool or Person.", - "ANNOTATION_DATE": "Invalid annotation date value '{0}' must be date in ISO 8601 format.", + "ANNOTATION_DATE": "Invalid annotation date value '{0}' is not in 'YYYY-MM-DDThh:mm:ssZ' format.", "SNIPPET_SPDX_ID_VALUE": 'SPDXID must be "SPDXRef-[idstring]" where [idstring] is a unique string ' 'containing letters, numbers, ".", "-".', "SNIPPET_SINGLE_LICS": "Snippet Concluded License must be a license url or spdx:noassertion or spdx:none.", diff --git a/spdx/parsers/tagvalue.py b/spdx/parsers/tagvalue.py index 23b71779a..edd57766b 100644 --- a/spdx/parsers/tagvalue.py +++ b/spdx/parsers/tagvalue.py @@ -28,7 +28,7 @@ "TOOL_VALUE": "Invalid tool value {0} at line: {1}", "ORG_VALUE": "Invalid organization value {0} at line: {1}", "PERSON_VALUE": "Invalid person value {0} at line: {1}", - "CREATED_VALUE_TYPE": "Created value must be date in ISO 8601 format, line: {0}", + "CREATED_VALUE_TYPE": "Created value must be in 'YYYY-MM-DDThh:mm:ssZ' format, line: {0}", "MORE_THAN_ONE": "Only one {0} allowed, extra at line: {1}", "CREATOR_COMMENT_VALUE_TYPE": "CreatorComment value must be free form text between tags or" "single line of text, line:{0}", @@ -50,11 +50,11 @@ 'and should not contain the "#" delimiter, line: {0}', "REVIEWER_VALUE_TYPE": "Invalid Reviewer value must be a Person, Organization or Tool. Line: {0}", "CREATOR_VALUE_TYPE": "Invalid Reviewer value must be a Person, Organization or Tool. Line: {0}", - "REVIEW_DATE_VALUE_TYPE": "ReviewDate value must be date in ISO 8601 format, line: {0}", + "REVIEW_DATE_VALUE_TYPE": "ReviewDate value must be in 'YYYY-MM-DDThh:mm:ssZ' format, line: {0}", "REVIEW_COMMENT_VALUE_TYPE": "ReviewComment value must be free form text between tags" "or single line of text, line:{0}", "ANNOTATOR_VALUE_TYPE": "Invalid Annotator value must be a Person, Organization or Tool. Line: {0}", - "ANNOTATION_DATE_VALUE_TYPE": "AnnotationDate value must be date in ISO 8601 format, line: {0}", + "ANNOTATION_DATE_VALUE_TYPE": "AnnotationDate value must be in 'YYYY-MM-DDThh:mm:ssZ' format, line: {0}", "ANNOTATION_COMMENT_VALUE_TYPE": "AnnotationComment value must be free form text between tags" "or single line of text, line:{0}", "ANNOTATION_TYPE_VALUE": 'AnnotationType must be "REVIEW" or "OTHER". Line: {0}', @@ -89,9 +89,9 @@ "PKG_VERF_CODE_VALUE": "VerificationCode doesn't match verifcode form, line:{0}", "PRIMARY_PACKAGE_PURPOSE_VALUE": 'PrimaryPackagePurpose must be one of APPLICATION, FRAMEWORK, LIBRARY, CONTAINER, ' 'OPERATING-SYSTEM, DEVICE, FIRMWARE, SOURCE, ARCHIVE, FILE, INSTALL, OTHER', - "BUILT_DATE_VALUE_TYPE": "Built date value must be date in ISO 8601 format, line: {0}", - "RELEASE_DATE_VALUE_TYPE": "Release date value must be date in ISO 8601 format, line: {0}", - "VALID_UNTIL_DATE_VALUE_TYPE": "Valid until date value must be date in ISO 8601 format, line: {0}", + "BUILT_DATE_VALUE_TYPE": "Built date value must be in 'YYYY-MM-DDThh:mm:ssZ' format, line: {0}", + "RELEASE_DATE_VALUE_TYPE": "Release date value must be in 'YYYY-MM-DDThh:mm:ssZ' format, line: {0}", + "VALID_UNTIL_DATE_VALUE_TYPE": "Valid until date value must be in 'YYYY-MM-DDThh:mm:ssZ' format, line: {0}", "FILE_NAME_VALUE": "FileName must be a single line of text, line: {0}", "FILE_COMMENT_VALUE": "FileComment must be free form text or single line of text, line:{0}", "FILE_TYPE_VALUE": 'FileType must be one of SOURCE, BINARY, ARCHIVE, APPLICATION, AUDIO, IMAGE, TEXT, VIDEO, ' diff --git a/spdx/utils.py b/spdx/utils.py index ebce59285..76d5e6e14 100644 --- a/spdx/utils.py +++ b/spdx/utils.py @@ -34,7 +34,7 @@ def datetime_iso_format(date): return date.isoformat() + "Z" -# Matches an iso 8601 date representation +# Matches an ISO-8601 date representation without fractional seconds DATE_ISO_REGEX = re.compile( r"(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z", re.UNICODE ) From 73f3f462591894cac8ef11e01ebec7e702e33c25 Mon Sep 17 00:00:00 2001 From: Gary O'Neall Date: Thu, 16 Mar 2023 08:43:56 -0700 Subject: [PATCH 026/354] Create dependabot.yml Signed-off-by: Gary O'Neall --- .github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..91abb11fd --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "pip" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" From 5eaa7a046de46b6c4a0210e3054554f5553fd74d Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 30 Mar 2023 08:21:14 +0200 Subject: [PATCH 027/354] [fix] adapt GitHub Action after merge to main Signed-off-by: Meret Behrens --- .github/workflows/install_and_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/install_and_test.yml b/.github/workflows/install_and_test.yml index ae48615d0..982c9089d 100644 --- a/.github/workflows/install_and_test.yml +++ b/.github/workflows/install_and_test.yml @@ -3,7 +3,7 @@ name: Install and Test on: push: branches: - - refactor-python-tools + - main pull_request: workflow_dispatch: From 5fa8b80063faa0a2c438cf5591e205889afe533f Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 30 Mar 2023 08:43:45 +0200 Subject: [PATCH 028/354] [issue-532] add GitHub Action to check the code style Signed-off-by: Meret Behrens --- .flake8 | 4 ++++ .github/workflows/check_codestyle.yml | 33 +++++++++++++++++++++++++++ CONTRIBUTING.md | 33 +++++++++++++++++++-------- pyproject.toml | 9 ++++++++ 4 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 .flake8 create mode 100644 .github/workflows/check_codestyle.yml diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..ae819fe55 --- /dev/null +++ b/.flake8 @@ -0,0 +1,4 @@ +[flake8] +max-line-length = 119 +exclude = src/spdx/parser/tagvalue/parsetab.py +extend-ignore = E203 diff --git a/.github/workflows/check_codestyle.yml b/.github/workflows/check_codestyle.yml new file mode 100644 index 000000000..aa05fce9f --- /dev/null +++ b/.github/workflows/check_codestyle.yml @@ -0,0 +1,33 @@ +name: Run Linter + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +jobs: + check_code_style: + runs-on: ${{ matrix.os }} + defaults: + run: + shell: bash + strategy: + matrix: + os: [ ubuntu-latest, macos-latest, windows-latest ] + python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11" ] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Installation + run: pip install ".[codestyle]" + - name: Check code with isort + run: | + isort src tests --check + black src tests --check + flake8 src tests diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6352e3894..653b366fa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,23 +47,36 @@ Here's the process to make changes to the codebase: of [the Developer Certificate of Origin](https://developercertificate.org/). Git has utilities for signing off on commits: `git commit -s` or `--signoff` signs a current commit, and `git rebase --signoff ` retroactively signs a range of past commits. - 6. Test your changes: ```sh - python setup.py test # in the repo root + pip install pytest + pytest -vvs # in the repo root ``` - You may use other test runners, such as `pytest` or `nose` at your preference. -7. Push the branch to your fork on GitHub: + +7. Check your code style. When opening a pull request, your changes will automatically be checked with `isort`, `black` + and `flake8` to make sure your changes fit with the rest of the code style. + ```sh + pip install .[code_style] + # run the following commands in the repo root + isort src tests + black src tests + flake8 src tests + ``` + `black` and `isort` will automatically format the code and sort the imports. The configuration for these linters + can be found in the `pyproject.toml`. `flake8` lists all problems found which then need to be resolved manually. + The configuration for the linter can be found in the `.flake8` file. + +8. Push the branch to your fork on GitHub: ```sh git push origin fix-or-improve-something ``` -8. Make a pull request on GitHub. -9. Continue making more changes and commits on the branch, with `git commit --signoff` and `git push`. -10. When done, write a comment on the PR asking for a code review. -11. Some other developer will review your changes and accept your PR. The merge should be done with `rebase`, if +9. Make a pull request on GitHub. +10. Continue making more changes and commits on the branch, with `git commit --signoff` and `git push`. +11. When done, write a comment on the PR asking for a code review. +12. Some other developer will review your changes and accept your PR. The merge should be done with `rebase`, if possible, or with `squash`. -12. The temporary branch on GitHub should be deleted (there is a button for deleting it). -13. Delete the local branch as well: +13. The temporary branch on GitHub should be deleted (there is a button for deleting it). +14. Delete the local branch as well: ```sh git checkout master git pull -p diff --git a/pyproject.toml b/pyproject.toml index dd52b43eb..b09e2d28e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,6 +29,7 @@ dynamic = ["version"] [project.optional-dependencies] test = ["pytest"] +code_style = ["isort", "black", "flake8"] [project.scripts] pyspdxtools = "spdx.clitools.pyspdxtools:main" @@ -50,3 +51,11 @@ git_describe_command = ["git", "describe", "--dirty", "--tags", "--long", "--mat [tool.aliases] release = "clean --all sdist --formats=gztar bdist_wheel" + +[tool.black] +line-length = 119 +include = "(^/src/.*.py|^/tests/.*.py)" + +[tool.isort] +profile = "black" +line_length = 119 From 487f7a99dae8715fd068b584e338dd07acd23069 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 30 Mar 2023 08:45:45 +0200 Subject: [PATCH 029/354] delete outdated configuration files Signed-off-by: Meret Behrens --- .coveragerc | 3 --- tox.ini | 25 ------------------------- 2 files changed, 28 deletions(-) delete mode 100644 .coveragerc delete mode 100644 tox.ini diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 9c27e202e..000000000 --- a/.coveragerc +++ /dev/null @@ -1,3 +0,0 @@ -[run] -branch = True -source = spdx diff --git a/tox.ini b/tox.ini deleted file mode 100644 index c46d2a3ab..000000000 --- a/tox.ini +++ /dev/null @@ -1,25 +0,0 @@ -[tox] -envlist = - py{37,38,39,310,311,py,py3} -skipsdist = True - -[testenv] -commands = - {envbindir}/python -m pip install '{toxinidir}[format]' - {envbindir}/coverage run --rcfile={toxinidir}/.coveragerc -m unittest discover -s tests - {envbindir}/coverage report --rcfile={toxinidir}/.coveragerc --show-missing - {envbindir}/coverage html --directory={envtmpdir}/htmlcov --rcfile={toxinidir}/.coveragerc {posargs} -deps = - coverage - pytest - xmltodict - -[testenv:coverage] -setenv = - COVERAGE_DEBUG_FILE={envtmpdir}/coverage-debug - COVERAGE_FILE={envtmpdir}/coverage-data -commands = - {envbindir}/python -m pip install '{toxinidir}[format]' - {envbindir}/coverage run --rcfile={toxinidir}/.coveragerc {envbindir}/trial jsonschema - {envbindir}/coverage report --rcfile={toxinidir}/.coveragerc --show-missing - {envbindir}/coverage html --directory={envtmpdir}/htmlcov --rcfile={toxinidir}/.coveragerc {posargs} From 9f9de5338d8318ef65799938799945d72cbb4595 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 28 Mar 2023 15:32:50 +0200 Subject: [PATCH 030/354] [code_style] sort imports with isort Signed-off-by: Meret Behrens --- src/spdx/document_utils.py | 7 +++-- src/spdx/jsonschema/annotation_converter.py | 2 +- src/spdx/jsonschema/converter.py | 4 +-- .../jsonschema/creation_info_converter.py | 2 +- src/spdx/jsonschema/document_converter.py | 11 +++++--- .../external_document_ref_converter.py | 2 +- .../external_package_ref_converter.py | 2 +- .../extracted_licensing_info_converter.py | 2 +- src/spdx/jsonschema/file_converter.py | 2 +- src/spdx/jsonschema/optional_utils.py | 2 +- src/spdx/jsonschema/package_converter.py | 8 +++--- .../package_verification_code_converter.py | 2 +- src/spdx/jsonschema/relationship_converter.py | 2 +- src/spdx/jsonschema/snippet_converter.py | 2 +- src/spdx/model/annotation.py | 2 +- src/spdx/model/checksum.py | 2 +- src/spdx/model/document.py | 4 +-- src/spdx/model/external_document_ref.py | 2 +- src/spdx/model/extracted_licensing_info.py | 4 +-- src/spdx/model/file.py | 9 ++++--- src/spdx/model/package.py | 9 ++++--- src/spdx/model/relationship.py | 6 ++--- src/spdx/model/snippet.py | 7 ++--- src/spdx/parser/actor_parser.py | 2 +- .../parser/jsonlikedict/annotation_parser.py | 10 +++---- .../parser/jsonlikedict/checksum_parser.py | 2 +- .../jsonlikedict/creation_info_parser.py | 16 ++++++----- .../extracted_licensing_info_parser.py | 2 +- src/spdx/parser/jsonlikedict/file_parser.py | 5 ++-- .../jsonlikedict/json_like_dict_parser.py | 4 +-- .../jsonlikedict/license_expression_parser.py | 6 ++--- .../parser/jsonlikedict/package_parser.py | 27 +++++++++++++------ .../jsonlikedict/relationship_parser.py | 12 ++++++--- .../parser/jsonlikedict/snippet_parser.py | 14 +++++----- src/spdx/parser/parse_anything.py | 2 +- src/spdx/parser/rdf/annotation_parser.py | 6 ++--- src/spdx/parser/rdf/checksum_parser.py | 2 +- src/spdx/parser/rdf/creation_info_parser.py | 15 +++++------ .../rdf/extracted_licensing_info_parser.py | 7 +++-- src/spdx/parser/rdf/file_parser.py | 12 ++++++--- .../parser/rdf/graph_parsing_functions.py | 6 ++--- .../parser/rdf/license_expression_parser.py | 8 +++--- src/spdx/parser/rdf/package_parser.py | 26 +++++++++++++----- src/spdx/parser/rdf/rdf_parser.py | 2 +- src/spdx/parser/rdf/relationship_parser.py | 12 ++++++--- src/spdx/parser/rdf/snippet_parser.py | 19 ++++++++----- src/spdx/parser/tagvalue/helper_methods.py | 2 +- src/spdx/parser/tagvalue/parser.py | 24 ++++++++++++----- src/spdx/parser/xml/xml_parser.py | 3 +-- src/spdx/validation/actor_validator.py | 2 +- src/spdx/validation/annotation_validator.py | 2 +- src/spdx/validation/checksum_validator.py | 4 +-- .../validation/creation_info_validator.py | 2 +- src/spdx/validation/document_validator.py | 2 +- .../external_document_ref_validator.py | 2 +- .../external_package_ref_validator.py | 6 ++--- .../extracted_licensing_info_validator.py | 2 +- src/spdx/validation/file_validator.py | 4 +-- .../license_expression_validator.py | 6 ++--- src/spdx/validation/package_validator.py | 6 ++--- .../package_verification_code_validator.py | 2 +- src/spdx/validation/relationship_validator.py | 2 +- src/spdx/validation/snippet_validator.py | 5 ++-- src/spdx/validation/validation_message.py | 2 +- src/spdx/writer/rdf/annotation_writer.py | 6 ++--- src/spdx/writer/rdf/checksum_writer.py | 2 +- src/spdx/writer/rdf/creation_info_writer.py | 4 +-- .../rdf/external_document_ref_writer.py | 4 +-- .../rdf/extracted_licensing_info_writer.py | 6 ++--- src/spdx/writer/rdf/file_writer.py | 8 +++--- .../writer/rdf/license_expression_writer.py | 20 +++++++++----- src/spdx/writer/rdf/package_writer.py | 23 ++++++++++------ src/spdx/writer/rdf/rdf_writer.py | 4 +-- src/spdx/writer/rdf/relationship_writer.py | 6 ++--- src/spdx/writer/rdf/snippet_writer.py | 11 ++++---- src/spdx/writer/rdf/writer_utils.py | 2 +- src/spdx/writer/tagvalue/annotation_writer.py | 2 +- .../writer/tagvalue/creation_info_writer.py | 8 ++++-- .../extracted_licensing_info_writer.py | 2 +- src/spdx/writer/tagvalue/file_writer.py | 2 +- src/spdx/writer/tagvalue/package_writer.py | 8 ++++-- .../writer/tagvalue/relationship_writer.py | 2 +- src/spdx/writer/tagvalue/snippet_writer.py | 3 ++- src/spdx/writer/tagvalue/tagvalue_writer.py | 11 +++++--- .../tagvalue_writer_helper_functions.py | 5 ++-- src/spdx/writer/write_anything.py | 5 ++-- tests/spdx/fixtures.py | 9 +++++-- tests/spdx/jsonschema/test_converter.py | 6 ++--- .../jsonschema/test_document_converter.py | 12 +++++++-- ...test_extracted_licensing_info_converter.py | 2 +- tests/spdx/jsonschema/test_file_converter.py | 8 +++--- .../spdx/jsonschema/test_package_converter.py | 20 +++++++++----- .../jsonschema/test_relationship_converter.py | 4 +-- .../spdx/jsonschema/test_snippet_converter.py | 8 +++--- tests/spdx/model/test_package.py | 2 +- tests/spdx/parser/json/test_json_parser.py | 2 ++ .../jsonlikedict/test_annotation_parser.py | 2 +- .../test_dict_parsing_functions.py | 7 +++-- .../parser/jsonlikedict/test_file_parser.py | 3 +-- .../jsonlikedict/test_package_parser.py | 4 +-- .../jsonlikedict/test_relationship_parser.py | 2 +- .../jsonlikedict/test_snippet_parser.py | 1 - tests/spdx/parser/rdf/test_checksum_parser.py | 4 +-- .../parser/rdf/test_creation_info_parser.py | 17 ++++++------ .../test_extracted_licensing_info_parser.py | 2 +- tests/spdx/parser/rdf/test_file_parser.py | 4 +-- .../parser/rdf/test_graph_parsing_function.py | 2 +- .../rdf/test_license_expression_parser.py | 5 ++-- tests/spdx/parser/rdf/test_package_parser.py | 6 ++--- .../parser/rdf/test_relationship_parser.py | 2 +- tests/spdx/parser/rdf/test_snippet_parser.py | 6 ++--- .../tagvalue/test_relationship_parser.py | 2 +- .../parser/tagvalue/test_tag_value_parser.py | 2 +- tests/spdx/test_actor_parser.py | 5 ++-- tests/spdx/test_casing_tools.py | 2 +- tests/spdx/test_document_utils.py | 4 +-- tests/spdx/validation/test_actor_validator.py | 2 +- .../validation/test_annotation_validator.py | 4 +-- .../validation/test_checksum_validator.py | 2 +- .../test_creation_info_validator.py | 2 +- .../validation/test_document_validator.py | 6 ++--- .../test_external_package_ref_validator.py | 16 ++++++++--- ...test_extracted_licensing_info_validator.py | 2 +- tests/spdx/validation/test_file_validator.py | 6 ++--- .../test_license_expression_validator.py | 5 ++-- .../spdx/validation/test_package_validator.py | 6 ++--- ...est_package_verification_code_validator.py | 2 +- .../validation/test_relationship_validator.py | 2 +- .../spdx/validation/test_snippet_validator.py | 4 +-- .../validation/test_spdx_id_validators.py | 20 +++++++++++--- tests/spdx/validation/test_uri_validators.py | 2 +- .../spdx/writer/rdf/test_annotation_writer.py | 4 +-- tests/spdx/writer/rdf/test_checksum_writer.py | 4 +-- .../writer/rdf/test_creation_info_writer.py | 4 +-- .../rdf/test_external_document_ref_writer.py | 4 +-- .../test_extracted_licensing_info_writer.py | 4 +-- tests/spdx/writer/rdf/test_file_writer.py | 4 +-- .../rdf/test_license_expression_writer.py | 4 +-- tests/spdx/writer/rdf/test_package_writer.py | 15 ++++++----- tests/spdx/writer/rdf/test_rdf_writer.py | 3 +-- .../writer/rdf/test_relationship_writer.py | 4 +-- tests/spdx/writer/rdf/test_snippet_writer.py | 6 ++--- .../tagvalue/test_creation_info_writer.py | 5 ++-- .../writer/tagvalue/test_package_writer.py | 4 +-- .../writer/tagvalue/test_tagvalue_writer.py | 2 +- .../test_tagvalue_writer_helper_functions.py | 2 +- 146 files changed, 487 insertions(+), 352 deletions(-) diff --git a/src/spdx/document_utils.py b/src/spdx/document_utils.py index 74a49faf9..b212cc77b 100644 --- a/src/spdx/document_utils.py +++ b/src/spdx/document_utils.py @@ -8,13 +8,12 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import List -from typing import Union +from typing import List, Union from spdx.model.document import Document -from spdx.model.snippet import Snippet -from spdx.model.package import Package from spdx.model.file import File +from spdx.model.package import Package +from spdx.model.snippet import Snippet def get_contained_spdx_element_ids(document: Document) -> List[str]: diff --git a/src/spdx/jsonschema/annotation_converter.py b/src/spdx/jsonschema/annotation_converter.py index c4bf4277e..24dd14465 100644 --- a/src/spdx/jsonschema/annotation_converter.py +++ b/src/spdx/jsonschema/annotation_converter.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Type, Any +from typing import Any, Type from spdx.datetime_conversions import datetime_to_iso_string from spdx.jsonschema.annotation_properties import AnnotationProperty diff --git a/src/spdx/jsonschema/converter.py b/src/spdx/jsonschema/converter.py index 4fddd4e1d..1b47ae3a0 100644 --- a/src/spdx/jsonschema/converter.py +++ b/src/spdx/jsonschema/converter.py @@ -9,11 +9,11 @@ # See the License for the specific language governing permissions and # limitations under the License. from abc import ABC, abstractmethod -from typing import Any, Type, Dict, TypeVar, Generic +from typing import Any, Dict, Generic, Type, TypeVar +from spdx.casing_tools import snake_case_to_camel_case from spdx.jsonschema.json_property import JsonProperty from spdx.model.document import Document -from spdx.casing_tools import snake_case_to_camel_case MISSING_IMPLEMENTATION_MESSAGE = "Must be implemented" diff --git a/src/spdx/jsonschema/creation_info_converter.py b/src/spdx/jsonschema/creation_info_converter.py index c4896659a..ce3dcef7d 100644 --- a/src/spdx/jsonschema/creation_info_converter.py +++ b/src/spdx/jsonschema/creation_info_converter.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Type, Any +from typing import Any, Type from spdx.datetime_conversions import datetime_to_iso_string from spdx.jsonschema.converter import TypedConverter diff --git a/src/spdx/jsonschema/document_converter.py b/src/spdx/jsonschema/document_converter.py index 71a3c76c5..319482012 100644 --- a/src/spdx/jsonschema/document_converter.py +++ b/src/spdx/jsonschema/document_converter.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Type, Any +from typing import Any, Type from spdx.document_utils import get_contained_spdx_element_ids from spdx.jsonschema.annotation_converter import AnnotationConverter @@ -24,9 +24,12 @@ from spdx.jsonschema.snippet_converter import SnippetConverter from spdx.model.document import Document from spdx.model.relationship import RelationshipType -from spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target, \ - find_package_contains_file_relationships, \ - find_file_contained_by_package_relationships +from spdx.model.relationship_filters import ( + filter_by_type_and_origin, + filter_by_type_and_target, + find_file_contained_by_package_relationships, + find_package_contains_file_relationships, +) class DocumentConverter(TypedConverter[Document]): diff --git a/src/spdx/jsonschema/external_document_ref_converter.py b/src/spdx/jsonschema/external_document_ref_converter.py index 023b38136..eb7c0f5bc 100644 --- a/src/spdx/jsonschema/external_document_ref_converter.py +++ b/src/spdx/jsonschema/external_document_ref_converter.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Type, Any +from typing import Any, Type from spdx.jsonschema.checksum_converter import ChecksumConverter from spdx.jsonschema.converter import TypedConverter diff --git a/src/spdx/jsonschema/external_package_ref_converter.py b/src/spdx/jsonschema/external_package_ref_converter.py index f1374c7c2..f67037bdd 100644 --- a/src/spdx/jsonschema/external_package_ref_converter.py +++ b/src/spdx/jsonschema/external_package_ref_converter.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Type, Any +from typing import Any, Type from spdx.jsonschema.converter import TypedConverter from spdx.jsonschema.external_package_ref_properties import ExternalPackageRefProperty diff --git a/src/spdx/jsonschema/extracted_licensing_info_converter.py b/src/spdx/jsonschema/extracted_licensing_info_converter.py index 3d198e3d6..ffd81e410 100644 --- a/src/spdx/jsonschema/extracted_licensing_info_converter.py +++ b/src/spdx/jsonschema/extracted_licensing_info_converter.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Type, Any +from typing import Any, Type from spdx.jsonschema.converter import TypedConverter from spdx.jsonschema.extracted_licensing_info_properties import ExtractedLicensingInfoProperty diff --git a/src/spdx/jsonschema/file_converter.py b/src/spdx/jsonschema/file_converter.py index 0d339c890..3b22a6108 100644 --- a/src/spdx/jsonschema/file_converter.py +++ b/src/spdx/jsonschema/file_converter.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Type, Any +from typing import Any, Type from spdx.jsonschema.annotation_converter import AnnotationConverter from spdx.jsonschema.checksum_converter import ChecksumConverter diff --git a/src/spdx/jsonschema/optional_utils.py b/src/spdx/jsonschema/optional_utils.py index 14824ed9a..3d5d6746a 100644 --- a/src/spdx/jsonschema/optional_utils.py +++ b/src/spdx/jsonschema/optional_utils.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Callable, TypeVar, Optional +from typing import Callable, Optional, TypeVar T = TypeVar("T") S = TypeVar("S") diff --git a/src/spdx/jsonschema/package_converter.py b/src/spdx/jsonschema/package_converter.py index c595e076f..a4614f57f 100644 --- a/src/spdx/jsonschema/package_converter.py +++ b/src/spdx/jsonschema/package_converter.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Type, Any +from typing import Any, Type from spdx.datetime_conversions import datetime_to_iso_string from spdx.jsonschema.annotation_converter import AnnotationConverter @@ -22,8 +22,10 @@ from spdx.model.actor import Actor from spdx.model.document import Document from spdx.model.package import Package -from spdx.model.relationship_filters import find_package_contains_file_relationships, \ - find_file_contained_by_package_relationships +from spdx.model.relationship_filters import ( + find_file_contained_by_package_relationships, + find_package_contains_file_relationships, +) class PackageConverter(TypedConverter[Package]): diff --git a/src/spdx/jsonschema/package_verification_code_converter.py b/src/spdx/jsonschema/package_verification_code_converter.py index a45bf1727..d2f7d2352 100644 --- a/src/spdx/jsonschema/package_verification_code_converter.py +++ b/src/spdx/jsonschema/package_verification_code_converter.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Type, Any +from typing import Any, Type from spdx.jsonschema.converter import TypedConverter from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/relationship_converter.py b/src/spdx/jsonschema/relationship_converter.py index f6d8d8d97..a3344a6a9 100644 --- a/src/spdx/jsonschema/relationship_converter.py +++ b/src/spdx/jsonschema/relationship_converter.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Type, Any +from typing import Any, Type from spdx.jsonschema.converter import TypedConverter from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/snippet_converter.py b/src/spdx/jsonschema/snippet_converter.py index 30e6ee9cf..ca1b7c4d9 100644 --- a/src/spdx/jsonschema/snippet_converter.py +++ b/src/spdx/jsonschema/snippet_converter.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Type, Any, Tuple, Dict +from typing import Any, Dict, Tuple, Type from spdx.jsonschema.annotation_converter import AnnotationConverter from spdx.jsonschema.converter import TypedConverter diff --git a/src/spdx/model/annotation.py b/src/spdx/model/annotation.py index ad44204ad..e12cf1d88 100644 --- a/src/spdx/model/annotation.py +++ b/src/spdx/model/annotation.py @@ -11,9 +11,9 @@ from datetime import datetime from enum import Enum, auto -from spdx.model.actor import Actor from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values +from spdx.model.actor import Actor class AnnotationType(Enum): diff --git a/src/spdx/model/checksum.py b/src/spdx/model/checksum.py index 94039b42e..4e9249615 100644 --- a/src/spdx/model/checksum.py +++ b/src/spdx/model/checksum.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from enum import auto, Enum +from enum import Enum, auto from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx/model/document.py b/src/spdx/model/document.py index c5147ddcb..063b9906e 100644 --- a/src/spdx/model/document.py +++ b/src/spdx/model/document.py @@ -12,16 +12,16 @@ from datetime import datetime from typing import List, Optional +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values from spdx.model.actor import Actor from spdx.model.annotation import Annotation -from common.typing.dataclass_with_properties import dataclass_with_properties from spdx.model.external_document_ref import ExternalDocumentRef from spdx.model.extracted_licensing_info import ExtractedLicensingInfo from spdx.model.file import File from spdx.model.package import Package from spdx.model.relationship import Relationship from spdx.model.snippet import Snippet -from common.typing.type_checks import check_types_and_set_values from spdx.model.version import Version diff --git a/src/spdx/model/external_document_ref.py b/src/spdx/model/external_document_ref.py index 2e33ec470..f99ad545f 100644 --- a/src/spdx/model/external_document_ref.py +++ b/src/spdx/model/external_document_ref.py @@ -9,9 +9,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -from spdx.model.checksum import Checksum from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values +from spdx.model.checksum import Checksum @dataclass_with_properties diff --git a/src/spdx/model/extracted_licensing_info.py b/src/spdx/model/extracted_licensing_info.py index a6c9030e3..f0954d45e 100644 --- a/src/spdx/model/extracted_licensing_info.py +++ b/src/spdx/model/extracted_licensing_info.py @@ -9,11 +9,11 @@ # See the License for the specific language governing permissions and # limitations under the License. from dataclasses import field -from typing import Optional, List, Union +from typing import List, Optional, Union -from spdx.model.spdx_no_assertion import SpdxNoAssertion from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values +from spdx.model.spdx_no_assertion import SpdxNoAssertion @dataclass_with_properties diff --git a/src/spdx/model/file.py b/src/spdx/model/file.py index 50b3576d6..fd3c66159 100644 --- a/src/spdx/model/file.py +++ b/src/spdx/model/file.py @@ -10,14 +10,15 @@ # limitations under the License. from dataclasses import field from enum import Enum, auto -from typing import Optional, List, Union +from typing import List, Optional, Union -from spdx.model.checksum import Checksum -from common.typing.dataclass_with_properties import dataclass_with_properties from license_expression import LicenseExpression + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values +from spdx.model.checksum import Checksum from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone -from common.typing.type_checks import check_types_and_set_values class FileType(Enum): diff --git a/src/spdx/model/package.py b/src/spdx/model/package.py index f725718d0..7e64574b7 100644 --- a/src/spdx/model/package.py +++ b/src/spdx/model/package.py @@ -11,15 +11,16 @@ from dataclasses import field from datetime import datetime from enum import Enum, auto -from typing import Optional, Union, List, Dict +from typing import Dict, List, Optional, Union +from license_expression import LicenseExpression + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values from spdx.model.actor import Actor from spdx.model.checksum import Checksum -from common.typing.dataclass_with_properties import dataclass_with_properties -from license_expression import LicenseExpression from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone -from common.typing.type_checks import check_types_and_set_values class PackagePurpose(Enum): diff --git a/src/spdx/model/relationship.py b/src/spdx/model/relationship.py index 25c9647be..22ad042a5 100644 --- a/src/spdx/model/relationship.py +++ b/src/spdx/model/relationship.py @@ -8,13 +8,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from enum import auto, Enum +from enum import Enum, auto from typing import Optional, Union -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values +from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx.model.spdx_none import SpdxNone class RelationshipType(Enum): diff --git a/src/spdx/model/snippet.py b/src/spdx/model/snippet.py index 1565dba0b..c34ef7652 100644 --- a/src/spdx/model/snippet.py +++ b/src/spdx/model/snippet.py @@ -9,13 +9,14 @@ # See the License for the specific language governing permissions and # limitations under the License. from dataclasses import field -from typing import Tuple, Optional, List, Union +from typing import List, Optional, Tuple, Union -from common.typing.dataclass_with_properties import dataclass_with_properties from license_expression import LicenseExpression + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone -from common.typing.type_checks import check_types_and_set_values @dataclass_with_properties diff --git a/src/spdx/parser/actor_parser.py b/src/spdx/parser/actor_parser.py index 7d6406eba..de8de6246 100644 --- a/src/spdx/parser/actor_parser.py +++ b/src/spdx/parser/actor_parser.py @@ -9,7 +9,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import re -from typing import Pattern, Match, Optional +from typing import Match, Optional, Pattern from spdx.model.actor import Actor, ActorType from spdx.parser.error import SPDXParsingError diff --git a/src/spdx/parser/jsonlikedict/annotation_parser.py b/src/spdx/parser/jsonlikedict/annotation_parser.py index f81da9ea4..43bbe634e 100644 --- a/src/spdx/parser/jsonlikedict/annotation_parser.py +++ b/src/spdx/parser/jsonlikedict/annotation_parser.py @@ -9,16 +9,16 @@ # See the License for the specific language governing permissions and # limitations under the License. from datetime import datetime -from typing import Dict, Optional, List +from typing import Dict, List, Optional +from spdx.datetime_conversions import datetime_from_str from spdx.model.actor import Actor from spdx.model.annotation import Annotation, AnnotationType -from spdx.parser.error import SPDXParsingError from spdx.parser.actor_parser import ActorParser -from spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_log_error, append_parsed_field_or_log_error -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.datetime_conversions import datetime_from_str +from spdx.parser.error import SPDXParsingError +from spdx.parser.jsonlikedict.dict_parsing_functions import append_parsed_field_or_log_error, parse_field_or_log_error from spdx.parser.logger import Logger +from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages class AnnotationParser: diff --git a/src/spdx/parser/jsonlikedict/checksum_parser.py b/src/spdx/parser/jsonlikedict/checksum_parser.py index 5bdb574a5..de09fc4ed 100644 --- a/src/spdx/parser/jsonlikedict/checksum_parser.py +++ b/src/spdx/parser/jsonlikedict/checksum_parser.py @@ -12,8 +12,8 @@ from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.parser.jsonlikedict.dict_parsing_functions import json_str_to_enum_name -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages from spdx.parser.logger import Logger +from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages class ChecksumParser: diff --git a/src/spdx/parser/jsonlikedict/creation_info_parser.py b/src/spdx/parser/jsonlikedict/creation_info_parser.py index 992ae8106..ddd86fce7 100644 --- a/src/spdx/parser/jsonlikedict/creation_info_parser.py +++ b/src/spdx/parser/jsonlikedict/creation_info_parser.py @@ -9,22 +9,24 @@ # See the License for the specific language governing permissions and # limitations under the License. from datetime import datetime -from typing import Dict, Optional, List +from typing import Dict, List, Optional +from spdx.datetime_conversions import datetime_from_str from spdx.model.actor import Actor from spdx.model.checksum import Checksum from spdx.model.document import CreationInfo from spdx.model.external_document_ref import ExternalDocumentRef from spdx.model.version import Version -from spdx.parser.error import SPDXParsingError from spdx.parser.actor_parser import ActorParser +from spdx.parser.error import SPDXParsingError from spdx.parser.jsonlikedict.checksum_parser import ChecksumParser -from spdx.parser.jsonlikedict.dict_parsing_functions import append_parsed_field_or_log_error, \ - parse_field_or_log_error, \ - parse_field_or_no_assertion -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.datetime_conversions import datetime_from_str +from spdx.parser.jsonlikedict.dict_parsing_functions import ( + append_parsed_field_or_log_error, + parse_field_or_log_error, + parse_field_or_no_assertion, +) from spdx.parser.logger import Logger +from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages class CreationInfoParser: diff --git a/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py b/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py index f1bad9657..41c3cab65 100644 --- a/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py +++ b/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py @@ -13,8 +13,8 @@ from spdx.model.extracted_licensing_info import ExtractedLicensingInfo from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_no_assertion -from spdx.parser.parsing_functions import construct_or_raise_parsing_error from spdx.parser.logger import Logger +from spdx.parser.parsing_functions import construct_or_raise_parsing_error class ExtractedLicensingInfoParser: diff --git a/src/spdx/parser/jsonlikedict/file_parser.py b/src/spdx/parser/jsonlikedict/file_parser.py index e89d9844b..f701c288b 100644 --- a/src/spdx/parser/jsonlikedict/file_parser.py +++ b/src/spdx/parser/jsonlikedict/file_parser.py @@ -10,16 +10,17 @@ # limitations under the License. from typing import Dict, List, Optional, Union +from license_expression import LicenseExpression + from spdx.model.checksum import Checksum from spdx.model.file import File, FileType -from license_expression import LicenseExpression from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone from spdx.parser.jsonlikedict.checksum_parser import ChecksumParser from spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_log_error -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages from spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser from spdx.parser.logger import Logger +from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages class FileParser: diff --git a/src/spdx/parser/jsonlikedict/json_like_dict_parser.py b/src/spdx/parser/jsonlikedict/json_like_dict_parser.py index a4ecf49a7..ae4d76965 100644 --- a/src/spdx/parser/jsonlikedict/json_like_dict_parser.py +++ b/src/spdx/parser/jsonlikedict/json_like_dict_parser.py @@ -15,13 +15,13 @@ from spdx.parser.jsonlikedict.annotation_parser import AnnotationParser from spdx.parser.jsonlikedict.creation_info_parser import CreationInfoParser from spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages from spdx.parser.jsonlikedict.extracted_licensing_info_parser import ExtractedLicensingInfoParser from spdx.parser.jsonlikedict.file_parser import FileParser -from spdx.parser.logger import Logger from spdx.parser.jsonlikedict.package_parser import PackageParser from spdx.parser.jsonlikedict.relationship_parser import RelationshipParser from spdx.parser.jsonlikedict.snippet_parser import SnippetParser +from spdx.parser.logger import Logger +from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages class JsonLikeDictParser: diff --git a/src/spdx/parser/jsonlikedict/license_expression_parser.py b/src/spdx/parser/jsonlikedict/license_expression_parser.py index a2e1912a8..3e57283cd 100644 --- a/src/spdx/parser/jsonlikedict/license_expression_parser.py +++ b/src/spdx/parser/jsonlikedict/license_expression_parser.py @@ -8,16 +8,16 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Union, List +from typing import List, Union -from license_expression import LicenseExpression, Licensing, ExpressionError +from license_expression import ExpressionError, LicenseExpression, Licensing from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone from spdx.parser.error import SPDXParsingError from spdx.parser.jsonlikedict.dict_parsing_functions import append_parsed_field_or_log_error -from spdx.parser.parsing_functions import raise_parsing_error_if_logger_has_messages from spdx.parser.logger import Logger +from spdx.parser.parsing_functions import raise_parsing_error_if_logger_has_messages class LicenseExpressionParser: diff --git a/src/spdx/parser/jsonlikedict/package_parser.py b/src/spdx/parser/jsonlikedict/package_parser.py index 50049092d..115474c1a 100644 --- a/src/spdx/parser/jsonlikedict/package_parser.py +++ b/src/spdx/parser/jsonlikedict/package_parser.py @@ -11,21 +11,32 @@ from datetime import datetime from typing import Dict, List, Optional, Union -from spdx.model.actor import Actor from license_expression import LicenseExpression -from spdx.model.package import Package, ExternalPackageRef, PackageVerificationCode, PackagePurpose, \ - ExternalPackageRefCategory + +from spdx.datetime_conversions import datetime_from_str +from spdx.model.actor import Actor +from spdx.model.package import ( + ExternalPackageRef, + ExternalPackageRefCategory, + Package, + PackagePurpose, + PackageVerificationCode, +) from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone -from spdx.parser.error import SPDXParsingError from spdx.parser.actor_parser import ActorParser +from spdx.parser.error import SPDXParsingError from spdx.parser.jsonlikedict.checksum_parser import ChecksumParser -from spdx.parser.jsonlikedict.dict_parsing_functions import append_parsed_field_or_log_error, \ - json_str_to_enum_name, parse_field_or_log_error, parse_field_or_no_assertion_or_none, parse_field_or_no_assertion -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.datetime_conversions import datetime_from_str +from spdx.parser.jsonlikedict.dict_parsing_functions import ( + append_parsed_field_or_log_error, + json_str_to_enum_name, + parse_field_or_log_error, + parse_field_or_no_assertion, + parse_field_or_no_assertion_or_none, +) from spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser from spdx.parser.logger import Logger +from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages class PackageParser: diff --git a/src/spdx/parser/jsonlikedict/relationship_parser.py b/src/spdx/parser/jsonlikedict/relationship_parser.py index c78d2771d..d83aaf8f4 100644 --- a/src/spdx/parser/jsonlikedict/relationship_parser.py +++ b/src/spdx/parser/jsonlikedict/relationship_parser.py @@ -10,13 +10,17 @@ # limitations under the License. from typing import Dict, List, Optional -from spdx.model.relationship import Relationship, RelationshipType from common.typing.constructor_type_errors import ConstructorTypeErrors +from spdx.model.relationship import Relationship, RelationshipType from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.dict_parsing_functions import json_str_to_enum_name, \ - parse_field_or_log_error, parse_field_or_no_assertion_or_none, delete_duplicates_from_list -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx.parser.jsonlikedict.dict_parsing_functions import ( + delete_duplicates_from_list, + json_str_to_enum_name, + parse_field_or_log_error, + parse_field_or_no_assertion_or_none, +) from spdx.parser.logger import Logger +from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages class RelationshipParser: diff --git a/src/spdx/parser/jsonlikedict/snippet_parser.py b/src/spdx/parser/jsonlikedict/snippet_parser.py index b942abe07..a5a60a00c 100644 --- a/src/spdx/parser/jsonlikedict/snippet_parser.py +++ b/src/spdx/parser/jsonlikedict/snippet_parser.py @@ -8,20 +8,22 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from enum import auto, Enum -from typing import Dict, Tuple, List, Optional, Union +from enum import Enum, auto +from typing import Dict, List, Optional, Tuple, Union from license_expression import LicenseExpression + from spdx.model.snippet import Snippet from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_log_error, \ - parse_field_or_no_assertion_or_none -from spdx.parser.parsing_functions import construct_or_raise_parsing_error - +from spdx.parser.jsonlikedict.dict_parsing_functions import ( + parse_field_or_log_error, + parse_field_or_no_assertion_or_none, +) from spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser from spdx.parser.logger import Logger +from spdx.parser.parsing_functions import construct_or_raise_parsing_error class RangeType(Enum): diff --git a/src/spdx/parser/parse_anything.py b/src/spdx/parser/parse_anything.py index 8b156cf34..51a730ae5 100644 --- a/src/spdx/parser/parse_anything.py +++ b/src/spdx/parser/parse_anything.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from spdx.formats import file_name_to_format, FileFormat +from spdx.formats import FileFormat, file_name_to_format from spdx.parser.json import json_parser from spdx.parser.rdf import rdf_parser from spdx.parser.tagvalue import tagvalue_parser diff --git a/src/spdx/parser/rdf/annotation_parser.py b/src/spdx/parser/rdf/annotation_parser.py index 88fe0ae65..74a927c09 100644 --- a/src/spdx/parser/rdf/annotation_parser.py +++ b/src/spdx/parser/rdf/annotation_parser.py @@ -8,14 +8,14 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import URIRef, Graph, RDFS +from rdflib import RDFS, Graph, URIRef from spdx.datetime_conversions import datetime_from_str from spdx.model.annotation import Annotation, AnnotationType from spdx.parser.actor_parser import ActorParser from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import raise_parsing_error_if_logger_has_messages, construct_or_raise_parsing_error -from spdx.parser.rdf.graph_parsing_functions import parse_literal, parse_spdx_id, parse_enum_value +from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx.parser.rdf.graph_parsing_functions import parse_enum_value, parse_literal, parse_spdx_id from spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/src/spdx/parser/rdf/checksum_parser.py b/src/spdx/parser/rdf/checksum_parser.py index 4ec73059e..40f7899a9 100644 --- a/src/spdx/parser/rdf/checksum_parser.py +++ b/src/spdx/parser/rdf/checksum_parser.py @@ -9,9 +9,9 @@ # See the License for the specific language governing permissions and # limitations under the License. from rdflib import Graph, URIRef -from spdx.parser.error import SPDXParsingError from spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx.parser.error import SPDXParsingError from spdx.parser.logger import Logger from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages from spdx.parser.rdf.graph_parsing_functions import parse_literal, remove_prefix diff --git a/src/spdx/parser/rdf/creation_info_parser.py b/src/spdx/parser/rdf/creation_info_parser.py index 7ca2215e1..ac8d1e1e6 100644 --- a/src/spdx/parser/rdf/creation_info_parser.py +++ b/src/spdx/parser/rdf/creation_info_parser.py @@ -13,22 +13,21 @@ from typing import Tuple from urllib.parse import urldefrag -from rdflib import Graph, RDFS, RDF, Namespace +from rdflib import RDF, RDFS, Graph, Namespace from rdflib.exceptions import UniquenessError from rdflib.term import URIRef -from spdx.parser.error import SPDXParsingError -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.rdf.checksum_parser import parse_checksum -from spdx.parser.rdf.graph_parsing_functions import parse_literal, parse_spdx_id, remove_prefix -from spdx.rdfschema.namespace import SPDX_NAMESPACE, LICENSE_NAMESPACE - from spdx.datetime_conversions import datetime_from_str from spdx.model.document import CreationInfo from spdx.model.external_document_ref import ExternalDocumentRef from spdx.model.version import Version from spdx.parser.actor_parser import ActorParser +from spdx.parser.error import SPDXParsingError +from spdx.parser.logger import Logger +from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx.parser.rdf.checksum_parser import parse_checksum +from spdx.parser.rdf.graph_parsing_functions import parse_literal, parse_spdx_id, remove_prefix +from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE def parse_creation_info(graph: Graph) -> Tuple[CreationInfo, URIRef]: diff --git a/src/spdx/parser/rdf/extracted_licensing_info_parser.py b/src/spdx/parser/rdf/extracted_licensing_info_parser.py index edaf68b4a..88b9f7688 100644 --- a/src/spdx/parser/rdf/extracted_licensing_info_parser.py +++ b/src/spdx/parser/rdf/extracted_licensing_info_parser.py @@ -8,13 +8,12 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import URIRef, Graph, RDFS -from spdx.parser.rdf.graph_parsing_functions import parse_literal, parse_literal_or_no_assertion_or_none - -from spdx.parser.parsing_functions import raise_parsing_error_if_logger_has_messages, construct_or_raise_parsing_error +from rdflib import RDFS, Graph, URIRef from spdx.model.extracted_licensing_info import ExtractedLicensingInfo from spdx.parser.logger import Logger +from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx.parser.rdf.graph_parsing_functions import parse_literal, parse_literal_or_no_assertion_or_none from spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/src/spdx/parser/rdf/file_parser.py b/src/spdx/parser/rdf/file_parser.py index 37cb2ca50..53a7c8860 100644 --- a/src/spdx/parser/rdf/file_parser.py +++ b/src/spdx/parser/rdf/file_parser.py @@ -8,14 +8,20 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import URIRef, Graph, RDFS +from rdflib import RDFS, Graph, URIRef from spdx.model.file import File, FileType from spdx.parser.logger import Logger from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages from spdx.parser.rdf.checksum_parser import parse_checksum -from spdx.parser.rdf.graph_parsing_functions import parse_literal, parse_spdx_id, parse_literal_or_no_assertion_or_none, \ - get_correctly_typed_value, apply_parsing_method_or_log_error, parse_enum_value +from spdx.parser.rdf.graph_parsing_functions import ( + apply_parsing_method_or_log_error, + get_correctly_typed_value, + parse_enum_value, + parse_literal, + parse_literal_or_no_assertion_or_none, + parse_spdx_id, +) from spdx.parser.rdf.license_expression_parser import parse_license_expression from spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/src/spdx/parser/rdf/graph_parsing_functions.py b/src/spdx/parser/rdf/graph_parsing_functions.py index 08fe3aae0..89bb34542 100644 --- a/src/spdx/parser/rdf/graph_parsing_functions.py +++ b/src/spdx/parser/rdf/graph_parsing_functions.py @@ -16,12 +16,12 @@ from rdflib.namespace import NamespaceManager from rdflib.term import Node -from spdx.model.spdx_no_assertion import SpdxNoAssertion, SPDX_NO_ASSERTION_STRING -from spdx.model.spdx_none import SpdxNone, SPDX_NONE_STRING +from spdx.casing_tools import camel_case_to_snake_case +from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion +from spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone from spdx.parser.error import SPDXParsingError from spdx.parser.logger import Logger from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.casing_tools import camel_case_to_snake_case def parse_literal(logger: Logger, graph: Graph, subject: Node, predicate: Node, diff --git a/src/spdx/parser/rdf/license_expression_parser.py b/src/spdx/parser/rdf/license_expression_parser.py index b178252e0..1d0293b57 100644 --- a/src/spdx/parser/rdf/license_expression_parser.py +++ b/src/spdx/parser/rdf/license_expression_parser.py @@ -10,12 +10,12 @@ # limitations under the License. from typing import Union -from rdflib import Graph, RDF from license_expression import LicenseExpression, get_spdx_licensing -from rdflib.term import Identifier, URIRef, BNode, Node -from spdx.parser.rdf.graph_parsing_functions import remove_prefix +from rdflib import RDF, Graph +from rdflib.term import BNode, Identifier, Node, URIRef -from spdx.rdfschema.namespace import SPDX_NAMESPACE, LICENSE_NAMESPACE +from spdx.parser.rdf.graph_parsing_functions import remove_prefix +from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE def parse_license_expression(license_expression_node: Union[URIRef, BNode, Node], graph: Graph, diff --git a/src/spdx/parser/rdf/package_parser.py b/src/spdx/parser/rdf/package_parser.py index 27977daba..9346d2dfc 100644 --- a/src/spdx/parser/rdf/package_parser.py +++ b/src/spdx/parser/rdf/package_parser.py @@ -9,19 +9,31 @@ # See the License for the specific language governing permissions and # limitations under the License. from typing import Optional -from rdflib import URIRef, Graph, RDFS, DOAP, Literal + +from rdflib import DOAP, RDFS, Graph, Literal, URIRef from spdx.datetime_conversions import datetime_from_str -from spdx.model.package import Package, PackagePurpose, ExternalPackageRef, PackageVerificationCode, \ - ExternalPackageRefCategory +from spdx.model.package import ( + ExternalPackageRef, + ExternalPackageRefCategory, + Package, + PackagePurpose, + PackageVerificationCode, +) from spdx.parser.actor_parser import ActorParser from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import raise_parsing_error_if_logger_has_messages, construct_or_raise_parsing_error +from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages from spdx.parser.rdf.checksum_parser import parse_checksum -from spdx.parser.rdf.graph_parsing_functions import parse_spdx_id, parse_literal, parse_enum_value, \ - parse_literal_or_no_assertion_or_none, get_correctly_typed_value, parse_literal_or_no_assertion_or_none, remove_prefix +from spdx.parser.rdf.graph_parsing_functions import ( + get_correctly_typed_value, + parse_enum_value, + parse_literal, + parse_literal_or_no_assertion_or_none, + parse_spdx_id, + remove_prefix, +) from spdx.parser.rdf.license_expression_parser import parse_license_expression -from spdx.rdfschema.namespace import SPDX_NAMESPACE, REFERENCE_NAMESPACE +from spdx.rdfschema.namespace import REFERENCE_NAMESPACE, SPDX_NAMESPACE def parse_package(package_node: URIRef, graph: Graph, doc_namespace: str) -> Package: diff --git a/src/spdx/parser/rdf/rdf_parser.py b/src/spdx/parser/rdf/rdf_parser.py index e343f4b26..4794651fa 100644 --- a/src/spdx/parser/rdf/rdf_parser.py +++ b/src/spdx/parser/rdf/rdf_parser.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import Graph, RDF +from rdflib import RDF, Graph from spdx.model.document import Document from spdx.parser.error import SPDXParsingError diff --git a/src/spdx/parser/rdf/relationship_parser.py b/src/spdx/parser/rdf/relationship_parser.py index c9a49403e..313efbe44 100644 --- a/src/spdx/parser/rdf/relationship_parser.py +++ b/src/spdx/parser/rdf/relationship_parser.py @@ -8,13 +8,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import URIRef, Graph, RDFS +from rdflib import RDFS, Graph, URIRef from spdx.model.relationship import Relationship, RelationshipType from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import raise_parsing_error_if_logger_has_messages, construct_or_raise_parsing_error -from spdx.parser.rdf.graph_parsing_functions import parse_literal, parse_enum_value, \ - parse_literal_or_no_assertion_or_none, parse_spdx_id +from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx.parser.rdf.graph_parsing_functions import ( + parse_enum_value, + parse_literal, + parse_literal_or_no_assertion_or_none, + parse_spdx_id, +) from spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/src/spdx/parser/rdf/snippet_parser.py b/src/spdx/parser/rdf/snippet_parser.py index 096681fe0..316ba2e76 100644 --- a/src/spdx/parser/rdf/snippet_parser.py +++ b/src/spdx/parser/rdf/snippet_parser.py @@ -8,20 +8,25 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Tuple, Optional, Dict +from typing import Dict, Optional, Tuple -from rdflib import Graph, RDF, RDFS +from rdflib import RDF, RDFS, Graph from rdflib.exceptions import UniquenessError -from rdflib.term import URIRef, Node -from spdx.parser.error import SPDXParsingError +from rdflib.term import Node, URIRef from spdx.model.snippet import Snippet +from spdx.parser.error import SPDXParsingError from spdx.parser.logger import Logger from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.rdf.graph_parsing_functions import parse_literal, parse_spdx_id, parse_literal_or_no_assertion_or_none, \ - get_correctly_typed_value, apply_parsing_method_or_log_error +from spdx.parser.rdf.graph_parsing_functions import ( + apply_parsing_method_or_log_error, + get_correctly_typed_value, + parse_literal, + parse_literal_or_no_assertion_or_none, + parse_spdx_id, +) from spdx.parser.rdf.license_expression_parser import parse_license_expression -from spdx.rdfschema.namespace import SPDX_NAMESPACE, POINTER_NAMESPACE +from spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE def parse_snippet(snippet_node: URIRef, graph: Graph, doc_namespace: str) -> Snippet: diff --git a/src/spdx/parser/tagvalue/helper_methods.py b/src/spdx/parser/tagvalue/helper_methods.py index 3f7ad0012..cd5329b49 100644 --- a/src/spdx/parser/tagvalue/helper_methods.py +++ b/src/spdx/parser/tagvalue/helper_methods.py @@ -9,7 +9,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import re -from typing import Optional, Callable, Any, Dict +from typing import Any, Callable, Dict, Optional from ply.yacc import YaccProduction diff --git a/src/spdx/parser/tagvalue/parser.py b/src/spdx/parser/tagvalue/parser.py index 9ee5a3ad8..d649695f3 100644 --- a/src/spdx/parser/tagvalue/parser.py +++ b/src/spdx/parser/tagvalue/parser.py @@ -11,20 +11,25 @@ # limitations under the License. import re -from typing import Any, List, Dict +from typing import Any, Dict, List from license_expression import get_spdx_licensing from ply import yacc from ply.yacc import LRParser from spdx.datetime_conversions import datetime_from_str -from spdx.model.annotation import AnnotationType, Annotation -from spdx.model.document import Document, CreationInfo +from spdx.model.annotation import Annotation, AnnotationType +from spdx.model.document import CreationInfo, Document from spdx.model.external_document_ref import ExternalDocumentRef from spdx.model.extracted_licensing_info import ExtractedLicensingInfo from spdx.model.file import File, FileType -from spdx.model.package import Package, PackageVerificationCode, PackagePurpose, ExternalPackageRef, \ - ExternalPackageRefCategory +from spdx.model.package import ( + ExternalPackageRef, + ExternalPackageRefCategory, + Package, + PackagePurpose, + PackageVerificationCode, +) from spdx.model.relationship import Relationship, RelationshipType from spdx.model.snippet import Snippet from spdx.model.spdx_no_assertion import SpdxNoAssertion @@ -34,9 +39,14 @@ from spdx.parser.error import SPDXParsingError from spdx.parser.logger import Logger from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx.parser.tagvalue.helper_methods import ( + TAG_DATA_MODEL_FIELD, + grammar_rule, + parse_checksum, + set_value, + str_from_text, +) from spdx.parser.tagvalue.lexer import SPDXLexer -from spdx.parser.tagvalue.helper_methods import grammar_rule, str_from_text, parse_checksum, set_value, \ - TAG_DATA_MODEL_FIELD CLASS_MAPPING = dict(File="files", Annotation="annotations", Relationship="relationships", Snippet="snippets", Package="packages", ExtractedLicensingInfo="extracted_licensing_info") diff --git a/src/spdx/parser/xml/xml_parser.py b/src/spdx/parser/xml/xml_parser.py index ccccd15d3..38670c976 100644 --- a/src/spdx/parser/xml/xml_parser.py +++ b/src/spdx/parser/xml/xml_parser.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict, Any +from typing import Any, Dict import xmltodict @@ -16,7 +16,6 @@ from spdx.parser.error import SPDXParsingError from spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser - LIST_LIKE_FIELDS = [ "creators", "externalDocumentRefs", diff --git a/src/spdx/validation/actor_validator.py b/src/spdx/validation/actor_validator.py index 033d2e94c..b105d5652 100644 --- a/src/spdx/validation/actor_validator.py +++ b/src/spdx/validation/actor_validator.py @@ -12,7 +12,7 @@ from typing import List from spdx.model.actor import Actor, ActorType -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_actors(actors: List[Actor], parent_id: str) -> List[ValidationMessage]: diff --git a/src/spdx/validation/annotation_validator.py b/src/spdx/validation/annotation_validator.py index 407b2f7b5..34a897f39 100644 --- a/src/spdx/validation/annotation_validator.py +++ b/src/spdx/validation/annotation_validator.py @@ -15,7 +15,7 @@ from spdx.model.document import Document from spdx.validation.actor_validator import validate_actor from spdx.validation.spdx_id_validators import validate_spdx_id -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_annotations(annotations: List[Annotation], document: Document) -> List[ValidationMessage]: diff --git a/src/spdx/validation/checksum_validator.py b/src/spdx/validation/checksum_validator.py index 1f4830336..3d747e102 100644 --- a/src/spdx/validation/checksum_validator.py +++ b/src/spdx/validation/checksum_validator.py @@ -10,10 +10,10 @@ # limitations under the License. import re -from typing import List, Dict +from typing import Dict, List from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage # in hexadecimal digits algorithm_length: Dict = { diff --git a/src/spdx/validation/creation_info_validator.py b/src/spdx/validation/creation_info_validator.py index 3511e1d89..286226351 100644 --- a/src/spdx/validation/creation_info_validator.py +++ b/src/spdx/validation/creation_info_validator.py @@ -15,7 +15,7 @@ from spdx.validation.actor_validator import validate_actors from spdx.validation.external_document_ref_validator import validate_external_document_refs from spdx.validation.uri_validators import validate_uri -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_creation_info(creation_info: CreationInfo, spdx_version: str) -> List[ValidationMessage]: diff --git a/src/spdx/validation/document_validator.py b/src/spdx/validation/document_validator.py index 264e8d400..becf5f401 100644 --- a/src/spdx/validation/document_validator.py +++ b/src/spdx/validation/document_validator.py @@ -21,7 +21,7 @@ from spdx.validation.relationship_validator import validate_relationships from spdx.validation.snippet_validator import validate_snippets from spdx.validation.spdx_id_validators import get_list_of_all_spdx_ids -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_full_spdx_document(document: Document, spdx_version: str = None) -> List[ValidationMessage]: diff --git a/src/spdx/validation/external_document_ref_validator.py b/src/spdx/validation/external_document_ref_validator.py index 99156566b..b331d161e 100644 --- a/src/spdx/validation/external_document_ref_validator.py +++ b/src/spdx/validation/external_document_ref_validator.py @@ -15,7 +15,7 @@ from spdx.validation.checksum_validator import validate_checksum from spdx.validation.spdx_id_validators import is_valid_external_doc_ref_id from spdx.validation.uri_validators import validate_uri -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_external_document_refs(external_document_refs: List[ExternalDocumentRef], parent_id: str, diff --git a/src/spdx/validation/external_package_ref_validator.py b/src/spdx/validation/external_package_ref_validator.py index 07a8f6bc4..d49099c84 100644 --- a/src/spdx/validation/external_package_ref_validator.py +++ b/src/spdx/validation/external_package_ref_validator.py @@ -9,13 +9,13 @@ # See the License for the specific language governing permissions and # limitations under the License. import re -from typing import List, Dict +from typing import Dict, List import uritools -from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory, CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES +from spdx.model.package import CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES, ExternalPackageRef, ExternalPackageRefCategory from spdx.validation.uri_validators import validate_url -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage CPE22TYPE_REGEX = r'^c[pP][eE]:/[AHOaho]?(:[A-Za-z0-9._\-~%]*){0,6}$' CPE23TYPE_REGEX = r'^cpe:2\.3:[aho\*\-](:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!"#$$%&\'\(\)\+,\/:;<=>@\[\]\^`\{\|}~]))+(\?*|\*?))|[\*\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\*\-]))(:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!"#$$%&\'\(\)\+,\/:;<=>@\[\]\^`\{\|}~]))+(\?*|\*?))|[\*\-])){4}$' diff --git a/src/spdx/validation/extracted_licensing_info_validator.py b/src/spdx/validation/extracted_licensing_info_validator.py index 8b769e13d..be08dc630 100644 --- a/src/spdx/validation/extracted_licensing_info_validator.py +++ b/src/spdx/validation/extracted_licensing_info_validator.py @@ -14,7 +14,7 @@ from spdx.model.extracted_licensing_info import ExtractedLicensingInfo from spdx.validation.uri_validators import validate_url -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_extracted_licensing_infos(extracted_licensing_infos: Optional[List[ExtractedLicensingInfo]]) -> List[ diff --git a/src/spdx/validation/file_validator.py b/src/spdx/validation/file_validator.py index 745131bdc..37bc880da 100644 --- a/src/spdx/validation/file_validator.py +++ b/src/spdx/validation/file_validator.py @@ -15,9 +15,9 @@ from spdx.model.document import Document from spdx.model.file import File from spdx.validation.checksum_validator import validate_checksums -from spdx.validation.license_expression_validator import validate_license_expressions, validate_license_expression +from spdx.validation.license_expression_validator import validate_license_expression, validate_license_expressions from spdx.validation.spdx_id_validators import validate_spdx_id -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_files(files: List[File], spdx_version: str, document: Optional[Document] = None) -> List[ diff --git a/src/spdx/validation/license_expression_validator.py b/src/spdx/validation/license_expression_validator.py index 789d6c8c4..546bbc8b4 100644 --- a/src/spdx/validation/license_expression_validator.py +++ b/src/spdx/validation/license_expression_validator.py @@ -11,12 +11,12 @@ from typing import List, Optional, Union -from license_expression import LicenseExpression, get_spdx_licensing, ExpressionError, ExpressionParseError -from spdx.model.document import Document +from license_expression import ExpressionError, ExpressionParseError, LicenseExpression, get_spdx_licensing +from spdx.model.document import Document from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_license_expressions( diff --git a/src/spdx/validation/package_validator.py b/src/spdx/validation/package_validator.py index 4cd850fc8..4b11136b2 100644 --- a/src/spdx/validation/package_validator.py +++ b/src/spdx/validation/package_validator.py @@ -13,15 +13,15 @@ from spdx.model.document import Document from spdx.model.package import Package -from spdx.model.relationship import RelationshipType, Relationship +from spdx.model.relationship import Relationship, RelationshipType from spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target from spdx.validation.checksum_validator import validate_checksums from spdx.validation.external_package_ref_validator import validate_external_package_refs from spdx.validation.license_expression_validator import validate_license_expression, validate_license_expressions from spdx.validation.package_verification_code_validator import validate_verification_code from spdx.validation.spdx_id_validators import validate_spdx_id -from spdx.validation.uri_validators import validate_url, validate_download_location -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.uri_validators import validate_download_location, validate_url +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_packages(packages: List[Package], spdx_version: str, document: Optional[Document] = None) -> List[ diff --git a/src/spdx/validation/package_verification_code_validator.py b/src/spdx/validation/package_verification_code_validator.py index de6abbec2..e12574bdd 100644 --- a/src/spdx/validation/package_verification_code_validator.py +++ b/src/spdx/validation/package_verification_code_validator.py @@ -13,7 +13,7 @@ from typing import List from spdx.model.package import PackageVerificationCode -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_verification_code(verification_code: PackageVerificationCode, parent_id: str) -> List[ValidationMessage]: diff --git a/src/spdx/validation/relationship_validator.py b/src/spdx/validation/relationship_validator.py index 4fa310970..b9c479675 100644 --- a/src/spdx/validation/relationship_validator.py +++ b/src/spdx/validation/relationship_validator.py @@ -16,7 +16,7 @@ from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone from spdx.validation.spdx_id_validators import validate_spdx_id -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_relationships(relationships: List[Relationship], spdx_version: str, document: Document) -> List[ diff --git a/src/spdx/validation/snippet_validator.py b/src/spdx/validation/snippet_validator.py index 90a110fa3..6a7f37378 100644 --- a/src/spdx/validation/snippet_validator.py +++ b/src/spdx/validation/snippet_validator.py @@ -13,10 +13,9 @@ from spdx.model.document import Document from spdx.model.snippet import Snippet -from spdx.validation.license_expression_validator import validate_license_expression, \ - validate_license_expressions +from spdx.validation.license_expression_validator import validate_license_expression, validate_license_expressions from spdx.validation.spdx_id_validators import validate_spdx_id -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_snippets(snippets: List[Snippet], spdx_version: str, document: Optional[Document] = None) -> List[ diff --git a/src/spdx/validation/validation_message.py b/src/spdx/validation/validation_message.py index 70001b78a..c1679f1c7 100644 --- a/src/spdx/validation/validation_message.py +++ b/src/spdx/validation/validation_message.py @@ -11,7 +11,7 @@ from dataclasses import dataclass from enum import Enum, auto -from typing import Optional, Any +from typing import Any, Optional class SpdxElementType(Enum): diff --git a/src/spdx/writer/rdf/annotation_writer.py b/src/spdx/writer/rdf/annotation_writer.py index e1e275d77..3f486a84c 100644 --- a/src/spdx/writer/rdf/annotation_writer.py +++ b/src/spdx/writer/rdf/annotation_writer.py @@ -10,13 +10,13 @@ # limitations under the License. from typing import Dict -from rdflib import Graph, Literal, RDFS, URIRef, RDF, BNode +from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef +from spdx.casing_tools import snake_case_to_camel_case from spdx.datetime_conversions import datetime_to_iso_string from spdx.model.annotation import Annotation -from spdx.casing_tools import snake_case_to_camel_case -from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id def add_annotation_to_graph(annotation: Annotation, graph: Graph, doc_namespace: str, diff --git a/src/spdx/writer/rdf/checksum_writer.py b/src/spdx/writer/rdf/checksum_writer.py index b9b2fe84f..319c144ae 100644 --- a/src/spdx/writer/rdf/checksum_writer.py +++ b/src/spdx/writer/rdf/checksum_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import Graph, URIRef, BNode, RDF, Literal +from rdflib import RDF, BNode, Graph, Literal, URIRef from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/src/spdx/writer/rdf/creation_info_writer.py b/src/spdx/writer/rdf/creation_info_writer.py index 1fe1330c5..b7e78f5d2 100644 --- a/src/spdx/writer/rdf/creation_info_writer.py +++ b/src/spdx/writer/rdf/creation_info_writer.py @@ -8,13 +8,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import Graph, BNode, RDF, Literal, RDFS, URIRef +from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef from spdx.datetime_conversions import datetime_to_iso_string from spdx.model.document import CreationInfo +from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE from spdx.writer.rdf.external_document_ref_writer import add_external_document_ref_to_graph from spdx.writer.rdf.writer_utils import add_optional_literal -from spdx.rdfschema.namespace import SPDX_NAMESPACE, LICENSE_NAMESPACE def add_creation_info_to_graph(creation_info: CreationInfo, graph: Graph): diff --git a/src/spdx/writer/rdf/external_document_ref_writer.py b/src/spdx/writer/rdf/external_document_ref_writer.py index 7521bd338..1ee876830 100644 --- a/src/spdx/writer/rdf/external_document_ref_writer.py +++ b/src/spdx/writer/rdf/external_document_ref_writer.py @@ -8,11 +8,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import Graph, URIRef, RDF +from rdflib import RDF, Graph, URIRef from spdx.model.external_document_ref import ExternalDocumentRef -from spdx.writer.rdf.checksum_writer import add_checksum_to_graph from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx.writer.rdf.checksum_writer import add_checksum_to_graph def add_external_document_ref_to_graph(external_document_ref: ExternalDocumentRef, graph: Graph, doc_node: URIRef, diff --git a/src/spdx/writer/rdf/extracted_licensing_info_writer.py b/src/spdx/writer/rdf/extracted_licensing_info_writer.py index 4d0f4b674..7e8e4e727 100644 --- a/src/spdx/writer/rdf/extracted_licensing_info_writer.py +++ b/src/spdx/writer/rdf/extracted_licensing_info_writer.py @@ -8,11 +8,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import Graph, URIRef, RDF, BNode, RDFS, Literal -from spdx.writer.rdf.writer_utils import add_optional_literal, add_literal_or_no_assertion -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef from spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx.writer.rdf.writer_utils import add_literal_or_no_assertion, add_optional_literal def add_extracted_licensing_info_to_graph(extracted_licensing_info: ExtractedLicensingInfo, graph: Graph, doc_node, diff --git a/src/spdx/writer/rdf/file_writer.py b/src/spdx/writer/rdf/file_writer.py index 6441d8c06..c66b37ccc 100644 --- a/src/spdx/writer/rdf/file_writer.py +++ b/src/spdx/writer/rdf/file_writer.py @@ -10,14 +10,14 @@ # limitations under the License. from typing import Dict -from rdflib import Graph, URIRef, Literal, RDF, RDFS +from rdflib import RDF, RDFS, Graph, Literal, URIRef -from spdx.model.file import File from spdx.casing_tools import snake_case_to_camel_case +from spdx.model.file import File +from spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx.writer.rdf.checksum_writer import add_checksum_to_graph from spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion -from spdx.writer.rdf.writer_utils import add_optional_literal, add_namespace_to_spdx_id -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id, add_optional_literal def add_file_to_graph(file: File, graph: Graph, doc_namespace: str, diff --git a/src/spdx/writer/rdf/license_expression_writer.py b/src/spdx/writer/rdf/license_expression_writer.py index cf4edde7e..eb97eb3ff 100644 --- a/src/spdx/writer/rdf/license_expression_writer.py +++ b/src/spdx/writer/rdf/license_expression_writer.py @@ -8,18 +8,24 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Union, List +from typing import List, Union from boolean import Expression -from rdflib import Graph, URIRef, BNode, RDF -from license_expression import AND, OR, LicenseWithExceptionSymbol, LicenseSymbol, get_spdx_licensing, ExpressionInfo, \ - LicenseExpression -from rdflib.term import Node, Literal +from license_expression import ( + AND, + OR, + ExpressionInfo, + LicenseExpression, + LicenseSymbol, + LicenseWithExceptionSymbol, + get_spdx_licensing, +) +from rdflib import RDF, BNode, Graph, URIRef +from rdflib.term import Literal, Node from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone - -from spdx.rdfschema.namespace import SPDX_NAMESPACE, LICENSE_NAMESPACE +from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE def add_license_expression_or_none_or_no_assertion(value: Union[ diff --git a/src/spdx/writer/rdf/package_writer.py b/src/spdx/writer/rdf/package_writer.py index 890cf8f12..99f22a3db 100644 --- a/src/spdx/writer/rdf/package_writer.py +++ b/src/spdx/writer/rdf/package_writer.py @@ -10,17 +10,24 @@ # limitations under the License. from typing import Dict -from rdflib import Graph, URIRef, RDF, Literal, XSD, BNode, DOAP, RDFS -from spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion +from rdflib import DOAP, RDF, RDFS, XSD, BNode, Graph, Literal, URIRef from spdx.casing_tools import snake_case_to_camel_case +from spdx.model.package import ( + CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES, + ExternalPackageRef, + Package, + PackageVerificationCode, +) +from spdx.rdfschema.namespace import REFERENCE_NAMESPACE, SPDX_NAMESPACE from spdx.writer.rdf.checksum_writer import add_checksum_to_graph - -from spdx.model.package import Package, PackageVerificationCode, ExternalPackageRef, \ - CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES -from spdx.writer.rdf.writer_utils import add_optional_literal, add_literal_or_no_assertion_or_none, \ - add_datetime_to_graph, add_namespace_to_spdx_id -from spdx.rdfschema.namespace import SPDX_NAMESPACE, REFERENCE_NAMESPACE +from spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion +from spdx.writer.rdf.writer_utils import ( + add_datetime_to_graph, + add_literal_or_no_assertion_or_none, + add_namespace_to_spdx_id, + add_optional_literal, +) def add_package_to_graph(package: Package, graph: Graph, doc_namespace: str, diff --git a/src/spdx/writer/rdf/rdf_writer.py b/src/spdx/writer/rdf/rdf_writer.py index 0e7848e86..9ef0f8b3c 100644 --- a/src/spdx/writer/rdf/rdf_writer.py +++ b/src/spdx/writer/rdf/rdf_writer.py @@ -10,10 +10,11 @@ # limitations under the License. from typing import Dict, List -from rdflib import Graph, DOAP +from rdflib import DOAP, Graph from rdflib.compare import to_isomorphic from spdx.model.document import Document +from spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE from spdx.validation.document_validator import validate_full_spdx_document from spdx.validation.validation_message import ValidationMessage from spdx.writer.rdf.annotation_writer import add_annotation_to_graph @@ -23,7 +24,6 @@ from spdx.writer.rdf.package_writer import add_package_to_graph from spdx.writer.rdf.relationship_writer import add_relationship_to_graph from spdx.writer.rdf.snippet_writer import add_snippet_to_graph -from spdx.rdfschema.namespace import SPDX_NAMESPACE, POINTER_NAMESPACE def write_document_to_file(document: Document, file_name: str, validate: bool): diff --git a/src/spdx/writer/rdf/relationship_writer.py b/src/spdx/writer/rdf/relationship_writer.py index 66bc95e24..5f01fd668 100644 --- a/src/spdx/writer/rdf/relationship_writer.py +++ b/src/spdx/writer/rdf/relationship_writer.py @@ -10,14 +10,14 @@ # limitations under the License. from typing import Dict -from rdflib import Graph, BNode, RDF, URIRef, RDFS, Literal +from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef +from spdx.casing_tools import snake_case_to_camel_case from spdx.model.relationship import Relationship from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone -from spdx.casing_tools import snake_case_to_camel_case -from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id def add_relationship_to_graph(relationship: Relationship, graph: Graph, doc_namespace: str, diff --git a/src/spdx/writer/rdf/snippet_writer.py b/src/spdx/writer/rdf/snippet_writer.py index b7ab6ce2a..94458a78c 100644 --- a/src/spdx/writer/rdf/snippet_writer.py +++ b/src/spdx/writer/rdf/snippet_writer.py @@ -8,15 +8,14 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Tuple, Optional, Dict +from typing import Dict, Optional, Tuple -from rdflib import Graph, URIRef, RDF, RDFS, Literal, BNode - -from spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion -from spdx.writer.rdf.writer_utils import add_optional_literal, add_namespace_to_spdx_id -from spdx.rdfschema.namespace import SPDX_NAMESPACE, POINTER_NAMESPACE +from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef from spdx.model.snippet import Snippet +from spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE +from spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion +from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id, add_optional_literal def add_snippet_to_graph(snippet: Snippet, graph: Graph, doc_namespace: str, diff --git a/src/spdx/writer/rdf/writer_utils.py b/src/spdx/writer/rdf/writer_utils.py index 1498b75a7..cfbe3b42e 100644 --- a/src/spdx/writer/rdf/writer_utils.py +++ b/src/spdx/writer/rdf/writer_utils.py @@ -10,7 +10,7 @@ # limitations under the License. import logging from datetime import datetime -from typing import Any, Optional, Dict +from typing import Any, Dict, Optional from rdflib import Graph, Literal from rdflib.term import Node diff --git a/src/spdx/writer/tagvalue/annotation_writer.py b/src/spdx/writer/tagvalue/annotation_writer.py index 231a7f5ea..b74991cc8 100644 --- a/src/spdx/writer/tagvalue/annotation_writer.py +++ b/src/spdx/writer/tagvalue/annotation_writer.py @@ -12,7 +12,7 @@ from spdx.datetime_conversions import datetime_to_iso_string from spdx.model.annotation import Annotation -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_value, write_text_value +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value def write_annotation(annotation: Annotation, text_output: TextIO): diff --git a/src/spdx/writer/tagvalue/creation_info_writer.py b/src/spdx/writer/tagvalue/creation_info_writer.py index 219af57a5..53d2da41e 100644 --- a/src/spdx/writer/tagvalue/creation_info_writer.py +++ b/src/spdx/writer/tagvalue/creation_info_writer.py @@ -12,8 +12,12 @@ from spdx.datetime_conversions import datetime_to_iso_string from spdx.model.document import CreationInfo -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_value, write_text_value, write_optional_heading, \ - write_separator +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( + write_optional_heading, + write_separator, + write_text_value, + write_value, +) def write_creation_info(creation_info: CreationInfo, text_output: TextIO): diff --git a/src/spdx/writer/tagvalue/extracted_licensing_info_writer.py b/src/spdx/writer/tagvalue/extracted_licensing_info_writer.py index bddbe48c2..556fb0737 100644 --- a/src/spdx/writer/tagvalue/extracted_licensing_info_writer.py +++ b/src/spdx/writer/tagvalue/extracted_licensing_info_writer.py @@ -11,7 +11,7 @@ from typing import TextIO from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_value, write_text_value +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value def write_extracted_licensing_info(extracted_licensing_info: ExtractedLicensingInfo, text_output: TextIO): diff --git a/src/spdx/writer/tagvalue/file_writer.py b/src/spdx/writer/tagvalue/file_writer.py index a12473738..c2d055fbd 100644 --- a/src/spdx/writer/tagvalue/file_writer.py +++ b/src/spdx/writer/tagvalue/file_writer.py @@ -12,7 +12,7 @@ from spdx.model.file import File from spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_value, write_text_value +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value def write_file(file: File, text_output: TextIO): diff --git a/src/spdx/writer/tagvalue/package_writer.py b/src/spdx/writer/tagvalue/package_writer.py index 74e4adeb6..0a6fbd283 100644 --- a/src/spdx/writer/tagvalue/package_writer.py +++ b/src/spdx/writer/tagvalue/package_writer.py @@ -13,8 +13,12 @@ from spdx.datetime_conversions import datetime_to_iso_string from spdx.model.package import Package, PackageVerificationCode from spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_value, write_text_value, \ - transform_enum_name_to_tv, write_actor +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( + transform_enum_name_to_tv, + write_actor, + write_text_value, + write_value, +) def write_package(package: Package, text_output: TextIO): diff --git a/src/spdx/writer/tagvalue/relationship_writer.py b/src/spdx/writer/tagvalue/relationship_writer.py index 8972996df..4af58466c 100644 --- a/src/spdx/writer/tagvalue/relationship_writer.py +++ b/src/spdx/writer/tagvalue/relationship_writer.py @@ -11,7 +11,7 @@ from typing import TextIO from spdx.model.relationship import Relationship -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_value, write_text_value +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value def write_relationship(relationship: Relationship, text_output: TextIO): diff --git a/src/spdx/writer/tagvalue/snippet_writer.py b/src/spdx/writer/tagvalue/snippet_writer.py index eee6b6416..55230bb07 100644 --- a/src/spdx/writer/tagvalue/snippet_writer.py +++ b/src/spdx/writer/tagvalue/snippet_writer.py @@ -11,7 +11,8 @@ from typing import TextIO from spdx.model.snippet import Snippet -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_value, write_text_value, write_range +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range, write_text_value, write_value + def write_snippet(snippet: Snippet, text_output: TextIO): text_output.write("## Snippet Information\n") diff --git a/src/spdx/writer/tagvalue/tagvalue_writer.py b/src/spdx/writer/tagvalue/tagvalue_writer.py index 92db6f2e1..2fc36bbea 100644 --- a/src/spdx/writer/tagvalue/tagvalue_writer.py +++ b/src/spdx/writer/tagvalue/tagvalue_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import TextIO, List +from typing import List, TextIO from spdx.model.document import Document from spdx.validation.document_validator import validate_full_spdx_document @@ -20,8 +20,13 @@ from spdx.writer.tagvalue.package_writer import write_package from spdx.writer.tagvalue.relationship_writer import write_relationship from spdx.writer.tagvalue.snippet_writer import write_snippet -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_separator, scan_relationships, \ - get_file_ids_with_contained_snippets, write_optional_heading, write_list_of_elements +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( + get_file_ids_with_contained_snippets, + scan_relationships, + write_list_of_elements, + write_optional_heading, + write_separator, +) def write_document_to_file(document: Document, file_name: str, validate: bool = True): diff --git a/src/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py b/src/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py index 1f30c0f45..3b2d8518d 100644 --- a/src/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py +++ b/src/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py @@ -8,11 +8,12 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import TextIO, Tuple, List, Dict, Any, Union, Callable, Optional +from typing import Any, Callable, Dict, List, Optional, TextIO, Tuple, Union + +from license_expression import LicenseExpression from spdx.model.actor import Actor from spdx.model.file import File -from license_expression import LicenseExpression from spdx.model.package import Package from spdx.model.relationship import Relationship, RelationshipType from spdx.model.snippet import Snippet diff --git a/src/spdx/writer/write_anything.py b/src/spdx/writer/write_anything.py index 7f8c67c21..b3ba5248e 100644 --- a/src/spdx/writer/write_anything.py +++ b/src/spdx/writer/write_anything.py @@ -8,11 +8,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from spdx.writer.rdf import rdf_writer - -from spdx.formats import file_name_to_format, FileFormat +from spdx.formats import FileFormat, file_name_to_format from spdx.model.document import Document from spdx.writer.json import json_writer +from spdx.writer.rdf import rdf_writer from spdx.writer.tagvalue import tagvalue_writer from spdx.writer.xml import xml_writer from spdx.writer.yaml import yaml_writer diff --git a/tests/spdx/fixtures.py b/tests/spdx/fixtures.py index 1158a87ef..3191678a9 100644 --- a/tests/spdx/fixtures.py +++ b/tests/spdx/fixtures.py @@ -19,8 +19,13 @@ from spdx.model.external_document_ref import ExternalDocumentRef from spdx.model.extracted_licensing_info import ExtractedLicensingInfo from spdx.model.file import File, FileType -from spdx.model.package import Package, PackageVerificationCode, PackagePurpose, ExternalPackageRef, \ - ExternalPackageRefCategory +from spdx.model.package import ( + ExternalPackageRef, + ExternalPackageRefCategory, + Package, + PackagePurpose, + PackageVerificationCode, +) from spdx.model.relationship import Relationship, RelationshipType from spdx.model.snippet import Snippet from spdx.model.spdx_no_assertion import SpdxNoAssertion diff --git a/tests/spdx/jsonschema/test_converter.py b/tests/spdx/jsonschema/test_converter.py index daf337491..20b8bed01 100644 --- a/tests/spdx/jsonschema/test_converter.py +++ b/tests/spdx/jsonschema/test_converter.py @@ -9,16 +9,16 @@ # See the License for the specific language governing permissions and # limitations under the License. from enum import auto -from typing import Type, Any +from typing import Any, Type import pytest +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values from spdx.jsonschema.converter import TypedConverter from spdx.jsonschema.json_property import JsonProperty from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.model.document import Document -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values class TestPropertyType(JsonProperty): diff --git a/tests/spdx/jsonschema/test_document_converter.py b/tests/spdx/jsonschema/test_document_converter.py index 0d5603fb4..f2742ce26 100644 --- a/tests/spdx/jsonschema/test_document_converter.py +++ b/tests/spdx/jsonschema/test_document_converter.py @@ -24,8 +24,16 @@ from spdx.model.document import Document from spdx.model.extracted_licensing_info import ExtractedLicensingInfo from spdx.model.relationship import Relationship, RelationshipType -from tests.spdx.fixtures import creation_info_fixture, file_fixture, package_fixture, external_document_ref_fixture, \ - snippet_fixture, annotation_fixture, document_fixture, relationship_fixture +from tests.spdx.fixtures import ( + annotation_fixture, + creation_info_fixture, + document_fixture, + external_document_ref_fixture, + file_fixture, + package_fixture, + relationship_fixture, + snippet_fixture, +) from tests.spdx.mock_utils import assert_mock_method_called_with_arguments, assert_no_mock_methods_called diff --git a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py index 05ec55a5f..780f57a04 100644 --- a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py +++ b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py @@ -13,7 +13,7 @@ from spdx.jsonschema.extracted_licensing_info_converter import ExtractedLicensingInfoConverter from spdx.jsonschema.extracted_licensing_info_properties import ExtractedLicensingInfoProperty from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.model.spdx_no_assertion import SpdxNoAssertion, SPDX_NO_ASSERTION_STRING +from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion from tests.spdx.fixtures import extracted_licensing_info_fixture diff --git a/tests/spdx/jsonschema/test_file_converter.py b/tests/spdx/jsonschema/test_file_converter.py index 51dd84ed0..4885e367a 100644 --- a/tests/spdx/jsonschema/test_file_converter.py +++ b/tests/spdx/jsonschema/test_file_converter.py @@ -14,6 +14,7 @@ from unittest.mock import MagicMock, NonCallableMagicMock import pytest +from license_expression import Licensing from spdx.jsonschema.annotation_converter import AnnotationConverter from spdx.jsonschema.file_converter import FileConverter @@ -23,10 +24,9 @@ from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.model.document import Document from spdx.model.file import File, FileType -from license_expression import Licensing -from spdx.model.spdx_no_assertion import SpdxNoAssertion, SPDX_NO_ASSERTION_STRING -from spdx.model.spdx_none import SpdxNone, SPDX_NONE_STRING -from tests.spdx.fixtures import creation_info_fixture, file_fixture, annotation_fixture, document_fixture +from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion +from spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from tests.spdx.fixtures import annotation_fixture, creation_info_fixture, document_fixture, file_fixture from tests.spdx.mock_utils import assert_mock_method_called_with_arguments diff --git a/tests/spdx/jsonschema/test_package_converter.py b/tests/spdx/jsonschema/test_package_converter.py index 4c2b18b37..a8e2ba9f2 100644 --- a/tests/spdx/jsonschema/test_package_converter.py +++ b/tests/spdx/jsonschema/test_package_converter.py @@ -14,6 +14,7 @@ from unittest.mock import MagicMock, NonCallableMagicMock import pytest +from license_expression import Licensing from spdx.jsonschema.annotation_converter import AnnotationConverter from spdx.jsonschema.package_converter import PackageConverter @@ -22,13 +23,20 @@ from spdx.model.annotation import Annotation, AnnotationType from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.model.document import Document -from license_expression import Licensing -from spdx.model.package import Package, PackageVerificationCode, PackagePurpose +from spdx.model.package import Package, PackagePurpose, PackageVerificationCode from spdx.model.relationship import RelationshipType -from spdx.model.spdx_no_assertion import SpdxNoAssertion, SPDX_NO_ASSERTION_STRING -from spdx.model.spdx_none import SpdxNone, SPDX_NONE_STRING -from tests.spdx.fixtures import creation_info_fixture, package_fixture, external_package_ref_fixture, document_fixture, \ - annotation_fixture, file_fixture, relationship_fixture, snippet_fixture +from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion +from spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from tests.spdx.fixtures import ( + annotation_fixture, + creation_info_fixture, + document_fixture, + external_package_ref_fixture, + file_fixture, + package_fixture, + relationship_fixture, + snippet_fixture, +) from tests.spdx.mock_utils import assert_mock_method_called_with_arguments diff --git a/tests/spdx/jsonschema/test_relationship_converter.py b/tests/spdx/jsonschema/test_relationship_converter.py index f6d3d5050..0926ca5c7 100644 --- a/tests/spdx/jsonschema/test_relationship_converter.py +++ b/tests/spdx/jsonschema/test_relationship_converter.py @@ -13,8 +13,8 @@ from spdx.jsonschema.relationship_converter import RelationshipConverter from spdx.jsonschema.relationship_properties import RelationshipProperty from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.spdx_no_assertion import SpdxNoAssertion, SPDX_NO_ASSERTION_STRING -from spdx.model.spdx_none import SpdxNone, SPDX_NONE_STRING +from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion +from spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone from tests.spdx.fixtures import relationship_fixture diff --git a/tests/spdx/jsonschema/test_snippet_converter.py b/tests/spdx/jsonschema/test_snippet_converter.py index 7752a2a6b..b7d07193d 100644 --- a/tests/spdx/jsonschema/test_snippet_converter.py +++ b/tests/spdx/jsonschema/test_snippet_converter.py @@ -14,6 +14,7 @@ from unittest.mock import MagicMock, NonCallableMagicMock import pytest +from license_expression import Licensing from spdx.jsonschema.annotation_converter import AnnotationConverter from spdx.jsonschema.snippet_converter import SnippetConverter @@ -21,11 +22,10 @@ from spdx.model.actor import Actor, ActorType from spdx.model.annotation import Annotation, AnnotationType from spdx.model.document import Document -from license_expression import Licensing from spdx.model.snippet import Snippet -from spdx.model.spdx_no_assertion import SpdxNoAssertion, SPDX_NO_ASSERTION_STRING -from spdx.model.spdx_none import SpdxNone, SPDX_NONE_STRING -from tests.spdx.fixtures import creation_info_fixture, snippet_fixture, document_fixture, annotation_fixture +from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion +from spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from tests.spdx.fixtures import annotation_fixture, creation_info_fixture, document_fixture, snippet_fixture from tests.spdx.mock_utils import assert_mock_method_called_with_arguments diff --git a/tests/spdx/model/test_package.py b/tests/spdx/model/test_package.py index a2fcf7961..c1c538f16 100644 --- a/tests/spdx/model/test_package.py +++ b/tests/spdx/model/test_package.py @@ -2,9 +2,9 @@ from unittest import mock import pytest +from license_expression import LicenseExpression, Licensing from spdx.model.checksum import Checksum, ChecksumAlgorithm -from license_expression import LicenseExpression, Licensing from spdx.model.package import Package, PackagePurpose from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone diff --git a/tests/spdx/parser/json/test_json_parser.py b/tests/spdx/parser/json/test_json_parser.py index d547332f0..f83a62be8 100644 --- a/tests/spdx/parser/json/test_json_parser.py +++ b/tests/spdx/parser/json/test_json_parser.py @@ -10,11 +10,13 @@ # limitations under the License. import os + import pytest from spdx.model.document import Document from spdx.parser.json import json_parser + def test_parse_json_file_not_found(): with pytest.raises(FileNotFoundError) as err: wrong_file_path = os.path.join(os.path.dirname(__file__), 'hnjfkjsedhnflsiafg.json') diff --git a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py index 7bf6b66f8..f68944cbd 100644 --- a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py @@ -14,7 +14,7 @@ import pytest from spdx.model.actor import Actor, ActorType -from spdx.model.annotation import AnnotationType, Annotation +from spdx.model.annotation import Annotation, AnnotationType from spdx.parser.error import SPDXParsingError from spdx.parser.jsonlikedict.annotation_parser import AnnotationParser diff --git a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py index 93b569362..bea9d74a7 100644 --- a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py +++ b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py @@ -15,8 +15,11 @@ from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.dict_parsing_functions import json_str_to_enum_name, \ - parse_field_or_no_assertion, parse_field_or_no_assertion_or_none +from spdx.parser.jsonlikedict.dict_parsing_functions import ( + json_str_to_enum_name, + parse_field_or_no_assertion, + parse_field_or_no_assertion_or_none, +) def test_json_str_to_enum(): diff --git a/tests/spdx/parser/jsonlikedict/test_file_parser.py b/tests/spdx/parser/jsonlikedict/test_file_parser.py index d08262dd4..5987b66e2 100644 --- a/tests/spdx/parser/jsonlikedict/test_file_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_file_parser.py @@ -11,11 +11,10 @@ from unittest import TestCase import pytest +from license_expression import Licensing from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.model.file import FileType -from license_expression import Licensing - from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.parser.error import SPDXParsingError from spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements diff --git a/tests/spdx/parser/jsonlikedict/test_package_parser.py b/tests/spdx/parser/jsonlikedict/test_package_parser.py index 809bab34c..367f3b795 100644 --- a/tests/spdx/parser/jsonlikedict/test_package_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_package_parser.py @@ -12,11 +12,11 @@ from unittest import TestCase import pytest +from license_expression import Licensing from spdx.model.actor import Actor, ActorType from spdx.model.checksum import Checksum, ChecksumAlgorithm -from license_expression import Licensing -from spdx.model.package import PackageVerificationCode, ExternalPackageRef, ExternalPackageRefCategory, PackagePurpose +from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory, PackagePurpose, PackageVerificationCode from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.parser.error import SPDXParsingError from spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements diff --git a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py index 79dae728c..3bf8fae2a 100644 --- a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py @@ -12,7 +12,7 @@ import pytest -from spdx.model.relationship import RelationshipType, Relationship +from spdx.model.relationship import Relationship, RelationshipType from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.parser.error import SPDXParsingError from spdx.parser.jsonlikedict.relationship_parser import RelationshipParser diff --git a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py index 27f778caa..14882aa2b 100644 --- a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py @@ -11,7 +11,6 @@ from unittest import TestCase import pytest - from license_expression import Licensing from spdx.model.spdx_no_assertion import SpdxNoAssertion diff --git a/tests/spdx/parser/rdf/test_checksum_parser.py b/tests/spdx/parser/rdf/test_checksum_parser.py index 26b8e0149..4cadb17b3 100644 --- a/tests/spdx/parser/rdf/test_checksum_parser.py +++ b/tests/spdx/parser/rdf/test_checksum_parser.py @@ -12,10 +12,10 @@ import pytest from rdflib import Graph, URIRef -from spdx.parser.error import SPDXParsingError from spdx.model.checksum import ChecksumAlgorithm -from spdx.parser.rdf.checksum_parser import parse_checksum, convert_rdf_to_algorithm +from spdx.parser.error import SPDXParsingError +from spdx.parser.rdf.checksum_parser import convert_rdf_to_algorithm, parse_checksum from spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/tests/spdx/parser/rdf/test_creation_info_parser.py b/tests/spdx/parser/rdf/test_creation_info_parser.py index 71ee6ccd6..0580a3802 100644 --- a/tests/spdx/parser/rdf/test_creation_info_parser.py +++ b/tests/spdx/parser/rdf/test_creation_info_parser.py @@ -10,19 +10,20 @@ # limitations under the License. import os from datetime import datetime -from typing import Tuple, List +from typing import List, Tuple import pytest -from rdflib import Graph, RDF, URIRef +from rdflib import RDF, Graph, URIRef from rdflib.term import Node -from spdx.model.checksum import Checksum, ChecksumAlgorithm - -from spdx.model.version import Version from spdx.model.actor import Actor, ActorType - -from spdx.parser.rdf.creation_info_parser import parse_creation_info, parse_namespace_and_spdx_id, \ - parse_external_document_refs +from spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx.model.version import Version +from spdx.parser.rdf.creation_info_parser import ( + parse_creation_info, + parse_external_document_refs, + parse_namespace_and_spdx_id, +) from spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py b/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py index eb3776f97..db09dd0ff 100644 --- a/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py @@ -10,7 +10,7 @@ # limitations under the License. import os -from rdflib import Graph, RDF +from rdflib import RDF, Graph from spdx.parser.rdf.extracted_licensing_info_parser import parse_extracted_licensing_info from spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py index 9b9f634d5..f6142e3ba 100644 --- a/tests/spdx/parser/rdf/test_file_parser.py +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -12,9 +12,9 @@ from unittest import TestCase from license_expression import get_spdx_licensing -from rdflib import Graph, RDF -from spdx.model.checksum import Checksum, ChecksumAlgorithm +from rdflib import RDF, Graph +from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.model.file import FileType from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.parser.rdf.file_parser import parse_file diff --git a/tests/spdx/parser/rdf/test_graph_parsing_function.py b/tests/spdx/parser/rdf/test_graph_parsing_function.py index c2b76203b..48240aad0 100644 --- a/tests/spdx/parser/rdf/test_graph_parsing_function.py +++ b/tests/spdx/parser/rdf/test_graph_parsing_function.py @@ -9,7 +9,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import pytest -from rdflib import URIRef, Graph, Namespace +from rdflib import Graph, Namespace, URIRef from spdx.parser.rdf.graph_parsing_functions import parse_spdx_id, remove_prefix diff --git a/tests/spdx/parser/rdf/test_license_expression_parser.py b/tests/spdx/parser/rdf/test_license_expression_parser.py index 0913a961a..012e8854e 100644 --- a/tests/spdx/parser/rdf/test_license_expression_parser.py +++ b/tests/spdx/parser/rdf/test_license_expression_parser.py @@ -12,12 +12,13 @@ from unittest import TestCase from license_expression import get_spdx_licensing -from rdflib import Graph, RDF -from spdx.parser.rdf import rdf_parser +from rdflib import RDF, Graph +from spdx.parser.rdf import rdf_parser from spdx.parser.rdf.license_expression_parser import parse_license_expression from spdx.rdfschema.namespace import SPDX_NAMESPACE + def test_license_expression_parser(): graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) package_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Package) diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index f219496a2..1b87e8f7f 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -16,10 +16,10 @@ from rdflib import RDF, Graph, Literal from spdx.model.actor import Actor, ActorType -from spdx.model.checksum import ChecksumAlgorithm, Checksum -from spdx.model.package import PackagePurpose, PackageVerificationCode, ExternalPackageRefCategory +from spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx.model.package import ExternalPackageRefCategory, PackagePurpose, PackageVerificationCode from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.parser.rdf.package_parser import parse_package, parse_external_package_ref +from spdx.parser.rdf.package_parser import parse_external_package_ref, parse_package from spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/tests/spdx/parser/rdf/test_relationship_parser.py b/tests/spdx/parser/rdf/test_relationship_parser.py index b4b794bcf..e96fee535 100644 --- a/tests/spdx/parser/rdf/test_relationship_parser.py +++ b/tests/spdx/parser/rdf/test_relationship_parser.py @@ -10,7 +10,7 @@ # limitations under the License. import os -from rdflib import Graph, RDF +from rdflib import RDF, Graph from spdx.model.relationship import RelationshipType from spdx.parser.rdf.relationship_parser import parse_relationship diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index b0af0bedf..a301a28d3 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -13,12 +13,12 @@ import pytest from license_expression import get_spdx_licensing -from rdflib import Graph, RDF, BNode, Literal +from rdflib import RDF, BNode, Graph, Literal from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.parser.error import SPDXParsingError -from spdx.parser.rdf.snippet_parser import parse_snippet, parse_ranges -from spdx.rdfschema.namespace import SPDX_NAMESPACE, POINTER_NAMESPACE +from spdx.parser.rdf.snippet_parser import parse_ranges, parse_snippet +from spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE def test_parse_snippet(): diff --git a/tests/spdx/parser/tagvalue/test_relationship_parser.py b/tests/spdx/parser/tagvalue/test_relationship_parser.py index 90ef9da4e..4c2d7b9a3 100644 --- a/tests/spdx/parser/tagvalue/test_relationship_parser.py +++ b/tests/spdx/parser/tagvalue/test_relationship_parser.py @@ -10,7 +10,7 @@ # limitations under the License. import pytest -from spdx.model.relationship import RelationshipType, Relationship +from spdx.model.relationship import Relationship, RelationshipType from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone from spdx.parser.error import SPDXParsingError diff --git a/tests/spdx/parser/tagvalue/test_tag_value_parser.py b/tests/spdx/parser/tagvalue/test_tag_value_parser.py index f194af2a7..192502033 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_parser.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_parser.py @@ -14,7 +14,7 @@ import pytest from spdx.model.document import Document -from spdx.model.relationship import RelationshipType, Relationship +from spdx.model.relationship import Relationship, RelationshipType from spdx.parser.error import SPDXParsingError from spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/test_actor_parser.py b/tests/spdx/test_actor_parser.py index 2e956a14f..cdaf6ef16 100644 --- a/tests/spdx/test_actor_parser.py +++ b/tests/spdx/test_actor_parser.py @@ -8,12 +8,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import pytest from unittest import TestCase +import pytest + from spdx.model.actor import ActorType -from spdx.parser.error import SPDXParsingError from spdx.parser.actor_parser import ActorParser +from spdx.parser.error import SPDXParsingError @pytest.mark.parametrize("actor_string,expected_type,expected_name,expected_mail", [ diff --git a/tests/spdx/test_casing_tools.py b/tests/spdx/test_casing_tools.py index c5be2beb3..572feb7b4 100644 --- a/tests/spdx/test_casing_tools.py +++ b/tests/spdx/test_casing_tools.py @@ -10,7 +10,7 @@ # limitations under the License. import pytest -from spdx.casing_tools import snake_case_to_camel_case, camel_case_to_snake_case +from spdx.casing_tools import camel_case_to_snake_case, snake_case_to_camel_case @pytest.mark.parametrize("snake_case_str,camel_case_str", [("snake_case", "snakeCase")]) diff --git a/tests/spdx/test_document_utils.py b/tests/spdx/test_document_utils.py index f2b0fb2ad..4c69f229d 100644 --- a/tests/spdx/test_document_utils.py +++ b/tests/spdx/test_document_utils.py @@ -5,8 +5,8 @@ import pytest -from spdx.document_utils import get_element_from_spdx_id, get_contained_spdx_element_ids -from tests.spdx.fixtures import document_fixture, snippet_fixture, package_fixture, file_fixture +from spdx.document_utils import get_contained_spdx_element_ids, get_element_from_spdx_id +from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture, snippet_fixture @pytest.fixture diff --git a/tests/spdx/validation/test_actor_validator.py b/tests/spdx/validation/test_actor_validator.py index dbee17547..7203977aa 100644 --- a/tests/spdx/validation/test_actor_validator.py +++ b/tests/spdx/validation/test_actor_validator.py @@ -15,7 +15,7 @@ from spdx.model.actor import ActorType from spdx.validation.actor_validator import validate_actor -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import actor_fixture diff --git a/tests/spdx/validation/test_annotation_validator.py b/tests/spdx/validation/test_annotation_validator.py index 608de5bb8..3a0e0d937 100644 --- a/tests/spdx/validation/test_annotation_validator.py +++ b/tests/spdx/validation/test_annotation_validator.py @@ -16,8 +16,8 @@ from spdx.model.annotation import Annotation from spdx.model.document import Document from spdx.validation.annotation_validator import validate_annotation -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType -from tests.spdx.fixtures import document_fixture, annotation_fixture, file_fixture +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import annotation_fixture, document_fixture, file_fixture def test_valid_annotation(): diff --git a/tests/spdx/validation/test_checksum_validator.py b/tests/spdx/validation/test_checksum_validator.py index 995806a28..42f6dc74e 100644 --- a/tests/spdx/validation/test_checksum_validator.py +++ b/tests/spdx/validation/test_checksum_validator.py @@ -15,7 +15,7 @@ from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.validation.checksum_validator import validate_checksum -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import checksum_fixture diff --git a/tests/spdx/validation/test_creation_info_validator.py b/tests/spdx/validation/test_creation_info_validator.py index 4e62e6fbc..d502aa1a0 100644 --- a/tests/spdx/validation/test_creation_info_validator.py +++ b/tests/spdx/validation/test_creation_info_validator.py @@ -14,7 +14,7 @@ import pytest from spdx.validation.creation_info_validator import validate_creation_info -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import creation_info_fixture diff --git a/tests/spdx/validation/test_document_validator.py b/tests/spdx/validation/test_document_validator.py index f9a66d1b5..8cf9fe043 100644 --- a/tests/spdx/validation/test_document_validator.py +++ b/tests/spdx/validation/test_document_validator.py @@ -13,11 +13,11 @@ import pytest -from spdx.model.document import Document, CreationInfo +from spdx.model.document import CreationInfo, Document from spdx.model.relationship import Relationship, RelationshipType from spdx.validation.document_validator import validate_full_spdx_document -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType -from tests.spdx.fixtures import document_fixture, creation_info_fixture, file_fixture, package_fixture, snippet_fixture +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import creation_info_fixture, document_fixture, file_fixture, package_fixture, snippet_fixture def test_valid_document(): diff --git a/tests/spdx/validation/test_external_package_ref_validator.py b/tests/spdx/validation/test_external_package_ref_validator.py index e9e50f7f5..adcdebaab 100644 --- a/tests/spdx/validation/test_external_package_ref_validator.py +++ b/tests/spdx/validation/test_external_package_ref_validator.py @@ -14,9 +14,19 @@ import pytest from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory -from spdx.validation.external_package_ref_validator import validate_external_package_ref, CPE22TYPE_REGEX, \ - CPE23TYPE_REGEX, MAVEN_CENTRAL_REGEX, NPM_REGEX, NUGET_REGEX, BOWER_REGEX, PURL_REGEX, SWH_REGEX, GITOID_REGEX -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.external_package_ref_validator import ( + BOWER_REGEX, + CPE22TYPE_REGEX, + CPE23TYPE_REGEX, + GITOID_REGEX, + MAVEN_CENTRAL_REGEX, + NPM_REGEX, + NUGET_REGEX, + PURL_REGEX, + SWH_REGEX, + validate_external_package_ref, +) +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage @pytest.mark.parametrize("category, reference_type, locator", diff --git a/tests/spdx/validation/test_extracted_licensing_info_validator.py b/tests/spdx/validation/test_extracted_licensing_info_validator.py index a85068f59..00b2b255e 100644 --- a/tests/spdx/validation/test_extracted_licensing_info_validator.py +++ b/tests/spdx/validation/test_extracted_licensing_info_validator.py @@ -14,7 +14,7 @@ import pytest from spdx.validation.extracted_licensing_info_validator import validate_extracted_licensing_info -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import extracted_licensing_info_fixture diff --git a/tests/spdx/validation/test_file_validator.py b/tests/spdx/validation/test_file_validator.py index b1fb6b41d..e71423b15 100644 --- a/tests/spdx/validation/test_file_validator.py +++ b/tests/spdx/validation/test_file_validator.py @@ -15,9 +15,9 @@ import pytest from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.validation.file_validator import validate_file_within_document, validate_file -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType -from tests.spdx.fixtures import file_fixture, document_fixture +from spdx.validation.file_validator import validate_file, validate_file_within_document +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import document_fixture, file_fixture def test_valid_file(): diff --git a/tests/spdx/validation/test_license_expression_validator.py b/tests/spdx/validation/test_license_expression_validator.py index 2bcdef5f1..c0ca3d5c7 100644 --- a/tests/spdx/validation/test_license_expression_validator.py +++ b/tests/spdx/validation/test_license_expression_validator.py @@ -13,16 +13,15 @@ from unittest import TestCase import pytest -from license_expression import get_spdx_licensing, LicenseExpression +from license_expression import LicenseExpression, get_spdx_licensing from spdx.model.document import Document from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone from spdx.validation.license_expression_validator import validate_license_expression, validate_license_expressions -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import document_fixture, extracted_licensing_info_fixture - FIXTURE_LICENSE_ID = extracted_licensing_info_fixture().license_id diff --git a/tests/spdx/validation/test_package_validator.py b/tests/spdx/validation/test_package_validator.py index fe054201a..565b01c57 100644 --- a/tests/spdx/validation/test_package_validator.py +++ b/tests/spdx/validation/test_package_validator.py @@ -18,9 +18,9 @@ from spdx.model.relationship import Relationship, RelationshipType from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone -from spdx.validation.package_validator import validate_package_within_document, validate_package -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType -from tests.spdx.fixtures import package_fixture, package_verification_code_fixture, document_fixture, file_fixture +from spdx.validation.package_validator import validate_package, validate_package_within_document +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture, package_verification_code_fixture def test_valid_package(): diff --git a/tests/spdx/validation/test_package_verification_code_validator.py b/tests/spdx/validation/test_package_verification_code_validator.py index d94d56be3..16c1eea02 100644 --- a/tests/spdx/validation/test_package_verification_code_validator.py +++ b/tests/spdx/validation/test_package_verification_code_validator.py @@ -13,7 +13,7 @@ from spdx.model.package import PackageVerificationCode from spdx.validation.package_verification_code_validator import validate_verification_code -from spdx.validation.validation_message import ValidationContext, SpdxElementType, ValidationMessage +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def test_valid_package_verification_code(): diff --git a/tests/spdx/validation/test_relationship_validator.py b/tests/spdx/validation/test_relationship_validator.py index 32e4c114b..464fe6e61 100644 --- a/tests/spdx/validation/test_relationship_validator.py +++ b/tests/spdx/validation/test_relationship_validator.py @@ -18,7 +18,7 @@ from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone from spdx.validation.relationship_validator import validate_relationship -from spdx.validation.validation_message import ValidationMessage, SpdxElementType, ValidationContext +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import document_fixture, relationship_fixture diff --git a/tests/spdx/validation/test_snippet_validator.py b/tests/spdx/validation/test_snippet_validator.py index 90bd4aca1..764c68abe 100644 --- a/tests/spdx/validation/test_snippet_validator.py +++ b/tests/spdx/validation/test_snippet_validator.py @@ -14,8 +14,8 @@ import pytest -from spdx.validation.snippet_validator import validate_snippet_within_document, validate_snippet -from spdx.validation.validation_message import ValidationMessage, ValidationContext, SpdxElementType +from spdx.validation.snippet_validator import validate_snippet, validate_snippet_within_document +from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import document_fixture, snippet_fixture diff --git a/tests/spdx/validation/test_spdx_id_validators.py b/tests/spdx/validation/test_spdx_id_validators.py index bcf8745c1..4ee3a4c9c 100644 --- a/tests/spdx/validation/test_spdx_id_validators.py +++ b/tests/spdx/validation/test_spdx_id_validators.py @@ -12,10 +12,22 @@ import pytest -from spdx.validation.spdx_id_validators import is_valid_internal_spdx_id, is_valid_external_doc_ref_id, \ - get_list_of_all_spdx_ids, is_spdx_id_present_in_document, is_external_doc_ref_present_in_document, validate_spdx_id -from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture, snippet_fixture, creation_info_fixture, \ - external_document_ref_fixture +from spdx.validation.spdx_id_validators import ( + get_list_of_all_spdx_ids, + is_external_doc_ref_present_in_document, + is_spdx_id_present_in_document, + is_valid_external_doc_ref_id, + is_valid_internal_spdx_id, + validate_spdx_id, +) +from tests.spdx.fixtures import ( + creation_info_fixture, + document_fixture, + external_document_ref_fixture, + file_fixture, + package_fixture, + snippet_fixture, +) DOCUMENT = document_fixture(files=[file_fixture(spdx_id="SPDXRef-File1"), file_fixture(spdx_id="SPDXRef-File2")], diff --git a/tests/spdx/validation/test_uri_validators.py b/tests/spdx/validation/test_uri_validators.py index a692ee8c7..fe59b9b74 100644 --- a/tests/spdx/validation/test_uri_validators.py +++ b/tests/spdx/validation/test_uri_validators.py @@ -11,7 +11,7 @@ import pytest -from spdx.validation.uri_validators import validate_url, validate_download_location, validate_uri +from spdx.validation.uri_validators import validate_download_location, validate_uri, validate_url @pytest.mark.parametrize("input_value", ["https://some.url", diff --git a/tests/spdx/writer/rdf/test_annotation_writer.py b/tests/spdx/writer/rdf/test_annotation_writer.py index 435599b85..1e616ac6a 100644 --- a/tests/spdx/writer/rdf/test_annotation_writer.py +++ b/tests/spdx/writer/rdf/test_annotation_writer.py @@ -8,11 +8,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import Graph, Literal, RDFS, URIRef, RDF +from rdflib import RDF, RDFS, Graph, Literal, URIRef from spdx.datetime_conversions import datetime_to_iso_string -from spdx.writer.rdf.annotation_writer import add_annotation_to_graph from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx.writer.rdf.annotation_writer import add_annotation_to_graph from tests.spdx.fixtures import annotation_fixture diff --git a/tests/spdx/writer/rdf/test_checksum_writer.py b/tests/spdx/writer/rdf/test_checksum_writer.py index 535418dff..b2426a123 100644 --- a/tests/spdx/writer/rdf/test_checksum_writer.py +++ b/tests/spdx/writer/rdf/test_checksum_writer.py @@ -9,11 +9,11 @@ # See the License for the specific language governing permissions and # limitations under the License. import pytest -from rdflib import Graph, URIRef, Literal, RDF +from rdflib import RDF, Graph, Literal, URIRef from spdx.model.checksum import ChecksumAlgorithm -from spdx.writer.rdf.checksum_writer import add_checksum_to_graph, algorithm_to_rdf_string from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx.writer.rdf.checksum_writer import add_checksum_to_graph, algorithm_to_rdf_string from tests.spdx.fixtures import checksum_fixture diff --git a/tests/spdx/writer/rdf/test_creation_info_writer.py b/tests/spdx/writer/rdf/test_creation_info_writer.py index 6237208ff..0a3e5155a 100644 --- a/tests/spdx/writer/rdf/test_creation_info_writer.py +++ b/tests/spdx/writer/rdf/test_creation_info_writer.py @@ -8,11 +8,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import Graph, Literal, RDFS, URIRef, RDF +from rdflib import RDF, RDFS, Graph, Literal, URIRef from spdx.datetime_conversions import datetime_to_iso_string +from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE from spdx.writer.rdf.creation_info_writer import add_creation_info_to_graph -from spdx.rdfschema.namespace import SPDX_NAMESPACE, LICENSE_NAMESPACE from tests.spdx.fixtures import creation_info_fixture diff --git a/tests/spdx/writer/rdf/test_external_document_ref_writer.py b/tests/spdx/writer/rdf/test_external_document_ref_writer.py index a8c206df1..673eb2873 100644 --- a/tests/spdx/writer/rdf/test_external_document_ref_writer.py +++ b/tests/spdx/writer/rdf/test_external_document_ref_writer.py @@ -8,9 +8,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import Graph, URIRef, RDF -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from rdflib import RDF, Graph, URIRef +from spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx.writer.rdf.external_document_ref_writer import add_external_document_ref_to_graph from tests.spdx.fixtures import external_document_ref_fixture diff --git a/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py b/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py index 55669dae5..3019d62ac 100644 --- a/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py +++ b/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py @@ -8,9 +8,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import Graph, Literal, RDFS, URIRef, RDF -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from rdflib import RDF, RDFS, Graph, Literal, URIRef +from spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx.writer.rdf.extracted_licensing_info_writer import add_extracted_licensing_info_to_graph from tests.spdx.fixtures import extracted_licensing_info_fixture diff --git a/tests/spdx/writer/rdf/test_file_writer.py b/tests/spdx/writer/rdf/test_file_writer.py index a8efc647a..d28a1c9b8 100644 --- a/tests/spdx/writer/rdf/test_file_writer.py +++ b/tests/spdx/writer/rdf/test_file_writer.py @@ -8,10 +8,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import Graph, Literal, RDFS, RDF, URIRef +from rdflib import RDF, RDFS, Graph, Literal, URIRef +from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE from spdx.writer.rdf.file_writer import add_file_to_graph -from spdx.rdfschema.namespace import SPDX_NAMESPACE, LICENSE_NAMESPACE from tests.spdx.fixtures import file_fixture diff --git a/tests/spdx/writer/rdf/test_license_expression_writer.py b/tests/spdx/writer/rdf/test_license_expression_writer.py index 8f7d9ff5c..c77641860 100644 --- a/tests/spdx/writer/rdf/test_license_expression_writer.py +++ b/tests/spdx/writer/rdf/test_license_expression_writer.py @@ -10,9 +10,9 @@ # limitations under the License. import pytest from license_expression import get_spdx_licensing -from rdflib import Graph, URIRef, RDF, Literal -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from rdflib import RDF, Graph, Literal, URIRef +from spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx.writer.rdf.license_expression_writer import add_license_expression_to_graph diff --git a/tests/spdx/writer/rdf/test_package_writer.py b/tests/spdx/writer/rdf/test_package_writer.py index 7f57a7b4b..b1f5ece06 100644 --- a/tests/spdx/writer/rdf/test_package_writer.py +++ b/tests/spdx/writer/rdf/test_package_writer.py @@ -9,14 +9,17 @@ # See the License for the specific language governing permissions and # limitations under the License. import pytest -from rdflib import Graph, URIRef, RDF, Literal, XSD, RDFS, DOAP -from spdx.model.package import ExternalPackageRefCategory +from rdflib import DOAP, RDF, RDFS, XSD, Graph, Literal, URIRef from spdx.datetime_conversions import datetime_to_iso_string -from spdx.writer.rdf.package_writer import add_package_to_graph, add_external_package_ref_to_graph, \ - add_package_verification_code_to_graph -from spdx.rdfschema.namespace import SPDX_NAMESPACE, LICENSE_NAMESPACE -from tests.spdx.fixtures import package_fixture, external_package_ref_fixture, package_verification_code_fixture +from spdx.model.package import ExternalPackageRefCategory +from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE +from spdx.writer.rdf.package_writer import ( + add_external_package_ref_to_graph, + add_package_to_graph, + add_package_verification_code_to_graph, +) +from tests.spdx.fixtures import external_package_ref_fixture, package_fixture, package_verification_code_fixture def test_add_package_to_graph(): diff --git a/tests/spdx/writer/rdf/test_rdf_writer.py b/tests/spdx/writer/rdf/test_rdf_writer.py index 38e4f5871..3d99c2389 100644 --- a/tests/spdx/writer/rdf/test_rdf_writer.py +++ b/tests/spdx/writer/rdf/test_rdf_writer.py @@ -12,10 +12,9 @@ import pytest -from tests.spdx.fixtures import document_fixture - from spdx.model.document import Document from spdx.writer.rdf.rdf_writer import write_document_to_file +from tests.spdx.fixtures import document_fixture @pytest.fixture diff --git a/tests/spdx/writer/rdf/test_relationship_writer.py b/tests/spdx/writer/rdf/test_relationship_writer.py index fd028d618..74c576585 100644 --- a/tests/spdx/writer/rdf/test_relationship_writer.py +++ b/tests/spdx/writer/rdf/test_relationship_writer.py @@ -8,10 +8,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from rdflib import Graph, URIRef, RDFS, Literal +from rdflib import RDFS, Graph, Literal, URIRef -from spdx.writer.rdf.relationship_writer import add_relationship_to_graph from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx.writer.rdf.relationship_writer import add_relationship_to_graph from tests.spdx.fixtures import relationship_fixture diff --git a/tests/spdx/writer/rdf/test_snippet_writer.py b/tests/spdx/writer/rdf/test_snippet_writer.py index 1951563aa..4dcf539a3 100644 --- a/tests/spdx/writer/rdf/test_snippet_writer.py +++ b/tests/spdx/writer/rdf/test_snippet_writer.py @@ -9,10 +9,10 @@ # See the License for the specific language governing permissions and # limitations under the License. import pytest -from rdflib import Graph, URIRef, RDF, Literal, RDFS -from spdx.rdfschema.namespace import SPDX_NAMESPACE, POINTER_NAMESPACE, LICENSE_NAMESPACE +from rdflib import RDF, RDFS, Graph, Literal, URIRef -from spdx.writer.rdf.snippet_writer import add_snippet_to_graph, add_range_to_graph +from spdx.rdfschema.namespace import LICENSE_NAMESPACE, POINTER_NAMESPACE, SPDX_NAMESPACE +from spdx.writer.rdf.snippet_writer import add_range_to_graph, add_snippet_to_graph from tests.spdx.fixtures import snippet_fixture diff --git a/tests/spdx/writer/tagvalue/test_creation_info_writer.py b/tests/spdx/writer/tagvalue/test_creation_info_writer.py index b4be91b5c..54bd7821f 100644 --- a/tests/spdx/writer/tagvalue/test_creation_info_writer.py +++ b/tests/spdx/writer/tagvalue/test_creation_info_writer.py @@ -2,14 +2,13 @@ # # SPDX-License-Identifier: Apache-2.0 import datetime -from unittest.mock import mock_open, patch, call, MagicMock +from unittest.mock import MagicMock, call, mock_open, patch import pytest from spdx.model.document import CreationInfo -from tests.spdx.fixtures import creation_info_fixture, actor_fixture - from spdx.writer.tagvalue.creation_info_writer import write_creation_info +from tests.spdx.fixtures import actor_fixture, creation_info_fixture @pytest.mark.parametrize("creation_info, expected_calls", diff --git a/tests/spdx/writer/tagvalue/test_package_writer.py b/tests/spdx/writer/tagvalue/test_package_writer.py index 60570d269..a89bcd65a 100644 --- a/tests/spdx/writer/tagvalue/test_package_writer.py +++ b/tests/spdx/writer/tagvalue/test_package_writer.py @@ -8,10 +8,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from unittest.mock import patch, mock_open, call, MagicMock +from unittest.mock import MagicMock, call, mock_open, patch -from tests.spdx.fixtures import package_fixture from spdx.writer.tagvalue.package_writer import write_package +from tests.spdx.fixtures import package_fixture def test_package_writer(): diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py index 1936326ab..bdb442303 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py @@ -14,8 +14,8 @@ import pytest from spdx.parser.tagvalue import tagvalue_parser -from tests.spdx.fixtures import document_fixture from spdx.writer.tagvalue.tagvalue_writer import write_document_to_file +from tests.spdx.fixtures import document_fixture @pytest.fixture diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py index 300a3fd33..a9c4832f0 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py @@ -10,7 +10,7 @@ # limitations under the License. from spdx.model.relationship import RelationshipType from spdx.writer.tagvalue.tagvalue_writer_helper_functions import scan_relationships -from tests.spdx.fixtures import package_fixture, file_fixture, relationship_fixture +from tests.spdx.fixtures import file_fixture, package_fixture, relationship_fixture def test_scan_relationships(): From 913e50f013b30e0ac44856c466a961c9154abe84 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 28 Mar 2023 15:40:47 +0200 Subject: [PATCH 031/354] [code_style] format files with black Signed-off-by: Meret Behrens --- src/common/typing/constructor_type_errors.py | 1 + .../typing/dataclass_with_properties.py | 3 +- src/spdx/clitools/pyspdxtools.py | 38 +- src/spdx/datetime_conversions.py | 4 +- src/spdx/jsonschema/annotation_converter.py | 5 +- src/spdx/jsonschema/checksum_converter.py | 6 +- src/spdx/jsonschema/converter.py | 3 +- .../jsonschema/creation_info_converter.py | 5 +- src/spdx/jsonschema/document_converter.py | 64 +-- .../external_document_ref_converter.py | 9 +- .../external_package_ref_converter.py | 8 +- .../extracted_licensing_info_converter.py | 9 +- src/spdx/jsonschema/json_property.py | 1 + src/spdx/jsonschema/package_converter.py | 32 +- .../package_verification_code_converter.py | 9 +- src/spdx/jsonschema/relationship_converter.py | 5 +- src/spdx/jsonschema/snippet_converter.py | 15 +- src/spdx/model/annotation.py | 10 +- src/spdx/model/document.py | 32 +- src/spdx/model/extracted_licensing_info.py | 11 +- src/spdx/model/file.py | 22 +- src/spdx/model/package.py | 52 ++- src/spdx/model/relationship.py | 9 +- src/spdx/model/relationship_filters.py | 56 ++- src/spdx/model/snippet.py | 20 +- src/spdx/parser/actor_parser.py | 10 +- .../parser/jsonlikedict/annotation_parser.py | 70 ++-- .../jsonlikedict/creation_info_parser.py | 69 ++-- .../jsonlikedict/dict_parsing_functions.py | 19 +- .../extracted_licensing_info_parser.py | 19 +- src/spdx/parser/jsonlikedict/file_parser.py | 45 ++- .../jsonlikedict/json_like_dict_parser.py | 50 ++- .../parser/jsonlikedict/package_parser.py | 139 ++++--- .../jsonlikedict/relationship_parser.py | 124 +++--- .../parser/jsonlikedict/snippet_parser.py | 38 +- src/spdx/parser/rdf/annotation_parser.py | 33 +- src/spdx/parser/rdf/checksum_parser.py | 5 +- src/spdx/parser/rdf/creation_info_parser.py | 76 ++-- .../rdf/extracted_licensing_info_parser.py | 21 +- src/spdx/parser/rdf/file_parser.py | 56 ++- .../parser/rdf/graph_parsing_functions.py | 32 +- .../parser/rdf/license_expression_parser.py | 19 +- src/spdx/parser/rdf/package_parser.py | 161 +++++--- src/spdx/parser/rdf/rdf_parser.py | 21 +- src/spdx/parser/rdf/relationship_parser.py | 34 +- src/spdx/parser/rdf/snippet_parser.py | 62 +-- src/spdx/parser/tagvalue/helper_methods.py | 78 ++-- src/spdx/parser/tagvalue/lexer.py | 25 +- src/spdx/parser/tagvalue/parser.py | 238 ++++++----- src/spdx/parser/xml/xml_parser.py | 4 +- src/spdx/validation/actor_validator.py | 2 +- src/spdx/validation/annotation_validator.py | 3 +- src/spdx/validation/checksum_validator.py | 24 +- .../validation/creation_info_validator.py | 19 +- src/spdx/validation/document_validator.py | 41 +- .../external_document_ref_validator.py | 23 +- .../external_package_ref_validator.py | 82 ++-- .../extracted_licensing_info_validator.py | 20 +- src/spdx/validation/file_validator.py | 33 +- .../license_expression_validator.py | 30 +- src/spdx/validation/package_validator.py | 80 ++-- .../package_verification_code_validator.py | 11 +- src/spdx/validation/relationship_validator.py | 20 +- src/spdx/validation/snippet_validator.py | 51 ++- src/spdx/validation/spdx_id_validators.py | 33 +- src/spdx/validation/uri_validators.py | 3 +- src/spdx/writer/rdf/annotation_writer.py | 21 +- src/spdx/writer/rdf/checksum_writer.py | 3 +- src/spdx/writer/rdf/creation_info_writer.py | 5 +- .../rdf/external_document_ref_writer.py | 9 +- .../rdf/extracted_licensing_info_writer.py | 20 +- src/spdx/writer/rdf/file_writer.py | 22 +- .../writer/rdf/license_expression_writer.py | 25 +- src/spdx/writer/rdf/package_writer.py | 89 +++-- src/spdx/writer/rdf/rdf_writer.py | 6 +- src/spdx/writer/rdf/relationship_writer.py | 31 +- src/spdx/writer/rdf/snippet_writer.py | 46 ++- src/spdx/writer/tagvalue/checksum_writer.py | 2 +- .../writer/tagvalue/creation_info_writer.py | 9 +- src/spdx/writer/tagvalue/package_writer.py | 12 +- .../writer/tagvalue/relationship_writer.py | 14 +- src/spdx/writer/tagvalue/tagvalue_writer.py | 28 +- .../tagvalue_writer_helper_functions.py | 39 +- src/spdx/writer/xml/xml_writer.py | 5 +- src/spdx/writer/yaml/yaml_writer.py | 5 +- tests/spdx/fixtures.py | 317 +++++++++++---- .../jsonschema/test_annotation_converter.py | 18 +- .../jsonschema/test_checksum_converter.py | 8 +- tests/spdx/jsonschema/test_converter.py | 10 +- .../test_creation_info_converter.py | 26 +- .../jsonschema/test_document_converter.py | 202 ++++++---- .../test_external_document_ref_converter.py | 21 +- .../test_external_package_ref_converter.py | 21 +- ...test_extracted_licensing_info_converter.py | 39 +- tests/spdx/jsonschema/test_file_converter.py | 120 ++++-- .../spdx/jsonschema/test_package_converter.py | 265 ++++++++----- ...est_package_verification_code_converter.py | 34 +- .../jsonschema/test_relationship_converter.py | 27 +- .../spdx/jsonschema/test_snippet_converter.py | 107 +++-- tests/spdx/model/test_actor.py | 20 +- tests/spdx/model/test_annotation.py | 12 +- tests/spdx/model/test_creation_info.py | 58 ++- tests/spdx/model/test_document.py | 42 +- .../spdx/model/test_external_document_ref.py | 6 +- .../model/test_external_package_reference.py | 3 +- tests/spdx/model/test_file.py | 42 +- tests/spdx/model/test_package.py | 41 +- tests/spdx/model/test_snippet.py | 15 +- tests/spdx/parser/json/test_json_parser.py | 18 +- .../jsonlikedict/test_annotation_parser.py | 155 +++++--- .../jsonlikedict/test_checksum_parser.py | 27 +- .../jsonlikedict/test_creation_info_parser.py | 92 +++-- .../test_dict_parsing_functions.py | 8 +- .../test_extracted_licensing_info_parser.py | 30 +- .../parser/jsonlikedict/test_file_parser.py | 130 +++--- .../test_license_expression_parser.py | 24 +- .../jsonlikedict/test_package_parser.py | 212 ++++++---- .../jsonlikedict/test_relationship_parser.py | 224 +++++++---- .../jsonlikedict/test_snippet_parser.py | 114 +++--- tests/spdx/parser/rdf/test_checksum_parser.py | 68 ++-- .../parser/rdf/test_creation_info_parser.py | 41 +- tests/spdx/parser/rdf/test_file_parser.py | 7 +- .../parser/rdf/test_graph_parsing_function.py | 26 +- .../rdf/test_license_expression_parser.py | 20 +- tests/spdx/parser/rdf/test_package_parser.py | 36 +- tests/spdx/parser/rdf/test_rdf_parser.py | 5 +- tests/spdx/parser/rdf/test_snippet_parser.py | 115 ++++-- .../parser/tagvalue/test_annotation_parser.py | 62 +-- .../tagvalue/test_creation_info_parser.py | 131 ++++--- .../test_extracted_licensing_info_parser.py | 72 ++-- .../spdx/parser/tagvalue/test_file_parser.py | 63 +-- .../parser/tagvalue/test_helper_methods.py | 126 +++--- .../parser/tagvalue/test_package_parser.py | 156 +++++--- .../tagvalue/test_relationship_parser.py | 61 ++- .../parser/tagvalue/test_snippet_parser.py | 73 ++-- .../parser/tagvalue/test_tag_value_lexer.py | 222 ++++++----- .../parser/tagvalue/test_tag_value_parser.py | 55 ++- tests/spdx/test_actor_parser.py | 36 +- tests/spdx/test_casing_tools.py | 7 +- tests/spdx/test_datetime_conversions.py | 10 +- tests/spdx/validation/test_actor_validator.py | 20 +- .../validation/test_annotation_validator.py | 20 +- .../validation/test_checksum_validator.py | 249 +++++++----- .../test_creation_info_validator.py | 25 +- .../validation/test_document_validator.py | 106 +++-- .../test_external_document_ref_validator.py | 5 +- .../test_external_package_ref_validator.py | 369 +++++++++++------- ...test_extracted_licensing_info_validator.py | 28 +- tests/spdx/validation/test_file_validator.py | 44 ++- .../test_license_expression_validator.py | 110 ++++-- .../spdx/validation/test_package_validator.py | 123 ++++-- ...est_package_verification_code_validator.py | 31 +- .../validation/test_relationship_validator.py | 66 ++-- .../spdx/validation/test_snippet_validator.py | 57 ++- .../validation/test_spdx_id_validators.py | 120 ++++-- tests/spdx/validation/test_uri_validators.py | 150 ++++--- tests/spdx/writer/json/test_json_writer.py | 2 +- tests/spdx/writer/rdf/test_checksum_writer.py | 43 +- .../rdf/test_external_document_ref_writer.py | 9 +- .../rdf/test_license_expression_writer.py | 31 +- tests/spdx/writer/rdf/test_package_writer.py | 36 +- .../writer/rdf/test_relationship_writer.py | 2 +- tests/spdx/writer/rdf/test_snippet_writer.py | 10 +- tests/spdx/writer/rdf/test_writer_utils.py | 20 +- .../tagvalue/test_creation_info_writer.py | 68 +++- .../writer/tagvalue/test_package_writer.py | 63 +-- .../test_tagvalue_writer_helper_functions.py | 19 +- 167 files changed, 5337 insertions(+), 3112 deletions(-) diff --git a/src/common/typing/constructor_type_errors.py b/src/common/typing/constructor_type_errors.py index 52b3a4db8..90c8d8402 100644 --- a/src/common/typing/constructor_type_errors.py +++ b/src/common/typing/constructor_type_errors.py @@ -6,6 +6,7 @@ class ConstructorTypeErrors(TypeError): Helper class that holds a list of error messages. Intended to capture all TypeErrors encountered during a constructor call, instead of raising only the first one. """ + messages: List[str] def __init__(self, messages: List[str]): diff --git a/src/common/typing/dataclass_with_properties.py b/src/common/typing/dataclass_with_properties.py index b53d9eb37..3c73ede87 100644 --- a/src/common/typing/dataclass_with_properties.py +++ b/src/common/typing/dataclass_with_properties.py @@ -50,6 +50,7 @@ def get_field_with_better_error_message(self) -> field_type: # As getters are created dynamically, their argument name is always "the return value". We replace it by the # actual name so the error message is more helpful. raise TypeError( - error_message.replace("the return value", field_name, 1) + f': {getattr(self, f"_{field_name}")}') + error_message.replace("the return value", field_name, 1) + f': {getattr(self, f"_{field_name}")}' + ) return get_field_with_better_error_message diff --git a/src/spdx/clitools/pyspdxtools.py b/src/spdx/clitools/pyspdxtools.py index 44a4a3bac..4f9ea75be 100644 --- a/src/spdx/clitools/pyspdxtools.py +++ b/src/spdx/clitools/pyspdxtools.py @@ -27,11 +27,16 @@ @click.command() @click.option("--infile", "-i", help="The file containing the document to be validated or converted.") -@click.option("--outfile", "-o", - help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion).") -@click.option("--version", - help='The SPDX version to be used during parsing and validation ("SPDX-2.2" or "SPDX-2.3"). Will be read from the document if not provided.', - default=None) +@click.option( + "--outfile", + "-o", + help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion).", +) +@click.option( + "--version", + help='The SPDX version to be used during parsing and validation ("SPDX-2.2" or "SPDX-2.3"). Will be read from the document if not provided.', + default=None, +) @click.option("--novalidation", is_flag=True, help="Don't validate the provided document.") def main(infile: str, outfile: str, version: str, novalidation: bool): """ @@ -56,8 +61,9 @@ def main(infile: str, outfile: str, version: str, novalidation: bool): validation_messages: List[ValidationMessage] = validate_full_spdx_document(document, version) if validation_messages: log_string = "\n".join( - ["The document is invalid. The following issues have been found:"] + - [message.validation_message for message in validation_messages]) + ["The document is invalid. The following issues have been found:"] + + [message.validation_message for message in validation_messages] + ) logging.error(log_string) sys.exit(1) else: @@ -67,16 +73,20 @@ def main(infile: str, outfile: str, version: str, novalidation: bool): write_file(document, outfile, validate=False) except NotImplementedError as err: - logging.error(err.args[0] + - "\nPlease note that this project is currently undergoing a major refactoring and therefore missing " - "a few features which will be added in time (refer to https://github.com/spdx/tools-python/issues " - "for insights into the current status).\n" - "In the meantime, please use the current PyPI release version.") + logging.error( + err.args[0] + + "\nPlease note that this project is currently undergoing a major refactoring and therefore missing " + "a few features which will be added in time (refer to https://github.com/spdx/tools-python/issues " + "for insights into the current status).\n" + "In the meantime, please use the current PyPI release version." + ) sys.exit(1) except SPDXParsingError as err: - log_string = "\n".join(["There have been issues while parsing the provided document:"] + - [message for message in err.get_messages()]) + log_string = "\n".join( + ["There have been issues while parsing the provided document:"] + + [message for message in err.get_messages()] + ) logging.error(log_string) sys.exit(1) diff --git a/src/spdx/datetime_conversions.py b/src/spdx/datetime_conversions.py index 62fafe866..e0a1383bc 100644 --- a/src/spdx/datetime_conversions.py +++ b/src/spdx/datetime_conversions.py @@ -15,12 +15,12 @@ def datetime_from_str(date_str: str) -> datetime: if not isinstance(date_str, str): raise TypeError(f"Could not convert str to datetime, invalid type: {type(date_str).__name__}") - date = datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%SZ") # raises ValueError if format does not match + date = datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%SZ") # raises ValueError if format does not match return date + def datetime_to_iso_string(date: datetime) -> str: """ Return an ISO-8601 representation of a datetime object. """ return date.isoformat() + "Z" - diff --git a/src/spdx/jsonschema/annotation_converter.py b/src/spdx/jsonschema/annotation_converter.py index 24dd14465..b06c932da 100644 --- a/src/spdx/jsonschema/annotation_converter.py +++ b/src/spdx/jsonschema/annotation_converter.py @@ -19,8 +19,9 @@ class AnnotationConverter(TypedConverter[Annotation]): - def _get_property_value(self, annotation: Annotation, annotation_property: AnnotationProperty, - document: Document = None) -> Any: + def _get_property_value( + self, annotation: Annotation, annotation_property: AnnotationProperty, document: Document = None + ) -> Any: if annotation_property == AnnotationProperty.ANNOTATION_DATE: return datetime_to_iso_string(annotation.annotation_date) elif annotation_property == AnnotationProperty.ANNOTATION_TYPE: diff --git a/src/spdx/jsonschema/checksum_converter.py b/src/spdx/jsonschema/checksum_converter.py index 6782adba2..edc466311 100644 --- a/src/spdx/jsonschema/checksum_converter.py +++ b/src/spdx/jsonschema/checksum_converter.py @@ -18,15 +18,15 @@ class ChecksumConverter(TypedConverter[Checksum]): - def get_data_model_type(self) -> Type[Checksum]: return Checksum def get_json_type(self) -> Type[JsonProperty]: return ChecksumProperty - def _get_property_value(self, checksum: Checksum, checksum_property: ChecksumProperty, - _document: Document = None) -> str: + def _get_property_value( + self, checksum: Checksum, checksum_property: ChecksumProperty, _document: Document = None + ) -> str: if checksum_property == ChecksumProperty.ALGORITHM: return algorithm_to_json_string(checksum.algorithm) elif checksum_property == ChecksumProperty.CHECKSUM_VALUE: diff --git a/src/spdx/jsonschema/converter.py b/src/spdx/jsonschema/converter.py index 1b47ae3a0..45444dc03 100644 --- a/src/spdx/jsonschema/converter.py +++ b/src/spdx/jsonschema/converter.py @@ -60,7 +60,8 @@ def convert(self, instance: T, document: Document = None) -> Dict: if not isinstance(instance, self.get_data_model_type()): raise TypeError( f"Converter of type {self.__class__} can only convert objects of type " - f"{self.get_data_model_type()}. Received {type(instance)} instead.") + f"{self.get_data_model_type()}. Received {type(instance)} instead." + ) if self.requires_full_document() and not document: raise ValueError(f"Converter of type {self.__class__} requires the full document") diff --git a/src/spdx/jsonschema/creation_info_converter.py b/src/spdx/jsonschema/creation_info_converter.py index ce3dcef7d..96ded13a0 100644 --- a/src/spdx/jsonschema/creation_info_converter.py +++ b/src/spdx/jsonschema/creation_info_converter.py @@ -25,8 +25,9 @@ def get_data_model_type(self) -> Type[CreationInfo]: def get_json_type(self) -> Type[JsonProperty]: return CreationInfoProperty - def _get_property_value(self, creation_info: CreationInfo, creation_info_property: CreationInfoProperty, - _document: Document = None) -> Any: + def _get_property_value( + self, creation_info: CreationInfo, creation_info_property: CreationInfoProperty, _document: Document = None + ) -> Any: if creation_info_property == CreationInfoProperty.CREATED: return datetime_to_iso_string(creation_info.created) elif creation_info_property == CreationInfoProperty.CREATORS: diff --git a/src/spdx/jsonschema/document_converter.py b/src/spdx/jsonschema/document_converter.py index 319482012..598dceb2d 100644 --- a/src/spdx/jsonschema/document_converter.py +++ b/src/spdx/jsonschema/document_converter.py @@ -63,15 +63,17 @@ def json_property_name(self, document_property: DocumentProperty) -> str: return "SPDXID" return super().json_property_name(document_property) - def _get_property_value(self, document: Document, document_property: DocumentProperty, - _document: Document = None) -> Any: + def _get_property_value( + self, document: Document, document_property: DocumentProperty, _document: Document = None + ) -> Any: if document_property == DocumentProperty.SPDX_ID: return document.creation_info.spdx_id elif document_property == DocumentProperty.ANNOTATIONS: # annotations referencing files, packages or snippets will be added to those elements directly element_ids = get_contained_spdx_element_ids(document) - document_annotations = filter(lambda annotation: annotation.spdx_id not in element_ids, - document.annotations) + document_annotations = filter( + lambda annotation: annotation.spdx_id not in element_ids, document.annotations + ) return [self.annotation_converter.convert(annotation) for annotation in document_annotations] or None elif document_property == DocumentProperty.COMMENT: return document.creation_info.document_comment @@ -80,11 +82,15 @@ def _get_property_value(self, document: Document, document_property: DocumentPro elif document_property == DocumentProperty.DATA_LICENSE: return document.creation_info.data_license elif document_property == DocumentProperty.EXTERNAL_DOCUMENT_REFS: - return [self.external_document_ref_converter.convert(external_document_ref) for - external_document_ref in document.creation_info.external_document_refs] or None + return [ + self.external_document_ref_converter.convert(external_document_ref) + for external_document_ref in document.creation_info.external_document_refs + ] or None elif document_property == DocumentProperty.HAS_EXTRACTED_LICENSING_INFOS: - return [self.extracted_licensing_info_converter.convert(licensing_info) for licensing_info in - document.extracted_licensing_info] or None + return [ + self.extracted_licensing_info_converter.convert(licensing_info) + for licensing_info in document.extracted_licensing_info + ] or None elif document_property == DocumentProperty.NAME: return document.creation_info.name elif document_property == DocumentProperty.SPDX_VERSION: @@ -92,12 +98,18 @@ def _get_property_value(self, document: Document, document_property: DocumentPro elif document_property == DocumentProperty.DOCUMENT_NAMESPACE: return document.creation_info.document_namespace elif document_property == DocumentProperty.DOCUMENT_DESCRIBES: - describes_ids = [relationship.related_spdx_element_id for relationship in - filter_by_type_and_origin(document.relationships, RelationshipType.DESCRIBES, - document.creation_info.spdx_id)] - described_by_ids = [relationship.spdx_element_id for relationship in - filter_by_type_and_target(document.relationships, RelationshipType.DESCRIBED_BY, - document.creation_info.spdx_id)] + describes_ids = [ + relationship.related_spdx_element_id + for relationship in filter_by_type_and_origin( + document.relationships, RelationshipType.DESCRIBES, document.creation_info.spdx_id + ) + ] + described_by_ids = [ + relationship.spdx_element_id + for relationship in filter_by_type_and_target( + document.relationships, RelationshipType.DESCRIBED_BY, document.creation_info.spdx_id + ) + ] return describes_ids + described_by_ids or None elif document_property == DocumentProperty.PACKAGES: return [self.package_converter.convert(package, document) for package in document.packages] or None @@ -106,16 +118,22 @@ def _get_property_value(self, document: Document, document_property: DocumentPro elif document_property == DocumentProperty.SNIPPETS: return [self.snippet_converter.convert(snippet, document) for snippet in document.snippets] or None elif document_property == DocumentProperty.RELATIONSHIPS: - already_covered_relationships = filter_by_type_and_origin(document.relationships, - RelationshipType.DESCRIBES, - document.creation_info.spdx_id) + already_covered_relationships = filter_by_type_and_origin( + document.relationships, RelationshipType.DESCRIBES, document.creation_info.spdx_id + ) already_covered_relationships.extend( - filter_by_type_and_target(document.relationships, RelationshipType.DESCRIBED_BY, - document.creation_info.spdx_id)) + filter_by_type_and_target( + document.relationships, RelationshipType.DESCRIBED_BY, document.creation_info.spdx_id + ) + ) for package in document.packages: already_covered_relationships.extend(find_package_contains_file_relationships(document, package)) already_covered_relationships.extend(find_file_contained_by_package_relationships(document, package)) - relationships_to_ignore = [relationship for relationship in already_covered_relationships if - relationship.comment is None] - return [self.relationship_converter.convert(relationship) for relationship in document.relationships if - relationship not in relationships_to_ignore] or None + relationships_to_ignore = [ + relationship for relationship in already_covered_relationships if relationship.comment is None + ] + return [ + self.relationship_converter.convert(relationship) + for relationship in document.relationships + if relationship not in relationships_to_ignore + ] or None diff --git a/src/spdx/jsonschema/external_document_ref_converter.py b/src/spdx/jsonschema/external_document_ref_converter.py index eb7c0f5bc..03dccf795 100644 --- a/src/spdx/jsonschema/external_document_ref_converter.py +++ b/src/spdx/jsonschema/external_document_ref_converter.py @@ -24,9 +24,12 @@ class ExternalDocumentRefConverter(TypedConverter[ExternalDocumentRef]): def __init__(self): self.checksum_converter = ChecksumConverter() - def _get_property_value(self, external_document_ref: ExternalDocumentRef, - external_document_ref_property: ExternalDocumentRefProperty, - _document: Document = None) -> Any: + def _get_property_value( + self, + external_document_ref: ExternalDocumentRef, + external_document_ref_property: ExternalDocumentRefProperty, + _document: Document = None, + ) -> Any: if external_document_ref_property == ExternalDocumentRefProperty.EXTERNAL_DOCUMENT_ID: return external_document_ref.document_ref_id elif external_document_ref_property == ExternalDocumentRefProperty.SPDX_DOCUMENT: diff --git a/src/spdx/jsonschema/external_package_ref_converter.py b/src/spdx/jsonschema/external_package_ref_converter.py index f67037bdd..5dbbb1e45 100644 --- a/src/spdx/jsonschema/external_package_ref_converter.py +++ b/src/spdx/jsonschema/external_package_ref_converter.py @@ -18,8 +18,12 @@ class ExternalPackageRefConverter(TypedConverter[ExternalPackageRef]): - def _get_property_value(self, external_ref: ExternalPackageRef, external_ref_property: ExternalPackageRefProperty, - document: Document = None) -> Any: + def _get_property_value( + self, + external_ref: ExternalPackageRef, + external_ref_property: ExternalPackageRefProperty, + document: Document = None, + ) -> Any: if external_ref_property == ExternalPackageRefProperty.COMMENT: return external_ref.comment elif external_ref_property == ExternalPackageRefProperty.REFERENCE_CATEGORY: diff --git a/src/spdx/jsonschema/extracted_licensing_info_converter.py b/src/spdx/jsonschema/extracted_licensing_info_converter.py index ffd81e410..9d7ea23c5 100644 --- a/src/spdx/jsonschema/extracted_licensing_info_converter.py +++ b/src/spdx/jsonschema/extracted_licensing_info_converter.py @@ -19,9 +19,12 @@ class ExtractedLicensingInfoConverter(TypedConverter[ExtractedLicensingInfo]): - def _get_property_value(self, extracted_licensing_info: ExtractedLicensingInfo, - extracted_licensing_info_property: ExtractedLicensingInfoProperty, - document: Document = None) -> Any: + def _get_property_value( + self, + extracted_licensing_info: ExtractedLicensingInfo, + extracted_licensing_info_property: ExtractedLicensingInfoProperty, + document: Document = None, + ) -> Any: if extracted_licensing_info_property == ExtractedLicensingInfoProperty.COMMENT: return extracted_licensing_info.comment elif extracted_licensing_info_property == ExtractedLicensingInfoProperty.EXTRACTED_TEXT: diff --git a/src/spdx/jsonschema/json_property.py b/src/spdx/jsonschema/json_property.py index 0f65a77f2..fa0114bac 100644 --- a/src/spdx/jsonschema/json_property.py +++ b/src/spdx/jsonschema/json_property.py @@ -17,4 +17,5 @@ class JsonProperty(Enum): type that can be used in type hints. In general, all the child enums list the properties of the corresponding objects from the json schema. """ + pass diff --git a/src/spdx/jsonschema/package_converter.py b/src/spdx/jsonschema/package_converter.py index a4614f57f..da70b9720 100644 --- a/src/spdx/jsonschema/package_converter.py +++ b/src/spdx/jsonschema/package_converter.py @@ -45,14 +45,18 @@ def json_property_name(self, package_property: PackageProperty) -> str: return "SPDXID" return super().json_property_name(package_property) - def _get_property_value(self, package: Package, package_property: PackageProperty, - document: Document = None) -> Any: + def _get_property_value( + self, package: Package, package_property: PackageProperty, document: Document = None + ) -> Any: if package_property == PackageProperty.SPDX_ID: return package.spdx_id elif package_property == PackageProperty.ANNOTATIONS: - package_annotations = filter(lambda annotation: annotation.spdx_id == package.spdx_id, document.annotations) - return [self.annotation_converter.convert(annotation, document) for annotation in - package_annotations] or None + package_annotations = filter( + lambda annotation: annotation.spdx_id == package.spdx_id, document.annotations + ) + return [ + self.annotation_converter.convert(annotation, document) for annotation in package_annotations + ] or None elif package_property == PackageProperty.ATTRIBUTION_TEXTS: return package.attribution_texts or None elif package_property == PackageProperty.BUILT_DATE: @@ -68,15 +72,21 @@ def _get_property_value(self, package: Package, package_property: PackagePropert elif package_property == PackageProperty.DOWNLOAD_LOCATION: return str(package.download_location) elif package_property == PackageProperty.EXTERNAL_REFS: - return [self.external_package_ref_converter.convert(external_ref) for external_ref in - package.external_references] or None + return [ + self.external_package_ref_converter.convert(external_ref) + for external_ref in package.external_references + ] or None elif package_property == PackageProperty.FILES_ANALYZED: return package.files_analyzed elif package_property == PackageProperty.HAS_FILES: - package_contains_file_ids = [relationship.related_spdx_element_id for relationship in - find_package_contains_file_relationships(document, package)] - file_contained_in_package_ids = [relationship.spdx_element_id for relationship in - find_file_contained_by_package_relationships(document, package)] + package_contains_file_ids = [ + relationship.related_spdx_element_id + for relationship in find_package_contains_file_relationships(document, package) + ] + file_contained_in_package_ids = [ + relationship.spdx_element_id + for relationship in find_file_contained_by_package_relationships(document, package) + ] return package_contains_file_ids + file_contained_in_package_ids or None elif package_property == PackageProperty.HOMEPAGE: return apply_if_present(str, package.homepage) diff --git a/src/spdx/jsonschema/package_verification_code_converter.py b/src/spdx/jsonschema/package_verification_code_converter.py index d2f7d2352..df72b9dcd 100644 --- a/src/spdx/jsonschema/package_verification_code_converter.py +++ b/src/spdx/jsonschema/package_verification_code_converter.py @@ -18,9 +18,12 @@ class PackageVerificationCodeConverter(TypedConverter[PackageVerificationCode]): - def _get_property_value(self, verification_code: PackageVerificationCode, - verification_code_property: PackageVerificationCodeProperty, - document: Document = None) -> Any: + def _get_property_value( + self, + verification_code: PackageVerificationCode, + verification_code_property: PackageVerificationCodeProperty, + document: Document = None, + ) -> Any: if verification_code_property == PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES: return verification_code.excluded_files or None elif verification_code_property == PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_VALUE: diff --git a/src/spdx/jsonschema/relationship_converter.py b/src/spdx/jsonschema/relationship_converter.py index a3344a6a9..b2482f640 100644 --- a/src/spdx/jsonschema/relationship_converter.py +++ b/src/spdx/jsonschema/relationship_converter.py @@ -18,8 +18,9 @@ class RelationshipConverter(TypedConverter[Relationship]): - def _get_property_value(self, relationship: Relationship, relationship_property: RelationshipProperty, - document: Document = None) -> Any: + def _get_property_value( + self, relationship: Relationship, relationship_property: RelationshipProperty, document: Document = None + ) -> Any: if relationship_property == RelationshipProperty.SPDX_ELEMENT_ID: return relationship.spdx_element_id elif relationship_property == RelationshipProperty.COMMENT: diff --git a/src/spdx/jsonschema/snippet_converter.py b/src/spdx/jsonschema/snippet_converter.py index ca1b7c4d9..d26e20ad5 100644 --- a/src/spdx/jsonschema/snippet_converter.py +++ b/src/spdx/jsonschema/snippet_converter.py @@ -30,12 +30,15 @@ def json_property_name(self, snippet_property: SnippetProperty) -> str: return "SPDXID" return super().json_property_name(snippet_property) - def _get_property_value(self, snippet: Snippet, snippet_property: SnippetProperty, - document: Document = None) -> Any: + def _get_property_value( + self, snippet: Snippet, snippet_property: SnippetProperty, document: Document = None + ) -> Any: if snippet_property == SnippetProperty.SPDX_ID: return snippet.spdx_id elif snippet_property == SnippetProperty.ANNOTATIONS: - snippet_annotations = filter(lambda annotation: annotation.spdx_id == snippet.spdx_id, document.annotations) + snippet_annotations = filter( + lambda annotation: annotation.spdx_id == snippet.spdx_id, document.annotations + ) return [self.annotation_converter.convert(annotation) for annotation in snippet_annotations] or None elif snippet_property == SnippetProperty.ATTRIBUTION_TEXTS: return snippet.attribution_texts or None @@ -78,8 +81,10 @@ def convert_byte_range_to_dict(byte_range: Tuple[int, int], file_id: str) -> Dic def _convert_range_to_dict(int_range: Tuple[int, int], file_id: str, pointer_property: str) -> Dict: - return {"startPointer": _pointer(file_id, int_range[0], pointer_property), - "endPointer": _pointer(file_id, int_range[1], pointer_property)} + return { + "startPointer": _pointer(file_id, int_range[0], pointer_property), + "endPointer": _pointer(file_id, int_range[1], pointer_property), + } def _pointer(reference: str, target: int, pointer_property: str) -> Dict: diff --git a/src/spdx/model/annotation.py b/src/spdx/model/annotation.py index e12cf1d88..2cfe0b212 100644 --- a/src/spdx/model/annotation.py +++ b/src/spdx/model/annotation.py @@ -29,6 +29,12 @@ class Annotation: annotation_date: datetime annotation_comment: str - def __init__(self, spdx_id: str, annotation_type: AnnotationType, annotator: Actor, annotation_date: datetime, - annotation_comment: str): + def __init__( + self, + spdx_id: str, + annotation_type: AnnotationType, + annotator: Actor, + annotation_date: datetime, + annotation_comment: str, + ): check_types_and_set_values(self, locals()) diff --git a/src/spdx/model/document.py b/src/spdx/model/document.py index 063b9906e..d727955ec 100644 --- a/src/spdx/model/document.py +++ b/src/spdx/model/document.py @@ -39,10 +39,20 @@ class CreationInfo: license_list_version: Optional[Version] = None document_comment: Optional[str] = None - def __init__(self, spdx_version: str, spdx_id: str, name: str, document_namespace: str, creators: List[Actor], - created: datetime, creator_comment: Optional[str] = None, data_license: str = "CC0-1.0", - external_document_refs: List[ExternalDocumentRef] = None, - license_list_version: Optional[Version] = None, document_comment: Optional[str] = None): + def __init__( + self, + spdx_version: str, + spdx_id: str, + name: str, + document_namespace: str, + creators: List[Actor], + created: datetime, + creator_comment: Optional[str] = None, + data_license: str = "CC0-1.0", + external_document_refs: List[ExternalDocumentRef] = None, + license_list_version: Optional[Version] = None, + document_comment: Optional[str] = None, + ): external_document_refs = [] if external_document_refs is None else external_document_refs check_types_and_set_values(self, locals()) @@ -58,10 +68,16 @@ class Document: relationships: List[Relationship] = field(default_factory=list) extracted_licensing_info: List[ExtractedLicensingInfo] = field(default_factory=list) - def __init__(self, creation_info: CreationInfo, packages: List[Package] = None, files: List[File] = None, - snippets: List[Snippet] = None, annotations: List[Annotation] = None, - relationships: List[Relationship] = None, - extracted_licensing_info: List[ExtractedLicensingInfo] = None): + def __init__( + self, + creation_info: CreationInfo, + packages: List[Package] = None, + files: List[File] = None, + snippets: List[Snippet] = None, + annotations: List[Annotation] = None, + relationships: List[Relationship] = None, + extracted_licensing_info: List[ExtractedLicensingInfo] = None, + ): packages = [] if packages is None else packages files = [] if files is None else files snippets = [] if snippets is None else snippets diff --git a/src/spdx/model/extracted_licensing_info.py b/src/spdx/model/extracted_licensing_info.py index f0954d45e..4d05a079f 100644 --- a/src/spdx/model/extracted_licensing_info.py +++ b/src/spdx/model/extracted_licensing_info.py @@ -24,8 +24,13 @@ class ExtractedLicensingInfo: cross_references: List[str] = field(default_factory=list) comment: Optional[str] = None - def __init__(self, license_id: Optional[str] = None, extracted_text: Optional[str] = None, - license_name: Optional[Union[str, SpdxNoAssertion]] = None, cross_references: List[str] = None, - comment: Optional[str] = None): + def __init__( + self, + license_id: Optional[str] = None, + extracted_text: Optional[str] = None, + license_name: Optional[Union[str, SpdxNoAssertion]] = None, + cross_references: List[str] = None, + comment: Optional[str] = None, + ): cross_references = [] if cross_references is None else cross_references check_types_and_set_values(self, locals()) diff --git a/src/spdx/model/file.py b/src/spdx/model/file.py index fd3c66159..6205ff998 100644 --- a/src/spdx/model/file.py +++ b/src/spdx/model/file.py @@ -55,13 +55,21 @@ class File: # - artifact of (3 properties): replace by an external package reference and a GENERATED_FROM relationship # between the file and this package - def __init__(self, name: str, spdx_id: str, checksums: List[Checksum], file_types: List[FileType] = None, - license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, - license_info_in_file: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, - license_comment: Optional[str] = None, - copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None, - comment: str = None, notice: Optional[str] = None, - contributors: List[str] = None, attribution_texts: List[str] = None): + def __init__( + self, + name: str, + spdx_id: str, + checksums: List[Checksum], + file_types: List[FileType] = None, + license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_info_in_file: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_comment: Optional[str] = None, + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None, + comment: str = None, + notice: Optional[str] = None, + contributors: List[str] = None, + attribution_texts: List[str] = None, + ): file_types = [] if file_types is None else file_types license_info_in_file = [] if license_info_in_file is None else license_info_in_file contributors = [] if contributors is None else contributors diff --git a/src/spdx/model/package.py b/src/spdx/model/package.py index 7e64574b7..2aa8731b4 100644 --- a/src/spdx/model/package.py +++ b/src/spdx/model/package.py @@ -59,7 +59,7 @@ class ExternalPackageRefCategory(Enum): ExternalPackageRefCategory.SECURITY: ["cpe22Type", "cpe23Type", "advisory", "fix", "url", "swid"], ExternalPackageRefCategory.PACKAGE_MANAGER: ["maven-central", "npm", "nuget", "bower", "purl"], ExternalPackageRefCategory.PERSISTENT_ID: ["swh", "gitoid"], - ExternalPackageRefCategory.OTHER: [] + ExternalPackageRefCategory.OTHER: [], } @@ -73,8 +73,9 @@ class ExternalPackageRef: locator: str comment: Optional[str] = None - def __init__(self, category: ExternalPackageRefCategory, reference_type: str, locator: str, - comment: Optional[str] = None): + def __init__( + self, category: ExternalPackageRefCategory, reference_type: str, locator: str, comment: Optional[str] = None + ): check_types_and_set_values(self, locals()) @@ -107,22 +108,35 @@ class Package: built_date: Optional[datetime] = None valid_until_date: Optional[datetime] = None - def __init__(self, spdx_id: str, name: str, download_location: Union[str, SpdxNoAssertion, SpdxNone], - version: Optional[str] = None, file_name: Optional[str] = None, - supplier: Optional[Union[Actor, SpdxNoAssertion]] = None, - originator: Optional[Union[Actor, SpdxNoAssertion]] = None, - files_analyzed: bool = True, verification_code: Optional[PackageVerificationCode] = None, - checksums: List[Checksum] = None, homepage: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None, - source_info: Optional[str] = None, - license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, - license_info_from_files: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, - license_declared: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, - license_comment: Optional[str] = None, - copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - external_references: List[ExternalPackageRef] = None, attribution_texts: List[str] = None, - primary_package_purpose: Optional[PackagePurpose] = None, release_date: Optional[datetime] = None, - built_date: Optional[datetime] = None, valid_until_date: Optional[datetime] = None): + def __init__( + self, + spdx_id: str, + name: str, + download_location: Union[str, SpdxNoAssertion, SpdxNone], + version: Optional[str] = None, + file_name: Optional[str] = None, + supplier: Optional[Union[Actor, SpdxNoAssertion]] = None, + originator: Optional[Union[Actor, SpdxNoAssertion]] = None, + files_analyzed: bool = True, + verification_code: Optional[PackageVerificationCode] = None, + checksums: List[Checksum] = None, + homepage: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None, + source_info: Optional[str] = None, + license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_info_from_files: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_declared: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_comment: Optional[str] = None, + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + external_references: List[ExternalPackageRef] = None, + attribution_texts: List[str] = None, + primary_package_purpose: Optional[PackagePurpose] = None, + release_date: Optional[datetime] = None, + built_date: Optional[datetime] = None, + valid_until_date: Optional[datetime] = None, + ): checksums = [] if checksums is None else checksums license_info_from_files = [] if license_info_from_files is None else license_info_from_files external_references = [] if external_references is None else external_references diff --git a/src/spdx/model/relationship.py b/src/spdx/model/relationship.py index 22ad042a5..19ecc2d8b 100644 --- a/src/spdx/model/relationship.py +++ b/src/spdx/model/relationship.py @@ -72,6 +72,11 @@ class Relationship: related_spdx_element_id: Union[str, SpdxNone, SpdxNoAssertion] comment: Optional[str] = None - def __init__(self, spdx_element_id: str, relationship_type: RelationshipType, - related_spdx_element_id: Union[str, SpdxNone, SpdxNoAssertion], comment: Optional[str] = None): + def __init__( + self, + spdx_element_id: str, + relationship_type: RelationshipType, + related_spdx_element_id: Union[str, SpdxNone, SpdxNoAssertion], + comment: Optional[str] = None, + ): check_types_and_set_values(self, locals()) diff --git a/src/spdx/model/relationship_filters.py b/src/spdx/model/relationship_filters.py index f981578e3..394a89479 100644 --- a/src/spdx/model/relationship_filters.py +++ b/src/spdx/model/relationship_filters.py @@ -17,27 +17,43 @@ def find_package_contains_file_relationships(document: Document, package: Package) -> List[Relationship]: file_ids_in_document = [file.spdx_id for file in document.files] - package_contains_relationships = filter_by_type_and_origin(document.relationships, RelationshipType.CONTAINS, - package.spdx_id) - return [relationship for relationship in package_contains_relationships if - relationship.related_spdx_element_id in file_ids_in_document] + package_contains_relationships = filter_by_type_and_origin( + document.relationships, RelationshipType.CONTAINS, package.spdx_id + ) + return [ + relationship + for relationship in package_contains_relationships + if relationship.related_spdx_element_id in file_ids_in_document + ] def find_file_contained_by_package_relationships(document: Document, package: Package) -> List[Relationship]: file_ids_in_document = [file.spdx_id for file in document.files] - contained_by_package_relationships = filter_by_type_and_target(document.relationships, - RelationshipType.CONTAINED_BY, package.spdx_id) - return [relationship for relationship in contained_by_package_relationships if - relationship.spdx_element_id in file_ids_in_document] - - -def filter_by_type_and_target(relationships: List[Relationship], relationship_type: RelationshipType, - target_id: str) -> List[Relationship]: - return [relationship for relationship in relationships if - relationship.relationship_type == relationship_type and relationship.related_spdx_element_id == target_id] - - -def filter_by_type_and_origin(relationships: List[Relationship], relationship_type: RelationshipType, - origin_id: str) -> List[Relationship]: - return [relationship for relationship in relationships if - relationship.relationship_type == relationship_type and relationship.spdx_element_id == origin_id] + contained_by_package_relationships = filter_by_type_and_target( + document.relationships, RelationshipType.CONTAINED_BY, package.spdx_id + ) + return [ + relationship + for relationship in contained_by_package_relationships + if relationship.spdx_element_id in file_ids_in_document + ] + + +def filter_by_type_and_target( + relationships: List[Relationship], relationship_type: RelationshipType, target_id: str +) -> List[Relationship]: + return [ + relationship + for relationship in relationships + if relationship.relationship_type == relationship_type and relationship.related_spdx_element_id == target_id + ] + + +def filter_by_type_and_origin( + relationships: List[Relationship], relationship_type: RelationshipType, origin_id: str +) -> List[Relationship]: + return [ + relationship + for relationship in relationships + if relationship.relationship_type == relationship_type and relationship.spdx_element_id == origin_id + ] diff --git a/src/spdx/model/snippet.py b/src/spdx/model/snippet.py index c34ef7652..2b12a7fc9 100644 --- a/src/spdx/model/snippet.py +++ b/src/spdx/model/snippet.py @@ -33,12 +33,20 @@ class Snippet: name: Optional[str] = None attribution_texts: List[str] = field(default_factory=list) - def __init__(self, spdx_id: str, file_spdx_id: str, byte_range: Tuple[int, int], - line_range: Optional[Tuple[int, int]] = None, - license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, - license_info_in_snippet: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, - license_comment: Optional[str] = None, copyright_text: Optional[str] = None, - comment: Optional[str] = None, name: Optional[str] = None, attribution_texts: List[str] = None): + def __init__( + self, + spdx_id: str, + file_spdx_id: str, + byte_range: Tuple[int, int], + line_range: Optional[Tuple[int, int]] = None, + license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_info_in_snippet: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, + license_comment: Optional[str] = None, + copyright_text: Optional[str] = None, + comment: Optional[str] = None, + name: Optional[str] = None, + attribution_texts: List[str] = None, + ): attribution_texts = [] if attribution_texts is None else attribution_texts license_info_in_snippet = [] if license_info_in_snippet is None else license_info_in_snippet check_types_and_set_values(self, locals()) diff --git a/src/spdx/parser/actor_parser.py b/src/spdx/parser/actor_parser.py index de8de6246..3ac5ddb9e 100644 --- a/src/spdx/parser/actor_parser.py +++ b/src/spdx/parser/actor_parser.py @@ -17,7 +17,6 @@ class ActorParser: - @staticmethod def parse_actor(actor: str) -> Actor: tool_re: Pattern = re.compile(r"^Tool:\s*(.+)", re.UNICODE) @@ -38,14 +37,17 @@ def parse_actor(actor: str) -> Actor: if not name: raise SPDXParsingError([f"No name for Person provided: {actor}."]) email: Optional[str] = ActorParser.get_email_or_none(person_match) - creator = construct_or_raise_parsing_error(Actor, dict(actor_type=ActorType.PERSON, name=name, email=email)) + creator = construct_or_raise_parsing_error( + Actor, dict(actor_type=ActorType.PERSON, name=name, email=email) + ) elif org_match: name: str = org_match.group(1).strip() if not name: raise SPDXParsingError([f"No name for Organization provided: {actor}."]) email: Optional[str] = ActorParser.get_email_or_none(org_match) - creator = construct_or_raise_parsing_error(Actor, - dict(actor_type=ActorType.ORGANIZATION, name=name, email=email)) + creator = construct_or_raise_parsing_error( + Actor, dict(actor_type=ActorType.ORGANIZATION, name=name, email=email) + ) else: raise SPDXParsingError([f"Actor {actor} doesn't match any of person, organization or tool."]) diff --git a/src/spdx/parser/jsonlikedict/annotation_parser.py b/src/spdx/parser/jsonlikedict/annotation_parser.py index 43bbe634e..72338179a 100644 --- a/src/spdx/parser/jsonlikedict/annotation_parser.py +++ b/src/spdx/parser/jsonlikedict/annotation_parser.py @@ -35,7 +35,8 @@ def parse_all_annotations(self, input_doc_dict: Dict) -> List[Annotation]: reviews: List[Dict] = input_doc_dict.get("revieweds", []) for review in reviews: annotations = append_parsed_field_or_log_error( - self.logger, annotations, review, lambda x: self.parse_review(x, spdx_id=input_doc_dict.get("SPDXID"))) + self.logger, annotations, review, lambda x: self.parse_review(x, spdx_id=input_doc_dict.get("SPDXID")) + ) packages: List[Dict] = input_doc_dict.get("packages", []) self.parse_annotations_from_object(annotations, packages) files: List[Dict] = input_doc_dict.get("files", []) @@ -50,31 +51,44 @@ def parse_annotations_from_object(self, annotations: List[Annotation], element_l for element in element_list: element_spdx_id: Optional[str] = element.get("SPDXID") element_annotations: List[Dict] = element.get("annotations", []) - annotations.extend(parse_field_or_log_error(self.logger, element_annotations, - - lambda y: self.parse_annotation(y, spdx_id=element_spdx_id), - [], True)) + annotations.extend( + parse_field_or_log_error( + self.logger, + element_annotations, + lambda y: self.parse_annotation(y, spdx_id=element_spdx_id), + [], + True, + ) + ) def parse_annotation(self, annotation_dict: Dict, spdx_id: Optional[str] = None) -> Annotation: logger = Logger() spdx_id: Optional[str] = annotation_dict.get("SPDXID") or spdx_id - annotation_type: Optional[AnnotationType] = parse_field_or_log_error(logger, - annotation_dict.get("annotationType"), - self.parse_annotation_type) + annotation_type: Optional[AnnotationType] = parse_field_or_log_error( + logger, annotation_dict.get("annotationType"), self.parse_annotation_type + ) - annotator: Optional[Actor] = parse_field_or_log_error(logger, annotation_dict.get("annotator"), - self.actor_parser.parse_actor) + annotator: Optional[Actor] = parse_field_or_log_error( + logger, annotation_dict.get("annotator"), self.actor_parser.parse_actor + ) - annotation_date: Optional[datetime] = parse_field_or_log_error(logger, annotation_dict.get("annotationDate"), - datetime_from_str) + annotation_date: Optional[datetime] = parse_field_or_log_error( + logger, annotation_dict.get("annotationDate"), datetime_from_str + ) annotation_comment: Optional[str] = annotation_dict.get("comment") raise_parsing_error_if_logger_has_messages(logger, "Annotation") - annotation_dict = construct_or_raise_parsing_error(Annotation, - dict(spdx_id=spdx_id, annotation_type=annotation_type, - annotator=annotator, annotation_date=annotation_date, - annotation_comment=annotation_comment)) + annotation_dict = construct_or_raise_parsing_error( + Annotation, + dict( + spdx_id=spdx_id, + annotation_type=annotation_type, + annotator=annotator, + annotation_date=annotation_date, + annotation_comment=annotation_comment, + ), + ) return annotation_dict @@ -87,18 +101,26 @@ def parse_annotation_type(annotation_type: str) -> AnnotationType: def parse_review(self, review_dict: Dict, spdx_id: str) -> Annotation: logger = Logger() - annotator: Optional[Actor] = parse_field_or_log_error(logger, review_dict.get("reviewer"), - self.actor_parser.parse_actor) + annotator: Optional[Actor] = parse_field_or_log_error( + logger, review_dict.get("reviewer"), self.actor_parser.parse_actor + ) - annotation_date: Optional[datetime] = parse_field_or_log_error(logger, review_dict.get("reviewDate"), - datetime_from_str) + annotation_date: Optional[datetime] = parse_field_or_log_error( + logger, review_dict.get("reviewDate"), datetime_from_str + ) annotation_type = AnnotationType.REVIEW comment: Optional[str] = review_dict.get("comment") raise_parsing_error_if_logger_has_messages(logger, "Annotation from revieweds") - annotation = construct_or_raise_parsing_error(Annotation, - dict(spdx_id=spdx_id, annotation_type=annotation_type, - annotator=annotator, annotation_date=annotation_date, - annotation_comment=comment)) + annotation = construct_or_raise_parsing_error( + Annotation, + dict( + spdx_id=spdx_id, + annotation_type=annotation_type, + annotator=annotator, + annotation_date=annotation_date, + annotation_comment=comment, + ), + ) return annotation diff --git a/src/spdx/parser/jsonlikedict/creation_info_parser.py b/src/spdx/parser/jsonlikedict/creation_info_parser.py index ddd86fce7..835aa6702 100644 --- a/src/spdx/parser/jsonlikedict/creation_info_parser.py +++ b/src/spdx/parser/jsonlikedict/creation_info_parser.py @@ -52,32 +52,42 @@ def parse_creation_info(self, doc_dict: Dict) -> CreationInfo: logger.append("CreationInfo does not exist.") raise SPDXParsingError([f"Error while parsing document {name}: {logger.get_messages()}"]) - creators: List[Actor] = parse_field_or_log_error(logger, creation_info_dict.get("creators"), - self.parse_creators) + creators: List[Actor] = parse_field_or_log_error( + logger, creation_info_dict.get("creators"), self.parse_creators + ) - created: Optional[datetime] = parse_field_or_log_error(logger, creation_info_dict.get("created"), - datetime_from_str) + created: Optional[datetime] = parse_field_or_log_error( + logger, creation_info_dict.get("created"), datetime_from_str + ) creator_comment: Optional[str] = creation_info_dict.get("comment") data_license: Optional[str] = doc_dict.get("dataLicense") - external_document_refs: List[ExternalDocumentRef] = parse_field_or_log_error(logger, doc_dict.get( - "externalDocumentRefs"), self.parse_external_document_refs) - license_list_version: Optional[Version] = parse_field_or_log_error(logger, - creation_info_dict.get("licenseListVersion"), - self.parse_version) + external_document_refs: List[ExternalDocumentRef] = parse_field_or_log_error( + logger, doc_dict.get("externalDocumentRefs"), self.parse_external_document_refs + ) + license_list_version: Optional[Version] = parse_field_or_log_error( + logger, creation_info_dict.get("licenseListVersion"), self.parse_version + ) document_comment: Optional[str] = doc_dict.get("comment") raise_parsing_error_if_logger_has_messages(logger, "Document") - creation_info = construct_or_raise_parsing_error(CreationInfo, - dict(spdx_version=spdx_version, spdx_id=spdx_id, name=name, - document_namespace=document_namespace, - creators=creators, created=created, - license_list_version=license_list_version, - document_comment=document_comment, - creator_comment=creator_comment, - data_license=data_license, - external_document_refs=external_document_refs)) + creation_info = construct_or_raise_parsing_error( + CreationInfo, + dict( + spdx_version=spdx_version, + spdx_id=spdx_id, + name=name, + document_namespace=document_namespace, + creators=creators, + created=created, + license_list_version=license_list_version, + document_comment=document_comment, + creator_comment=creator_comment, + data_license=data_license, + external_document_refs=external_document_refs, + ), + ) return creation_info @@ -85,7 +95,9 @@ def parse_creators(self, creators_list_from_dict: List[str]) -> List[Actor]: logger = Logger() creators = [] for creator_str in creators_list_from_dict: - creators = append_parsed_field_or_log_error(logger, creators, creator_str, lambda x: parse_field_or_no_assertion(x, self.actor_parser.parse_actor)) + creators = append_parsed_field_or_log_error( + logger, creators, creator_str, lambda x: parse_field_or_no_assertion(x, self.actor_parser.parse_actor) + ) raise_parsing_error_if_logger_has_messages(logger) return creators @@ -101,8 +113,9 @@ def parse_external_document_refs(self, external_document_ref_dicts: List[Dict]) logger = Logger() external_document_refs = [] for external_document_ref_dict in external_document_ref_dicts: - external_document_ref: ExternalDocumentRef = parse_field_or_log_error(logger, external_document_ref_dict, - self.parse_external_document_ref) + external_document_ref: ExternalDocumentRef = parse_field_or_log_error( + logger, external_document_ref_dict, self.parse_external_document_ref + ) external_document_refs.append(external_document_ref) @@ -111,16 +124,16 @@ def parse_external_document_refs(self, external_document_ref_dicts: List[Dict]) def parse_external_document_ref(self, external_document_ref_dict: Dict) -> ExternalDocumentRef: logger = Logger() - checksum: Optional[Checksum] = parse_field_or_log_error(logger, external_document_ref_dict.get("checksum"), - self.checksum_parser.parse_checksum) + checksum: Optional[Checksum] = parse_field_or_log_error( + logger, external_document_ref_dict.get("checksum"), self.checksum_parser.parse_checksum + ) external_document_id: Optional[str] = external_document_ref_dict.get("externalDocumentId") document_uri: Optional[str] = external_document_ref_dict.get("spdxDocument") raise_parsing_error_if_logger_has_messages(logger, "ExternalDocumentRef") - external_document_ref: ExternalDocumentRef = construct_or_raise_parsing_error(ExternalDocumentRef, - dict( - document_ref_id=external_document_id, - checksum=checksum, - document_uri=document_uri)) + external_document_ref: ExternalDocumentRef = construct_or_raise_parsing_error( + ExternalDocumentRef, + dict(document_ref_id=external_document_id, checksum=checksum, document_uri=document_uri), + ) return external_document_ref diff --git a/src/spdx/parser/jsonlikedict/dict_parsing_functions.py b/src/spdx/parser/jsonlikedict/dict_parsing_functions.py index 3986cbfc0..4e791f6b4 100644 --- a/src/spdx/parser/jsonlikedict/dict_parsing_functions.py +++ b/src/spdx/parser/jsonlikedict/dict_parsing_functions.py @@ -23,8 +23,13 @@ def json_str_to_enum_name(json_str: str) -> str: return json_str.replace("-", "_").upper() -def parse_field_or_log_error(logger: Logger, field: Any, parsing_method: Callable = lambda x: x, default: Any = None, - field_is_list: bool = False) -> Any: +def parse_field_or_log_error( + logger: Logger, + field: Any, + parsing_method: Callable = lambda x: x, + default: Any = None, + field_is_list: bool = False, +) -> Any: if not field: return default try: @@ -39,8 +44,9 @@ def parse_field_or_log_error(logger: Logger, field: Any, parsing_method: Callabl return default -def append_parsed_field_or_log_error(logger: Logger, list_to_append_to: List[Any], field: Any, - method_to_parse: Callable) -> List[Any]: +def append_parsed_field_or_log_error( + logger: Logger, list_to_append_to: List[Any], field: Any, method_to_parse: Callable +) -> List[Any]: try: parsed_element = method_to_parse(field) list_to_append_to.append(parsed_element) @@ -72,8 +78,9 @@ def parse_list_of_elements(list_of_elements: List[Dict], method_to_parse_element logger = Logger() parsed_elements = [] for element_dict in list_of_elements: - parsed_elements = append_parsed_field_or_log_error(logger, parsed_elements, element_dict, - method_to_parse_element) + parsed_elements = append_parsed_field_or_log_error( + logger, parsed_elements, element_dict, method_to_parse_element + ) raise_parsing_error_if_logger_has_messages(logger) return parsed_elements diff --git a/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py b/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py index 41c3cab65..65ec7495f 100644 --- a/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py +++ b/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py @@ -28,13 +28,18 @@ def parse_extracted_licensing_info(extracted_licensing_info_dict: Dict) -> Extra license_id: Optional[str] = extracted_licensing_info_dict.get("licenseId") extracted_text: Optional[str] = extracted_licensing_info_dict.get("extractedText") license_name: Optional[Union[str, SpdxNoAssertion]] = parse_field_or_no_assertion( - extracted_licensing_info_dict.get("name")) + extracted_licensing_info_dict.get("name") + ) cross_references: List[str] = extracted_licensing_info_dict.get("seeAlsos", []) comment: Optional[str] = extracted_licensing_info_dict.get("comment") - extracted_licensing_info = construct_or_raise_parsing_error(ExtractedLicensingInfo, - dict(license_id=license_id, - extracted_text=extracted_text, - comment=comment, - license_name=license_name, - cross_references=cross_references)) + extracted_licensing_info = construct_or_raise_parsing_error( + ExtractedLicensingInfo, + dict( + license_id=license_id, + extracted_text=extracted_text, + comment=comment, + license_name=license_name, + cross_references=cross_references, + ), + ) return extracted_licensing_info diff --git a/src/spdx/parser/jsonlikedict/file_parser.py b/src/spdx/parser/jsonlikedict/file_parser.py index f701c288b..501ba4b76 100644 --- a/src/spdx/parser/jsonlikedict/file_parser.py +++ b/src/spdx/parser/jsonlikedict/file_parser.py @@ -38,35 +38,50 @@ def parse_file(self, file_dict: Dict) -> Optional[File]: name: Optional[str] = file_dict.get("fileName") spdx_id: Optional[str] = file_dict.get("SPDXID") checksums_list: List[Dict] = file_dict.get("checksums") - checksums: List[Checksum] = parse_field_or_log_error(logger, checksums_list, - self.checksum_parser.parse_checksum, field_is_list=True) + checksums: List[Checksum] = parse_field_or_log_error( + logger, checksums_list, self.checksum_parser.parse_checksum, field_is_list=True + ) attribution_texts: List[str] = file_dict.get("attributionTexts", []) comment: Optional[str] = file_dict.get("comment") copyright_text: Optional[str] = file_dict.get("copyrightText") file_contributors: List[str] = file_dict.get("fileContributors", []) - file_types: List[FileType] = parse_field_or_log_error(logger, file_dict.get("fileTypes"), self.parse_file_types) + file_types: List[FileType] = parse_field_or_log_error( + logger, file_dict.get("fileTypes"), self.parse_file_types + ) license_comments: Optional[str] = file_dict.get("licenseComments") license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error( - logger, file_dict.get("licenseConcluded"), self.license_expression_parser.parse_license_expression) + logger, file_dict.get("licenseConcluded"), self.license_expression_parser.parse_license_expression + ) license_info_in_files: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error( - logger, file_dict.get("licenseInfoInFiles"), self.license_expression_parser.parse_license_expression, - field_is_list=True) + logger, + file_dict.get("licenseInfoInFiles"), + self.license_expression_parser.parse_license_expression, + field_is_list=True, + ) notice_text: Optional[str] = file_dict.get("noticeText") raise_parsing_error_if_logger_has_messages(logger, "File") - file = construct_or_raise_parsing_error(File, dict(name=name, spdx_id=spdx_id, checksums=checksums, - attribution_texts=attribution_texts, comment=comment, - copyright_text=copyright_text, file_types=file_types, - contributors=file_contributors, - license_comment=license_comments, - license_concluded=license_concluded, - license_info_in_file=license_info_in_files, - notice=notice_text) - ) + file = construct_or_raise_parsing_error( + File, + dict( + name=name, + spdx_id=spdx_id, + checksums=checksums, + attribution_texts=attribution_texts, + comment=comment, + copyright_text=copyright_text, + file_types=file_types, + contributors=file_contributors, + license_comment=license_comments, + license_concluded=license_concluded, + license_info_in_file=license_info_in_files, + notice=notice_text, + ), + ) return file @staticmethod diff --git a/src/spdx/parser/jsonlikedict/json_like_dict_parser.py b/src/spdx/parser/jsonlikedict/json_like_dict_parser.py index ae4d76965..148cd4dd2 100644 --- a/src/spdx/parser/jsonlikedict/json_like_dict_parser.py +++ b/src/spdx/parser/jsonlikedict/json_like_dict_parser.py @@ -45,23 +45,39 @@ def __init__(self): self.annotation_parser = AnnotationParser() def parse(self, json_like_dict: Dict) -> Document: - - fields_to_parse = [("creation_info", json_like_dict, self.creation_info_parser.parse_creation_info, False), - ("packages", json_like_dict.get("packages"), lambda x: parse_list_of_elements(x, - self.package_parser.parse_package, - self.package_parser.logger), True), - ("files", json_like_dict.get("files"), lambda x: parse_list_of_elements(x, - self.file_parser.parse_file, - self.file_parser.logger), True), - ("annotations", json_like_dict, self.annotation_parser.parse_all_annotations, True), - ("snippets", json_like_dict.get("snippets"), lambda x: parse_list_of_elements(x, - self.snippet_parser.parse_snippet, - self.snippet_parser.logger), True), - ("relationships", json_like_dict, self.relationship_parser.parse_all_relationships, True), - ("extracted_licensing_info", json_like_dict.get("hasExtractedLicensingInfos"), - lambda x: parse_list_of_elements(x, - self.extracted_licensing_info_parser.parse_extracted_licensing_info, - self.extracted_licensing_info_parser.logger), True)] + fields_to_parse = [ + ("creation_info", json_like_dict, self.creation_info_parser.parse_creation_info, False), + ( + "packages", + json_like_dict.get("packages"), + lambda x: parse_list_of_elements(x, self.package_parser.parse_package, self.package_parser.logger), + True, + ), + ( + "files", + json_like_dict.get("files"), + lambda x: parse_list_of_elements(x, self.file_parser.parse_file, self.file_parser.logger), + True, + ), + ("annotations", json_like_dict, self.annotation_parser.parse_all_annotations, True), + ( + "snippets", + json_like_dict.get("snippets"), + lambda x: parse_list_of_elements(x, self.snippet_parser.parse_snippet, self.snippet_parser.logger), + True, + ), + ("relationships", json_like_dict, self.relationship_parser.parse_all_relationships, True), + ( + "extracted_licensing_info", + json_like_dict.get("hasExtractedLicensingInfos"), + lambda x: parse_list_of_elements( + x, + self.extracted_licensing_info_parser.parse_extracted_licensing_info, + self.extracted_licensing_info_parser.logger, + ), + True, + ), + ] parsed_fields = {} diff --git a/src/spdx/parser/jsonlikedict/package_parser.py b/src/spdx/parser/jsonlikedict/package_parser.py index 115474c1a..9ed80c0ee 100644 --- a/src/spdx/parser/jsonlikedict/package_parser.py +++ b/src/spdx/parser/jsonlikedict/package_parser.py @@ -57,19 +57,23 @@ def parse_package(self, package_dict: Dict) -> Package: spdx_id: Optional[str] = package_dict.get("SPDXID") attribution_texts: List[str] = package_dict.get("attributionTexts", []) - built_date: Optional[datetime] = parse_field_or_log_error(logger, package_dict.get("builtDate"), - datetime_from_str) + built_date: Optional[datetime] = parse_field_or_log_error( + logger, package_dict.get("builtDate"), datetime_from_str + ) - checksums = parse_field_or_log_error(logger, package_dict.get("checksums"), self.checksum_parser.parse_checksum, - field_is_list=True) + checksums = parse_field_or_log_error( + logger, package_dict.get("checksums"), self.checksum_parser.parse_checksum, field_is_list=True + ) comment: Optional[str] = package_dict.get("comment") copyright_text: Optional[str] = package_dict.get("copyrightText") description: Optional[str] = package_dict.get("description") download_location: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = parse_field_or_no_assertion_or_none( - package_dict.get("downloadLocation")) + package_dict.get("downloadLocation") + ) - external_refs: List[ExternalPackageRef] = parse_field_or_log_error(logger, package_dict.get("externalRefs"), - self.parse_external_refs) + external_refs: List[ExternalPackageRef] = parse_field_or_log_error( + logger, package_dict.get("externalRefs"), self.parse_external_refs + ) files_analyzed: Optional[Union[bool, str]] = package_dict.get("filesAnalyzed") @@ -84,85 +88,112 @@ def parse_package(self, package_dict: Dict) -> Package: homepage: Optional[str] = package_dict.get("homepage") license_comments: Optional[str] = package_dict.get("licenseComments") license_concluded = parse_field_or_log_error( - logger, package_dict.get("licenseConcluded"), self.license_expression_parser.parse_license_expression) + logger, package_dict.get("licenseConcluded"), self.license_expression_parser.parse_license_expression + ) license_declared: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error( - logger, package_dict.get("licenseDeclared"), self.license_expression_parser.parse_license_expression) + logger, package_dict.get("licenseDeclared"), self.license_expression_parser.parse_license_expression + ) license_info_from_file: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error( - logger, package_dict.get("licenseInfoFromFiles"), self.license_expression_parser.parse_license_expression, - field_is_list=True) + logger, + package_dict.get("licenseInfoFromFiles"), + self.license_expression_parser.parse_license_expression, + field_is_list=True, + ) originator: Optional[Union[Actor, SpdxNoAssertion]] = parse_field_or_log_error( - logger, package_dict.get("originator"), - lambda x: parse_field_or_no_assertion(x, self.actor_parser.parse_actor)) + logger, + package_dict.get("originator"), + lambda x: parse_field_or_no_assertion(x, self.actor_parser.parse_actor), + ) package_file_name: Optional[str] = package_dict.get("packageFileName") - package_verification_code: Optional[ - PackageVerificationCode] = parse_field_or_log_error(logger, package_dict.get("packageVerificationCode"), - self.parse_package_verification_code) - primary_package_purpose: Optional[PackagePurpose] = parse_field_or_log_error(logger, package_dict.get( - "primaryPackagePurpose"), self.parse_primary_package_purpose) + package_verification_code: Optional[PackageVerificationCode] = parse_field_or_log_error( + logger, package_dict.get("packageVerificationCode"), self.parse_package_verification_code + ) + primary_package_purpose: Optional[PackagePurpose] = parse_field_or_log_error( + logger, package_dict.get("primaryPackagePurpose"), self.parse_primary_package_purpose + ) - release_date: Optional[datetime] = parse_field_or_log_error(logger, package_dict.get("releaseDate"), - datetime_from_str) + release_date: Optional[datetime] = parse_field_or_log_error( + logger, package_dict.get("releaseDate"), datetime_from_str + ) source_info: Optional[str] = package_dict.get("sourceInfo") summary: Optional[str] = package_dict.get("summary") supplier: Optional[Union[Actor, SpdxNoAssertion]] = parse_field_or_log_error( - logger, package_dict.get("supplier"), - lambda x: parse_field_or_no_assertion(x, self.actor_parser.parse_actor)) - valid_until_date: Optional[datetime] = parse_field_or_log_error(logger, package_dict.get("validUntilDate"), - datetime_from_str) + logger, + package_dict.get("supplier"), + lambda x: parse_field_or_no_assertion(x, self.actor_parser.parse_actor), + ) + valid_until_date: Optional[datetime] = parse_field_or_log_error( + logger, package_dict.get("validUntilDate"), datetime_from_str + ) version_info: Optional[str] = package_dict.get("versionInfo") raise_parsing_error_if_logger_has_messages(logger, "Package") - package = construct_or_raise_parsing_error(Package, - dict(spdx_id=spdx_id, name=name, download_location=download_location, - version=version_info, file_name=package_file_name, - supplier=supplier, originator=originator, - files_analyzed=files_analyzed, - verification_code=package_verification_code, - checksums=checksums, homepage=homepage, source_info=source_info, - license_concluded=license_concluded, - license_info_from_files=license_info_from_file, - license_declared=license_declared, - license_comment=license_comments, - copyright_text=copyright_text, summary=summary, - description=description, comment=comment, - external_references=external_refs, - attribution_texts=attribution_texts, - primary_package_purpose=primary_package_purpose, - release_date=release_date, built_date=built_date, - valid_until_date=valid_until_date)) + package = construct_or_raise_parsing_error( + Package, + dict( + spdx_id=spdx_id, + name=name, + download_location=download_location, + version=version_info, + file_name=package_file_name, + supplier=supplier, + originator=originator, + files_analyzed=files_analyzed, + verification_code=package_verification_code, + checksums=checksums, + homepage=homepage, + source_info=source_info, + license_concluded=license_concluded, + license_info_from_files=license_info_from_file, + license_declared=license_declared, + license_comment=license_comments, + copyright_text=copyright_text, + summary=summary, + description=description, + comment=comment, + external_references=external_refs, + attribution_texts=attribution_texts, + primary_package_purpose=primary_package_purpose, + release_date=release_date, + built_date=built_date, + valid_until_date=valid_until_date, + ), + ) return package def parse_external_refs(self, external_ref_dicts: List[Dict]) -> List[ExternalPackageRef]: external_refs = [] for external_ref_dict in external_ref_dicts: - external_refs = append_parsed_field_or_log_error(self.logger, external_refs, external_ref_dict, - self.parse_external_ref) + external_refs = append_parsed_field_or_log_error( + self.logger, external_refs, external_ref_dict, self.parse_external_ref + ) return external_refs def parse_external_ref(self, external_ref_dict: Dict) -> ExternalPackageRef: logger = Logger() - ref_category = parse_field_or_log_error(logger, external_ref_dict.get("referenceCategory"), - self.parse_external_ref_category) + ref_category = parse_field_or_log_error( + logger, external_ref_dict.get("referenceCategory"), self.parse_external_ref_category + ) ref_locator: Optional[str] = external_ref_dict.get("referenceLocator") ref_type: Optional[str] = external_ref_dict.get("referenceType") comment: Optional[str] = external_ref_dict.get("comment") raise_parsing_error_if_logger_has_messages(logger, "ExternalPackageRef") - external_ref = construct_or_raise_parsing_error(ExternalPackageRef, - dict(category=ref_category, reference_type=ref_type, - locator=ref_locator, comment=comment)) + external_ref = construct_or_raise_parsing_error( + ExternalPackageRef, + dict(category=ref_category, reference_type=ref_type, locator=ref_locator, comment=comment), + ) return external_ref @staticmethod def parse_external_ref_category(external_ref_category_str: str) -> ExternalPackageRefCategory: try: - external_ref_category = ExternalPackageRefCategory[ - json_str_to_enum_name(external_ref_category_str)] + external_ref_category = ExternalPackageRefCategory[json_str_to_enum_name(external_ref_category_str)] except KeyError: raise SPDXParsingError([f"Invalid ExternalPackageRefCategory: {external_ref_category_str}"]) @@ -173,9 +204,9 @@ def parse_package_verification_code(verification_code_dict: Dict) -> PackageVeri excluded_files: List[str] = verification_code_dict.get("packageVerificationCodeExcludedFiles", []) verification_code_value: Optional[str] = verification_code_dict.get("packageVerificationCodeValue") - package_verification_code = construct_or_raise_parsing_error(PackageVerificationCode, - dict(value=verification_code_value, - excluded_files=excluded_files)) + package_verification_code = construct_or_raise_parsing_error( + PackageVerificationCode, dict(value=verification_code_value, excluded_files=excluded_files) + ) return package_verification_code diff --git a/src/spdx/parser/jsonlikedict/relationship_parser.py b/src/spdx/parser/jsonlikedict/relationship_parser.py index d83aaf8f4..598ec4ecd 100644 --- a/src/spdx/parser/jsonlikedict/relationship_parser.py +++ b/src/spdx/parser/jsonlikedict/relationship_parser.py @@ -33,21 +33,33 @@ def parse_all_relationships(self, input_doc_dict: Dict) -> List[Relationship]: relationships = [] relationship_dicts: List[Dict] = input_doc_dict.get("relationships", []) relationships.extend( - parse_field_or_log_error(self.logger, relationship_dicts, self.parse_relationship, [], True)) + parse_field_or_log_error(self.logger, relationship_dicts, self.parse_relationship, [], True) + ) document_describes: List[str] = delete_duplicates_from_list(input_doc_dict.get("documentDescribes", [])) doc_spdx_id: Optional[str] = input_doc_dict.get("SPDXID") relationships.extend( - parse_field_or_log_error(self.logger, document_describes, lambda x: self.parse_document_describes( - doc_spdx_id=doc_spdx_id, described_spdx_ids=x, - existing_relationships=relationships), [])) + parse_field_or_log_error( + self.logger, + document_describes, + lambda x: self.parse_document_describes( + doc_spdx_id=doc_spdx_id, described_spdx_ids=x, existing_relationships=relationships + ), + [], + ) + ) package_dicts: List[Dict] = input_doc_dict.get("packages", []) - relationships.extend(parse_field_or_log_error( - self.logger, package_dicts, - lambda x: self.parse_has_files(package_dicts=x, existing_relationships=relationships), [])) + relationships.extend( + parse_field_or_log_error( + self.logger, + package_dicts, + lambda x: self.parse_has_files(package_dicts=x, existing_relationships=relationships), + [], + ) + ) file_dicts: List[Dict] = input_doc_dict.get("files", []) @@ -62,16 +74,24 @@ def parse_all_relationships(self, input_doc_dict: Dict) -> List[Relationship]: def parse_relationship(self, relationship_dict: Dict) -> Relationship: logger = Logger() spdx_element_id: Optional[str] = relationship_dict.get("spdxElementId") - related_spdx_element: Optional[str] = parse_field_or_no_assertion_or_none(relationship_dict.get("relatedSpdxElement")) - relationship_type: Optional[RelationshipType] = parse_field_or_log_error(logger, relationship_dict.get( - "relationshipType"), self.parse_relationship_type) + related_spdx_element: Optional[str] = parse_field_or_no_assertion_or_none( + relationship_dict.get("relatedSpdxElement") + ) + relationship_type: Optional[RelationshipType] = parse_field_or_log_error( + logger, relationship_dict.get("relationshipType"), self.parse_relationship_type + ) relationship_comment: Optional[str] = relationship_dict.get("comment") raise_parsing_error_if_logger_has_messages(logger, "Relationship") - relationship = construct_or_raise_parsing_error(Relationship, dict(spdx_element_id=spdx_element_id, - relationship_type=relationship_type, - related_spdx_element_id=related_spdx_element, - comment=relationship_comment)) + relationship = construct_or_raise_parsing_error( + Relationship, + dict( + spdx_element_id=spdx_element_id, + relationship_type=relationship_type, + related_spdx_element_id=related_spdx_element, + comment=relationship_comment, + ), + ) return relationship @staticmethod @@ -82,15 +102,18 @@ def parse_relationship_type(relationship_type_str: str) -> RelationshipType: raise SPDXParsingError([f"Invalid RelationshipType: {relationship_type_str}"]) return relationship_type - def parse_document_describes(self, doc_spdx_id: str, described_spdx_ids: List[str], - existing_relationships: List[Relationship]) -> List[Relationship]: + def parse_document_describes( + self, doc_spdx_id: str, described_spdx_ids: List[str], existing_relationships: List[Relationship] + ) -> List[Relationship]: logger = Logger() describes_relationships = [] for spdx_id in described_spdx_ids: try: - describes_relationship = Relationship(spdx_element_id=doc_spdx_id, - relationship_type=RelationshipType.DESCRIBES, - related_spdx_element_id=spdx_id) + describes_relationship = Relationship( + spdx_element_id=doc_spdx_id, + relationship_type=RelationshipType.DESCRIBES, + related_spdx_element_id=spdx_id, + ) except ConstructorTypeErrors as err: logger.append(err.get_messages()) continue @@ -100,8 +123,9 @@ def parse_document_describes(self, doc_spdx_id: str, described_spdx_ids: List[st return describes_relationships - def parse_has_files(self, package_dicts: List[Dict], existing_relationships: List[Relationship]) -> List[ - Relationship]: + def parse_has_files( + self, package_dicts: List[Dict], existing_relationships: List[Relationship] + ) -> List[Relationship]: logger = Logger() contains_relationships = [] for package in package_dicts: @@ -111,23 +135,28 @@ def parse_has_files(self, package_dicts: List[Dict], existing_relationships: Lis continue for file_spdx_id in contained_files: try: - contains_relationship = Relationship(spdx_element_id=package_spdx_id, - relationship_type=RelationshipType.CONTAINS, - related_spdx_element_id=file_spdx_id) + contains_relationship = Relationship( + spdx_element_id=package_spdx_id, + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id=file_spdx_id, + ) except ConstructorTypeErrors as err: logger.append(err.get_messages()) continue - if not self.check_if_relationship_exists(relationship=contains_relationship, - existing_relationships=existing_relationships): + if not self.check_if_relationship_exists( + relationship=contains_relationship, existing_relationships=existing_relationships + ): contains_relationships.append(contains_relationship) raise_parsing_error_if_logger_has_messages(logger, "package contains relationships") return contains_relationships - def check_if_relationship_exists(self, relationship: Relationship, - existing_relationships: List[Relationship]) -> bool: + def check_if_relationship_exists( + self, relationship: Relationship, existing_relationships: List[Relationship] + ) -> bool: existing_relationships_without_comments: List[Relationship] = self.get_all_relationships_without_comments( - existing_relationships) + existing_relationships + ) if relationship in existing_relationships_without_comments: return True relationship_inverted: Relationship = self.invert_relationship(relationship) @@ -138,26 +167,33 @@ def check_if_relationship_exists(self, relationship: Relationship, @staticmethod def get_all_relationships_without_comments(existing_relationships: List[Relationship]) -> List[Relationship]: - relationships_without_comments = [Relationship(relationship_type=relationship.relationship_type, - related_spdx_element_id=relationship.related_spdx_element_id, - spdx_element_id=relationship.spdx_element_id) for relationship in - existing_relationships] + relationships_without_comments = [ + Relationship( + relationship_type=relationship.relationship_type, + related_spdx_element_id=relationship.related_spdx_element_id, + spdx_element_id=relationship.spdx_element_id, + ) + for relationship in existing_relationships + ] return relationships_without_comments def invert_relationship(self, relationship: Relationship) -> Relationship: - return Relationship(related_spdx_element_id=relationship.spdx_element_id, - spdx_element_id=relationship.related_spdx_element_id, - relationship_type=self.invert_relationship_types[relationship.relationship_type], - comment=relationship.comment) - - invert_relationship_types = {RelationshipType.DESCRIBES: RelationshipType.DESCRIBED_BY, - RelationshipType.DESCRIBED_BY: RelationshipType.DESCRIBES, - RelationshipType.CONTAINS: RelationshipType.CONTAINED_BY, - RelationshipType.CONTAINED_BY: RelationshipType.CONTAINS} + return Relationship( + related_spdx_element_id=relationship.spdx_element_id, + spdx_element_id=relationship.related_spdx_element_id, + relationship_type=self.invert_relationship_types[relationship.relationship_type], + comment=relationship.comment, + ) + + invert_relationship_types = { + RelationshipType.DESCRIBES: RelationshipType.DESCRIBED_BY, + RelationshipType.DESCRIBED_BY: RelationshipType.DESCRIBES, + RelationshipType.CONTAINS: RelationshipType.CONTAINED_BY, + RelationshipType.CONTAINED_BY: RelationshipType.CONTAINS, + } @staticmethod - def parse_file_dependencies(file_dicts: List[Dict]) -> List[ - Relationship]: + def parse_file_dependencies(file_dicts: List[Dict]) -> List[Relationship]: dependency_relationships = [] # the field fileDependencies is deprecated and should be converted to a relationship (https://github.com/spdx/tools-python/issues/387) return dependency_relationships diff --git a/src/spdx/parser/jsonlikedict/snippet_parser.py b/src/spdx/parser/jsonlikedict/snippet_parser.py index a5a60a00c..d07e6eff6 100644 --- a/src/spdx/parser/jsonlikedict/snippet_parser.py +++ b/src/spdx/parser/jsonlikedict/snippet_parser.py @@ -56,21 +56,34 @@ def parse_snippet(self, snippet_dict: Dict) -> Snippet: copyright_text: Optional[str] = snippet_dict.get("copyrightText") license_comment: Optional[str] = snippet_dict.get("licenseComments") license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error( - logger, snippet_dict.get("licenseConcluded"), self.license_expression_parser.parse_license_expression) + logger, snippet_dict.get("licenseConcluded"), self.license_expression_parser.parse_license_expression + ) license_info: List[Union[LicenseExpression], SpdxNoAssertion, SpdxNone] = parse_field_or_log_error( - logger, snippet_dict.get("licenseInfoInSnippets"), self.license_expression_parser.parse_license_expression, - field_is_list=True) + logger, + snippet_dict.get("licenseInfoInSnippets"), + self.license_expression_parser.parse_license_expression, + field_is_list=True, + ) if logger.has_messages(): raise SPDXParsingError([f"Error while parsing snippet: {logger.get_messages()}"]) - snippet = construct_or_raise_parsing_error(Snippet, - dict(spdx_id=spdx_id, name=name, byte_range=byte_range, - file_spdx_id=file_spdx_id, line_range=line_range, - attribution_texts=attribution_texts, comment=comment, - copyright_text=copyright_text, license_comment=license_comment, - license_concluded=license_concluded, - license_info_in_snippet=license_info)) + snippet = construct_or_raise_parsing_error( + Snippet, + dict( + spdx_id=spdx_id, + name=name, + byte_range=byte_range, + file_spdx_id=file_spdx_id, + line_range=line_range, + attribution_texts=attribution_texts, + comment=comment, + copyright_text=copyright_text, + license_comment=license_comment, + license_concluded=license_concluded, + license_info_in_snippet=license_info, + ), + ) return snippet @@ -120,8 +133,9 @@ def validate_pointer_and_get_type(pointer: Dict) -> RangeType: return RangeType.BYTE if "offset" in pointer else RangeType.LINE @staticmethod - def convert_range_from_str(_range: Tuple[Union[int, str], Union[int, str]]) -> Tuple[ - Union[int, str], Union[int, str]]: + def convert_range_from_str( + _range: Tuple[Union[int, str], Union[int, str]] + ) -> Tuple[Union[int, str], Union[int, str]]: # XML does not support integers, so we have to convert from string (if possible) if not _range: return _range diff --git a/src/spdx/parser/rdf/annotation_parser.py b/src/spdx/parser/rdf/annotation_parser.py index 74a927c09..80d6229bf 100644 --- a/src/spdx/parser/rdf/annotation_parser.py +++ b/src/spdx/parser/rdf/annotation_parser.py @@ -22,18 +22,31 @@ def parse_annotation(annotation_node: URIRef, graph: Graph, parent_node: URIRef, doc_namespace: str) -> Annotation: logger = Logger() spdx_id = parse_spdx_id(parent_node, doc_namespace, graph) - annotator = parse_literal(logger, graph, annotation_node, SPDX_NAMESPACE.annotator, - parsing_method=ActorParser.parse_actor) - annotation_type = parse_literal(logger, graph, annotation_node, SPDX_NAMESPACE.annotationType, - parsing_method=lambda x: parse_enum_value(x, AnnotationType, - SPDX_NAMESPACE.annotationType_)) - annotation_date = parse_literal(logger, graph, annotation_node, SPDX_NAMESPACE.annotationDate, - parsing_method=datetime_from_str) + annotator = parse_literal( + logger, graph, annotation_node, SPDX_NAMESPACE.annotator, parsing_method=ActorParser.parse_actor + ) + annotation_type = parse_literal( + logger, + graph, + annotation_node, + SPDX_NAMESPACE.annotationType, + parsing_method=lambda x: parse_enum_value(x, AnnotationType, SPDX_NAMESPACE.annotationType_), + ) + annotation_date = parse_literal( + logger, graph, annotation_node, SPDX_NAMESPACE.annotationDate, parsing_method=datetime_from_str + ) annotation_comment = parse_literal(logger, graph, annotation_node, RDFS.comment) raise_parsing_error_if_logger_has_messages(logger, "Annotation") - annotation = construct_or_raise_parsing_error(Annotation, dict(spdx_id=spdx_id, annotation_type=annotation_type, - annotator=annotator, annotation_date=annotation_date, - annotation_comment=annotation_comment)) + annotation = construct_or_raise_parsing_error( + Annotation, + dict( + spdx_id=spdx_id, + annotation_type=annotation_type, + annotator=annotator, + annotation_date=annotation_date, + annotation_comment=annotation_comment, + ), + ) return annotation diff --git a/src/spdx/parser/rdf/checksum_parser.py b/src/spdx/parser/rdf/checksum_parser.py index 40f7899a9..91fd82244 100644 --- a/src/spdx/parser/rdf/checksum_parser.py +++ b/src/spdx/parser/rdf/checksum_parser.py @@ -20,8 +20,9 @@ def parse_checksum(parent_node: URIRef, graph: Graph) -> Checksum: logger = Logger() - algorithm = parse_literal(logger, graph, parent_node, SPDX_NAMESPACE.algorithm, - parsing_method=convert_rdf_to_algorithm) + algorithm = parse_literal( + logger, graph, parent_node, SPDX_NAMESPACE.algorithm, parsing_method=convert_rdf_to_algorithm + ) value = parse_literal(logger, graph, parent_node, SPDX_NAMESPACE.checksumValue) raise_parsing_error_if_logger_has_messages(logger, "Checksum") diff --git a/src/spdx/parser/rdf/creation_info_parser.py b/src/spdx/parser/rdf/creation_info_parser.py index ac8d1e1e6..6d6ac9b50 100644 --- a/src/spdx/parser/rdf/creation_info_parser.py +++ b/src/spdx/parser/rdf/creation_info_parser.py @@ -34,8 +34,13 @@ def parse_creation_info(graph: Graph) -> Tuple[CreationInfo, URIRef]: logger = Logger() namespace, spdx_id, doc_node = parse_namespace_and_spdx_id(graph) spec_version = parse_literal(logger, graph, doc_node, SPDX_NAMESPACE.specVersion) - data_license = parse_literal(logger, graph, doc_node, SPDX_NAMESPACE.dataLicense, - parsing_method=lambda x: remove_prefix(x, LICENSE_NAMESPACE)) + data_license = parse_literal( + logger, + graph, + doc_node, + SPDX_NAMESPACE.dataLicense, + parsing_method=lambda x: remove_prefix(x, LICENSE_NAMESPACE), + ) comment = parse_literal(logger, graph, doc_node, RDFS.comment) name = parse_literal(logger, graph, doc_node, SPDX_NAMESPACE.name) @@ -44,27 +49,37 @@ def parse_creation_info(graph: Graph) -> Tuple[CreationInfo, URIRef]: logger.append("CreationInfo does not exist.") raise SPDXParsingError([f"Error while parsing document {name}: {logger.get_messages()}"]) - created = parse_literal(logger, graph, creation_info_node, SPDX_NAMESPACE.created, - parsing_method=datetime_from_str) - license_list_version = parse_literal(logger, graph, creation_info_node, SPDX_NAMESPACE.licenseListVersion, - parsing_method=Version.from_string) + created = parse_literal( + logger, graph, creation_info_node, SPDX_NAMESPACE.created, parsing_method=datetime_from_str + ) + license_list_version = parse_literal( + logger, graph, creation_info_node, SPDX_NAMESPACE.licenseListVersion, parsing_method=Version.from_string + ) creator_comment = parse_literal(logger, graph, creation_info_node, RDFS.comment) creators = [] - for (_, _, creator_literal) in graph.triples((creation_info_node, SPDX_NAMESPACE.creator, None)): + for _, _, creator_literal in graph.triples((creation_info_node, SPDX_NAMESPACE.creator, None)): creators.append(ActorParser.parse_actor(creator_literal)) external_document_refs = [] - for (_, _, external_document_node) in graph.triples((doc_node, SPDX_NAMESPACE.externalDocumentRef, None)): + for _, _, external_document_node in graph.triples((doc_node, SPDX_NAMESPACE.externalDocumentRef, None)): external_document_refs.append(parse_external_document_refs(external_document_node, graph, namespace)) raise_parsing_error_if_logger_has_messages(logger, "CreationInfo") - creation_info = construct_or_raise_parsing_error(CreationInfo, dict(spdx_id=spdx_id, document_namespace=namespace, - spdx_version=spec_version, name=name, - data_license=data_license, - document_comment=comment, created=created, - license_list_version=license_list_version, - creator_comment=creator_comment, - creators=creators, - external_document_refs=external_document_refs)) + creation_info = construct_or_raise_parsing_error( + CreationInfo, + dict( + spdx_id=spdx_id, + document_namespace=namespace, + spdx_version=spec_version, + name=name, + data_license=data_license, + document_comment=comment, + created=created, + license_list_version=license_list_version, + creator_comment=creator_comment, + creators=creators, + external_document_refs=external_document_refs, + ), + ) return creation_info, doc_node @@ -79,15 +94,18 @@ def parse_namespace_and_spdx_id(graph: Graph) -> (str, str): logging.error("No SpdxDocument found, can't parse rdf file.") sys.exit(1) if not "#" in subject: - logging.error("No '#' found in the URI of SpdxDocument, " - "the URI for the SpdxDocument should be the namespace appended by '#SPDXRef-DOCUMENT.") + logging.error( + "No '#' found in the URI of SpdxDocument, " + "the URI for the SpdxDocument should be the namespace appended by '#SPDXRef-DOCUMENT." + ) sys.exit(1) namespace, spdx_id = urldefrag(subject) if not namespace: logging.error( - "No namespace found, the URI for the SpdxDocument should be the namespace appended by '#SPDXRef-DOCUMENT.") + "No namespace found, the URI for the SpdxDocument should be the namespace appended by '#SPDXRef-DOCUMENT." + ) sys.exit(1) if not spdx_id: @@ -96,16 +114,22 @@ def parse_namespace_and_spdx_id(graph: Graph) -> (str, str): return namespace, spdx_id, subject -def parse_external_document_refs(external_document_node: URIRef, graph: Graph, - doc_namespace: str) -> ExternalDocumentRef: +def parse_external_document_refs( + external_document_node: URIRef, graph: Graph, doc_namespace: str +) -> ExternalDocumentRef: logger = Logger() document_ref_id = parse_spdx_id(external_document_node, doc_namespace, graph) document_uri = parse_literal(logger, graph, external_document_node, SPDX_NAMESPACE.spdxDocument) - checksum = parse_literal(logger, graph, external_document_node, SPDX_NAMESPACE.checksum, - parsing_method=lambda x: parse_checksum(x, graph)) - external_document_ref = construct_or_raise_parsing_error(ExternalDocumentRef, dict(document_ref_id=document_ref_id, - document_uri=document_uri, - checksum=checksum)) + checksum = parse_literal( + logger, + graph, + external_document_node, + SPDX_NAMESPACE.checksum, + parsing_method=lambda x: parse_checksum(x, graph), + ) + external_document_ref = construct_or_raise_parsing_error( + ExternalDocumentRef, dict(document_ref_id=document_ref_id, document_uri=document_uri, checksum=checksum) + ) # To replace the external doc namespaces by the ref id in spdx ids later (e.g. in a relationship), we need to bind # the namespace to the graph. diff --git a/src/spdx/parser/rdf/extracted_licensing_info_parser.py b/src/spdx/parser/rdf/extracted_licensing_info_parser.py index 88b9f7688..2fa598696 100644 --- a/src/spdx/parser/rdf/extracted_licensing_info_parser.py +++ b/src/spdx/parser/rdf/extracted_licensing_info_parser.py @@ -22,15 +22,22 @@ def parse_extracted_licensing_info(extracted_licensing_info_node: URIRef, graph: license_id = parse_literal(logger, graph, extracted_licensing_info_node, SPDX_NAMESPACE.licenseId) extracted_text = parse_literal(logger, graph, extracted_licensing_info_node, SPDX_NAMESPACE.extractedText) comment = parse_literal(logger, graph, extracted_licensing_info_node, RDFS.comment) - license_name = parse_literal_or_no_assertion_or_none(logger, graph, extracted_licensing_info_node, SPDX_NAMESPACE.name) + license_name = parse_literal_or_no_assertion_or_none( + logger, graph, extracted_licensing_info_node, SPDX_NAMESPACE.name + ) cross_references = [] - for (_, _, cross_reference_node) in graph.triples((extracted_licensing_info_node, RDFS.seeAlso, None)): + for _, _, cross_reference_node in graph.triples((extracted_licensing_info_node, RDFS.seeAlso, None)): cross_references.append(cross_reference_node.toPython()) raise_parsing_error_if_logger_has_messages(logger, "ExtractedLicensingInfo") - extracted_licensing_info = construct_or_raise_parsing_error(ExtractedLicensingInfo, dict(license_id=license_id, - extracted_text=extracted_text, - comment=comment, - license_name=license_name, - cross_references=cross_references)) + extracted_licensing_info = construct_or_raise_parsing_error( + ExtractedLicensingInfo, + dict( + license_id=license_id, + extracted_text=extracted_text, + comment=comment, + license_name=license_name, + cross_references=cross_references, + ), + ) return extracted_licensing_info diff --git a/src/spdx/parser/rdf/file_parser.py b/src/spdx/parser/rdf/file_parser.py index 53a7c8860..5f0a0a5cd 100644 --- a/src/spdx/parser/rdf/file_parser.py +++ b/src/spdx/parser/rdf/file_parser.py @@ -31,41 +31,57 @@ def parse_file(file_node: URIRef, graph: Graph, doc_namespace: str) -> File: spdx_id = parse_spdx_id(file_node, doc_namespace, graph) name = parse_literal(logger, graph, file_node, SPDX_NAMESPACE.fileName) checksums = [] - for (_, _, checksum_node) in graph.triples((file_node, SPDX_NAMESPACE.checksum, None)): + for _, _, checksum_node in graph.triples((file_node, SPDX_NAMESPACE.checksum, None)): checksums.append(parse_checksum(checksum_node, graph)) file_types = [] - for (_, _, file_type_ref) in graph.triples((file_node, SPDX_NAMESPACE.fileType, None)): + for _, _, file_type_ref in graph.triples((file_node, SPDX_NAMESPACE.fileType, None)): file_types.append( - apply_parsing_method_or_log_error(logger, file_type_ref, - parsing_method=lambda x: parse_enum_value(x, FileType, - SPDX_NAMESPACE.fileType_))) + apply_parsing_method_or_log_error( + logger, file_type_ref, parsing_method=lambda x: parse_enum_value(x, FileType, SPDX_NAMESPACE.fileType_) + ) + ) license_concluded = parse_literal_or_no_assertion_or_none( - logger, graph, file_node, SPDX_NAMESPACE.licenseConcluded, - parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace)) + logger, + graph, + file_node, + SPDX_NAMESPACE.licenseConcluded, + parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace), + ) license_info_in_file = [] - for (_, _, license_info_from_files_node) in graph.triples((file_node, SPDX_NAMESPACE.licenseInfoInFile, None)): + for _, _, license_info_from_files_node in graph.triples((file_node, SPDX_NAMESPACE.licenseInfoInFile, None)): license_info_in_file.append( - get_correctly_typed_value(logger, license_info_from_files_node, - lambda x: parse_license_expression(x, graph, doc_namespace))) + get_correctly_typed_value( + logger, license_info_from_files_node, lambda x: parse_license_expression(x, graph, doc_namespace) + ) + ) license_comment = parse_literal(logger, graph, file_node, SPDX_NAMESPACE.licenseComments) copyright_text = parse_literal_or_no_assertion_or_none(logger, graph, file_node, SPDX_NAMESPACE.copyrightText) file_contributors = [] - for (_, _, file_contributor) in graph.triples((file_node, SPDX_NAMESPACE.fileContributor, None)): + for _, _, file_contributor in graph.triples((file_node, SPDX_NAMESPACE.fileContributor, None)): file_contributors.append(file_contributor.toPython()) notice_text = parse_literal(logger, graph, file_node, SPDX_NAMESPACE.noticeText) comment = parse_literal(logger, graph, file_node, RDFS.comment) attribution_texts = [] - for (_, _, attribution_text_literal) in graph.triples((file_node, SPDX_NAMESPACE.attributionText, None)): + for _, _, attribution_text_literal in graph.triples((file_node, SPDX_NAMESPACE.attributionText, None)): attribution_texts.append(attribution_text_literal.toPython()) raise_parsing_error_if_logger_has_messages(logger, "File") - file = construct_or_raise_parsing_error(File, dict(name=name, spdx_id=spdx_id, checksums=checksums, - attribution_texts=attribution_texts, comment=comment, - copyright_text=copyright_text, file_types=file_types, - contributors=file_contributors, - license_comment=license_comment, - license_concluded=license_concluded, - license_info_in_file=license_info_in_file, - notice=notice_text)) + file = construct_or_raise_parsing_error( + File, + dict( + name=name, + spdx_id=spdx_id, + checksums=checksums, + attribution_texts=attribution_texts, + comment=comment, + copyright_text=copyright_text, + file_types=file_types, + contributors=file_contributors, + license_comment=license_comment, + license_concluded=license_concluded, + license_info_in_file=license_info_in_file, + notice=notice_text, + ), + ) return file diff --git a/src/spdx/parser/rdf/graph_parsing_functions.py b/src/spdx/parser/rdf/graph_parsing_functions.py index 89bb34542..297f6e9ba 100644 --- a/src/spdx/parser/rdf/graph_parsing_functions.py +++ b/src/spdx/parser/rdf/graph_parsing_functions.py @@ -24,16 +24,23 @@ from spdx.rdfschema.namespace import SPDX_NAMESPACE -def parse_literal(logger: Logger, graph: Graph, subject: Node, predicate: Node, - parsing_method: Callable = lambda x: x.strip(), default: Any = None): +def parse_literal( + logger: Logger, + graph: Graph, + subject: Node, + predicate: Node, + parsing_method: Callable = lambda x: x.strip(), + default: Any = None, +): value = get_unique_value(logger, graph, subject, predicate, default) if not value: return default return apply_parsing_method_or_log_error(logger, value, parsing_method, default) -def apply_parsing_method_or_log_error(logger: Logger, value: Any, parsing_method: Callable = lambda x: x.strip(), - default: Any = None): +def apply_parsing_method_or_log_error( + logger: Logger, value: Any, parsing_method: Callable = lambda x: x.strip(), default: Any = None +): try: return parsing_method(value) except SPDXParsingError as err: @@ -43,14 +50,21 @@ def apply_parsing_method_or_log_error(logger: Logger, value: Any, parsing_method return default -def parse_literal_or_no_assertion_or_none(logger: Logger, graph: Graph, subject: Node, predicate: Node, - parsing_method: Callable = lambda x: x.strip(), default: Any = None): +def parse_literal_or_no_assertion_or_none( + logger: Logger, + graph: Graph, + subject: Node, + predicate: Node, + parsing_method: Callable = lambda x: x.strip(), + default: Any = None, +): value = get_unique_value(logger, graph, subject, predicate, default) return get_correctly_typed_value(logger, value, parsing_method, default) -def get_correctly_typed_value(logger: Logger, value: Any, parsing_method: Callable = lambda x: x.strip(), - default: Any = None): +def get_correctly_typed_value( + logger: Logger, value: Any, parsing_method: Callable = lambda x: x.strip(), default: Any = None +): if not value: return default if value == SPDX_NAMESPACE.noassertion or value.toPython() == SPDX_NO_ASSERTION_STRING: @@ -93,5 +107,5 @@ def parse_spdx_id(resource: URIRef, doc_namespace: str, graph: Graph) -> Optiona # to write our own helper method to delete prefixes. def remove_prefix(string: str, prefix: str) -> str: if string.startswith(prefix): - return string[len(prefix):] + return string[len(prefix) :] return string diff --git a/src/spdx/parser/rdf/license_expression_parser.py b/src/spdx/parser/rdf/license_expression_parser.py index 1d0293b57..346fd5143 100644 --- a/src/spdx/parser/rdf/license_expression_parser.py +++ b/src/spdx/parser/rdf/license_expression_parser.py @@ -18,8 +18,9 @@ from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE -def parse_license_expression(license_expression_node: Union[URIRef, BNode, Node], graph: Graph, - doc_namespace: str) -> LicenseExpression: +def parse_license_expression( + license_expression_node: Union[URIRef, BNode, Node], graph: Graph, doc_namespace: str +) -> LicenseExpression: spdx_licensing = get_spdx_licensing() expression = "" if license_expression_node.startswith(LICENSE_NAMESPACE): @@ -32,19 +33,21 @@ def parse_license_expression(license_expression_node: Union[URIRef, BNode, Node] node_type = graph.value(license_expression_node, RDF.type) if node_type == SPDX_NAMESPACE.ConjunctiveLicenseSet: members = [] - for (_, _, member_node) in graph.triples((license_expression_node, SPDX_NAMESPACE.member, None)): + for _, _, member_node in graph.triples((license_expression_node, SPDX_NAMESPACE.member, None)): members.append(parse_license_expression(member_node, graph, doc_namespace)) expression = " AND ".join([str(member) for member in members]) if node_type == SPDX_NAMESPACE.DisjunctiveLicenseSet: members = [] - for (_, _, member_node) in graph.triples((license_expression_node, SPDX_NAMESPACE.member, None)): + for _, _, member_node in graph.triples((license_expression_node, SPDX_NAMESPACE.member, None)): members.append(parse_license_expression(member_node, graph, doc_namespace)) expression = " OR ".join([str(member) for member in members]) if node_type == SPDX_NAMESPACE.WithExceptionOperator: - license_expression = parse_license_expression(graph.value(license_expression_node, SPDX_NAMESPACE.member), - graph, doc_namespace) - exception = parse_license_exception(graph.value(license_expression_node, SPDX_NAMESPACE.licenseException), - graph) + license_expression = parse_license_expression( + graph.value(license_expression_node, SPDX_NAMESPACE.member), graph, doc_namespace + ) + exception = parse_license_exception( + graph.value(license_expression_node, SPDX_NAMESPACE.licenseException), graph + ) expression = f"{license_expression} WITH {exception}" return spdx_licensing.parse(expression) diff --git a/src/spdx/parser/rdf/package_parser.py b/src/spdx/parser/rdf/package_parser.py index 9346d2dfc..a09630d2b 100644 --- a/src/spdx/parser/rdf/package_parser.py +++ b/src/spdx/parser/rdf/package_parser.py @@ -40,38 +40,55 @@ def parse_package(package_node: URIRef, graph: Graph, doc_namespace: str) -> Pac logger = Logger() spdx_id = parse_spdx_id(package_node, doc_namespace, graph) name = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.name) - download_location = parse_literal_or_no_assertion_or_none(logger, graph, package_node, - SPDX_NAMESPACE.downloadLocation) + download_location = parse_literal_or_no_assertion_or_none( + logger, graph, package_node, SPDX_NAMESPACE.downloadLocation + ) checksums = [] - for (_, _, checksum_node) in graph.triples((package_node, SPDX_NAMESPACE.checksum, None)): + for _, _, checksum_node in graph.triples((package_node, SPDX_NAMESPACE.checksum, None)): checksums.append(parse_checksum(checksum_node, graph)) version_info = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.versionInfo) package_file_name = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.packageFileName) - supplier = parse_literal_or_no_assertion_or_none(logger, graph, package_node, SPDX_NAMESPACE.supplier, - parsing_method=ActorParser.parse_actor) - originator = parse_literal_or_no_assertion_or_none(logger, graph, package_node, SPDX_NAMESPACE.originator, - parsing_method=ActorParser.parse_actor) - verification_code = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.packageVerificationCode, - parsing_method=lambda x: parse_package_verification_code(x, graph)) + supplier = parse_literal_or_no_assertion_or_none( + logger, graph, package_node, SPDX_NAMESPACE.supplier, parsing_method=ActorParser.parse_actor + ) + originator = parse_literal_or_no_assertion_or_none( + logger, graph, package_node, SPDX_NAMESPACE.originator, parsing_method=ActorParser.parse_actor + ) + verification_code = parse_literal( + logger, + graph, + package_node, + SPDX_NAMESPACE.packageVerificationCode, + parsing_method=lambda x: parse_package_verification_code(x, graph), + ) external_package_refs = [] - for (_, _, external_package_ref_node) in graph.triples((package_node, SPDX_NAMESPACE.externalRef, None)): + for _, _, external_package_ref_node in graph.triples((package_node, SPDX_NAMESPACE.externalRef, None)): external_package_refs.append(parse_external_package_ref(external_package_ref_node, graph, doc_namespace)) files_analyzed = bool(graph.value(package_node, SPDX_NAMESPACE.filesAnalyzed, default=True)) license_concluded = parse_literal_or_no_assertion_or_none( - logger, graph, package_node, SPDX_NAMESPACE.licenseConcluded, - parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace)) + logger, + graph, + package_node, + SPDX_NAMESPACE.licenseConcluded, + parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace), + ) license_declared = parse_literal_or_no_assertion_or_none( - logger, graph, package_node, SPDX_NAMESPACE.licenseDeclared, - parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace)) + logger, + graph, + package_node, + SPDX_NAMESPACE.licenseDeclared, + parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace), + ) license_info_from_files = [] - for (_, _, license_info_from_files_node) in graph.triples( - (package_node, SPDX_NAMESPACE.licenseInfoFromFiles, None)): + for _, _, license_info_from_files_node in graph.triples((package_node, SPDX_NAMESPACE.licenseInfoFromFiles, None)): license_info_from_files.append( - get_correctly_typed_value(logger, license_info_from_files_node, - lambda x: parse_license_expression(x, graph, doc_namespace))) + get_correctly_typed_value( + logger, license_info_from_files_node, lambda x: parse_license_expression(x, graph, doc_namespace) + ) + ) license_comment = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.licenseComments) comment = parse_literal(logger, graph, package_node, RDFS.comment) summary = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.summary) @@ -79,55 +96,76 @@ def parse_package(package_node: URIRef, graph: Graph, doc_namespace: str) -> Pac copyright_text = parse_literal_or_no_assertion_or_none(logger, graph, package_node, SPDX_NAMESPACE.copyrightText) source_info = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.sourceInfo) primary_package_purpose = parse_literal( - logger, graph, package_node, SPDX_NAMESPACE.primaryPackagePurpose, - parsing_method=lambda x: parse_enum_value(x, PackagePurpose, SPDX_NAMESPACE.purpose_)) + logger, + graph, + package_node, + SPDX_NAMESPACE.primaryPackagePurpose, + parsing_method=lambda x: parse_enum_value(x, PackagePurpose, SPDX_NAMESPACE.purpose_), + ) homepage = parse_literal(logger, graph, package_node, DOAP.homepage) attribution_texts = [] - for (_, _, attribution_text_literal) in graph.triples((package_node, SPDX_NAMESPACE.attributionText, None)): + for _, _, attribution_text_literal in graph.triples((package_node, SPDX_NAMESPACE.attributionText, None)): attribution_texts.append(attribution_text_literal.toPython()) - release_date = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.releaseDate, - parsing_method=datetime_from_str) + release_date = parse_literal( + logger, graph, package_node, SPDX_NAMESPACE.releaseDate, parsing_method=datetime_from_str + ) built_date = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.builtDate, parsing_method=datetime_from_str) - valid_until_date = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.validUntilDate, - parsing_method=datetime_from_str) + valid_until_date = parse_literal( + logger, graph, package_node, SPDX_NAMESPACE.validUntilDate, parsing_method=datetime_from_str + ) raise_parsing_error_if_logger_has_messages(logger, "Package") - package = construct_or_raise_parsing_error(Package, - dict(name=name, spdx_id=spdx_id, download_location=download_location, - version=version_info, file_name=package_file_name, - supplier=supplier, originator=originator, - files_analyzed=files_analyzed, - verification_code=verification_code, - checksums=checksums, homepage=homepage, - source_info=source_info, - license_concluded=license_concluded, - license_info_from_files=license_info_from_files, - license_declared=license_declared, - license_comment=license_comment, - copyright_text=copyright_text, summary=summary, - description=description, comment=comment, - external_references=external_package_refs, - attribution_texts=attribution_texts, - primary_package_purpose=primary_package_purpose, - release_date=release_date, built_date=built_date, - valid_until_date=valid_until_date)) + package = construct_or_raise_parsing_error( + Package, + dict( + name=name, + spdx_id=spdx_id, + download_location=download_location, + version=version_info, + file_name=package_file_name, + supplier=supplier, + originator=originator, + files_analyzed=files_analyzed, + verification_code=verification_code, + checksums=checksums, + homepage=homepage, + source_info=source_info, + license_concluded=license_concluded, + license_info_from_files=license_info_from_files, + license_declared=license_declared, + license_comment=license_comment, + copyright_text=copyright_text, + summary=summary, + description=description, + comment=comment, + external_references=external_package_refs, + attribution_texts=attribution_texts, + primary_package_purpose=primary_package_purpose, + release_date=release_date, + built_date=built_date, + valid_until_date=valid_until_date, + ), + ) return package -def parse_package_verification_code(package_verification_code_node: URIRef, graph: Graph) -> Optional[ - PackageVerificationCode]: +def parse_package_verification_code( + package_verification_code_node: URIRef, graph: Graph +) -> Optional[PackageVerificationCode]: logger = Logger() value = parse_literal(logger, graph, package_verification_code_node, SPDX_NAMESPACE.packageVerificationCodeValue) excluded_files = [] - for (_, _, excluded_file_literal) in graph.triples( - (package_verification_code_node, SPDX_NAMESPACE.packageVerificationCodeExcludedFile, None)): + for _, _, excluded_file_literal in graph.triples( + (package_verification_code_node, SPDX_NAMESPACE.packageVerificationCodeExcludedFile, None) + ): excluded_files.append(excluded_file_literal.toPython()) raise_parsing_error_if_logger_has_messages(logger, "PackageVerificationCode") - package_verification_code = construct_or_raise_parsing_error(PackageVerificationCode, dict(value=value, - excluded_files=excluded_files)) + package_verification_code = construct_or_raise_parsing_error( + PackageVerificationCode, dict(value=value, excluded_files=excluded_files) + ) return package_verification_code @@ -135,16 +173,25 @@ def parse_external_package_ref(external_package_ref_node: URIRef, graph: Graph, logger = Logger() ref_locator = parse_literal(logger, graph, external_package_ref_node, SPDX_NAMESPACE.referenceLocator) ref_category = parse_literal( - logger, graph, external_package_ref_node, SPDX_NAMESPACE.referenceCategory, - parsing_method=lambda x: parse_enum_value(x, ExternalPackageRefCategory, SPDX_NAMESPACE.referenceCategory_)) - ref_type = parse_literal(logger, graph, external_package_ref_node, SPDX_NAMESPACE.referenceType, - parsing_method=lambda x: parse_external_package_ref_type(x, doc_namespace)) + logger, + graph, + external_package_ref_node, + SPDX_NAMESPACE.referenceCategory, + parsing_method=lambda x: parse_enum_value(x, ExternalPackageRefCategory, SPDX_NAMESPACE.referenceCategory_), + ) + ref_type = parse_literal( + logger, + graph, + external_package_ref_node, + SPDX_NAMESPACE.referenceType, + parsing_method=lambda x: parse_external_package_ref_type(x, doc_namespace), + ) comment = parse_literal(logger, graph, external_package_ref_node, RDFS.comment) raise_parsing_error_if_logger_has_messages(logger, "ExternalPackageRef") - external_package_ref = construct_or_raise_parsing_error(ExternalPackageRef, - dict(category=ref_category, reference_type=ref_type, - locator=ref_locator, comment=comment)) + external_package_ref = construct_or_raise_parsing_error( + ExternalPackageRef, dict(category=ref_category, reference_type=ref_type, locator=ref_locator, comment=comment) + ) return external_package_ref diff --git a/src/spdx/parser/rdf/rdf_parser.py b/src/spdx/parser/rdf/rdf_parser.py index 4794651fa..60f0bfb9f 100644 --- a/src/spdx/parser/rdf/rdf_parser.py +++ b/src/spdx/parser/rdf/rdf_parser.py @@ -44,22 +44,25 @@ def translate_graph_to_document(graph: Graph) -> Document: parsed_fields["creation_info"] = creation_info - for element, triple, parsing_method in [("packages", (None, RDF.type, SPDX_NAMESPACE.Package), parse_package), - ("files", (None, RDF.type, SPDX_NAMESPACE.File), parse_file), - ("snippets", (None, RDF.type, SPDX_NAMESPACE.Snippet), parse_snippet)]: + for element, triple, parsing_method in [ + ("packages", (None, RDF.type, SPDX_NAMESPACE.Package), parse_package), + ("files", (None, RDF.type, SPDX_NAMESPACE.File), parse_file), + ("snippets", (None, RDF.type, SPDX_NAMESPACE.Snippet), parse_snippet), + ]: elements = [] - for (element_node, _, _) in graph.triples(triple): + for element_node, _, _ in graph.triples(triple): try: elements.append(parsing_method(element_node, graph, creation_info.document_namespace)) except SPDXParsingError as err: logger.extend(err.get_messages()) parsed_fields[element] = elements - for element, triple, parsing_method in [("annotations", (None, SPDX_NAMESPACE.annotation, None), parse_annotation), - ("relationships", (None, SPDX_NAMESPACE.relationship, None), - parse_relationship)]: + for element, triple, parsing_method in [ + ("annotations", (None, SPDX_NAMESPACE.annotation, None), parse_annotation), + ("relationships", (None, SPDX_NAMESPACE.relationship, None), parse_relationship), + ]: elements = [] - for (parent_node, _, element_node) in graph.triples(triple): + for parent_node, _, element_node in graph.triples(triple): try: elements.append(parsing_method(element_node, graph, parent_node, creation_info.document_namespace)) except SPDXParsingError as err: @@ -67,7 +70,7 @@ def translate_graph_to_document(graph: Graph) -> Document: parsed_fields[element] = elements extracted_licensing_infos = [] - for (_, _, extracted_licensing_info_node) in graph.triples((None, SPDX_NAMESPACE.hasExtractedLicensingInfo, None)): + for _, _, extracted_licensing_info_node in graph.triples((None, SPDX_NAMESPACE.hasExtractedLicensingInfo, None)): try: extracted_licensing_infos.append(parse_extracted_licensing_info(extracted_licensing_info_node, graph)) except SPDXParsingError as err: diff --git a/src/spdx/parser/rdf/relationship_parser.py b/src/spdx/parser/rdf/relationship_parser.py index 313efbe44..e0bb13e17 100644 --- a/src/spdx/parser/rdf/relationship_parser.py +++ b/src/spdx/parser/rdf/relationship_parser.py @@ -22,23 +22,37 @@ from spdx.rdfschema.namespace import SPDX_NAMESPACE -def parse_relationship(relationship_node: URIRef, graph: Graph, parent_node: URIRef, - doc_namespace: str) -> Relationship: +def parse_relationship( + relationship_node: URIRef, graph: Graph, parent_node: URIRef, doc_namespace: str +) -> Relationship: logger = Logger() spdx_element_id = parse_spdx_id(parent_node, doc_namespace, graph) relationship_type = parse_literal( - logger, graph, relationship_node, SPDX_NAMESPACE.relationshipType, - parsing_method=lambda x: parse_enum_value(x, RelationshipType, SPDX_NAMESPACE.relationshipType_)) + logger, + graph, + relationship_node, + SPDX_NAMESPACE.relationshipType, + parsing_method=lambda x: parse_enum_value(x, RelationshipType, SPDX_NAMESPACE.relationshipType_), + ) related_spdx_element = parse_literal_or_no_assertion_or_none( - logger, graph, relationship_node, SPDX_NAMESPACE.relatedSpdxElement, - parsing_method=lambda x: parse_spdx_id(x, doc_namespace, graph)) + logger, + graph, + relationship_node, + SPDX_NAMESPACE.relatedSpdxElement, + parsing_method=lambda x: parse_spdx_id(x, doc_namespace, graph), + ) comment = parse_literal(logger, graph, relationship_node, RDFS.comment) raise_parsing_error_if_logger_has_messages(logger, "Relationship") - relationship = construct_or_raise_parsing_error(Relationship, - dict(spdx_element_id=spdx_element_id, - relationship_type=relationship_type, - related_spdx_element_id=related_spdx_element, comment=comment)) + relationship = construct_or_raise_parsing_error( + Relationship, + dict( + spdx_element_id=spdx_element_id, + relationship_type=relationship_type, + related_spdx_element_id=related_spdx_element, + comment=comment, + ), + ) return relationship diff --git a/src/spdx/parser/rdf/snippet_parser.py b/src/spdx/parser/rdf/snippet_parser.py index 316ba2e76..a21a5a1cf 100644 --- a/src/spdx/parser/rdf/snippet_parser.py +++ b/src/spdx/parser/rdf/snippet_parser.py @@ -36,42 +36,60 @@ def parse_snippet(snippet_node: URIRef, graph: Graph, doc_namespace: str) -> Sni file_spdx_id = parse_spdx_id(file_spdx_id_uri, doc_namespace, graph) byte_range = None line_range = None - for (_, _, start_end_pointer) in graph.triples((snippet_node, SPDX_NAMESPACE.range, None)): - parsed_range = apply_parsing_method_or_log_error(logger, start_end_pointer, - parsing_method=lambda x: parse_ranges(x, graph)) + for _, _, start_end_pointer in graph.triples((snippet_node, SPDX_NAMESPACE.range, None)): + parsed_range = apply_parsing_method_or_log_error( + logger, start_end_pointer, parsing_method=lambda x: parse_ranges(x, graph) + ) byte_range, line_range = set_range_or_log_error(byte_range, line_range, logger, parsed_range) license_concluded = parse_literal_or_no_assertion_or_none( - logger, graph, snippet_node, SPDX_NAMESPACE.licenseConcluded, - parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace)) + logger, + graph, + snippet_node, + SPDX_NAMESPACE.licenseConcluded, + parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace), + ) license_info_in_snippet = [] - for (_, _, license_info_in_snippet_node) in graph.triples( - (snippet_node, SPDX_NAMESPACE.licenseInfoInSnippet, None)): + for _, _, license_info_in_snippet_node in graph.triples((snippet_node, SPDX_NAMESPACE.licenseInfoInSnippet, None)): license_info_in_snippet.append( - get_correctly_typed_value(logger, license_info_in_snippet_node, - lambda x: parse_license_expression(x, graph, doc_namespace))) + get_correctly_typed_value( + logger, license_info_in_snippet_node, lambda x: parse_license_expression(x, graph, doc_namespace) + ) + ) license_comment = parse_literal(logger, graph, snippet_node, SPDX_NAMESPACE.licenseComments) copyright_text = parse_literal_or_no_assertion_or_none(logger, graph, snippet_node, SPDX_NAMESPACE.copyrightText) comment = parse_literal(logger, graph, snippet_node, RDFS.comment) name = parse_literal(logger, graph, snippet_node, SPDX_NAMESPACE.name) attribution_texts = [] - for (_, _, attribution_text_literal) in graph.triples((snippet_node, SPDX_NAMESPACE.attributionText, None)): + for _, _, attribution_text_literal in graph.triples((snippet_node, SPDX_NAMESPACE.attributionText, None)): attribution_texts.append(attribution_text_literal.toPython()) raise_parsing_error_if_logger_has_messages(logger, "Snippet") - snippet = construct_or_raise_parsing_error(Snippet, - dict(spdx_id=spdx_id, file_spdx_id=file_spdx_id, byte_range=byte_range, - line_range=line_range, license_concluded=license_concluded, - license_info_in_snippet=license_info_in_snippet, - license_comment=license_comment, - copyright_text=copyright_text, comment=comment, name=name, - attribution_texts=attribution_texts)) + snippet = construct_or_raise_parsing_error( + Snippet, + dict( + spdx_id=spdx_id, + file_spdx_id=file_spdx_id, + byte_range=byte_range, + line_range=line_range, + license_concluded=license_concluded, + license_info_in_snippet=license_info_in_snippet, + license_comment=license_comment, + copyright_text=copyright_text, + comment=comment, + name=name, + attribution_texts=attribution_texts, + ), + ) return snippet def set_range_or_log_error( - byte_range: Optional[Tuple[int, int]], line_range: Optional[Tuple[int, int]], logger: Logger, - parsed_range: Dict[str, Tuple[int, int]]) -> Tuple[Optional[Tuple[int, int]], Optional[Tuple[int, int]]]: + byte_range: Optional[Tuple[int, int]], + line_range: Optional[Tuple[int, int]], + logger: Logger, + parsed_range: Dict[str, Tuple[int, int]], +) -> Tuple[Optional[Tuple[int, int]], Optional[Tuple[int, int]]]: if not parsed_range: return byte_range, line_range if "ByteOffsetPointer" in parsed_range.keys() and not byte_range: @@ -96,8 +114,7 @@ def parse_ranges(start_end_pointer: URIRef, graph: Graph) -> Dict[str, Tuple[int range_values["startPointer"] = parse_range_value(graph, start_pointer_node, POINTER_MATCHING[start_pointer_type]) range_values["endPointer"] = parse_range_value(graph, end_pointer_node, POINTER_MATCHING[end_pointer_type]) - return {str(start_pointer_type.fragment): ( - range_values["startPointer"], range_values["endPointer"])} + return {str(start_pointer_type.fragment): (range_values["startPointer"], range_values["endPointer"])} def get_pointer_type(graph: Graph, pointer: URIRef, start_end_pointer: URIRef) -> Tuple[URIRef, URIRef]: @@ -113,7 +130,8 @@ def get_pointer_type(graph: Graph, pointer: URIRef, start_end_pointer: URIRef) - POINTER_MATCHING = { POINTER_NAMESPACE.ByteOffsetPointer: POINTER_NAMESPACE.offset, - POINTER_NAMESPACE.LineCharPointer: POINTER_NAMESPACE.lineNumber} + POINTER_NAMESPACE.LineCharPointer: POINTER_NAMESPACE.lineNumber, +} def parse_range_value(graph: Graph, pointer_node: Node, predicate: URIRef) -> Optional[int]: diff --git a/src/spdx/parser/tagvalue/helper_methods.py b/src/spdx/parser/tagvalue/helper_methods.py index cd5329b49..3814b3d29 100644 --- a/src/spdx/parser/tagvalue/helper_methods.py +++ b/src/spdx/parser/tagvalue/helper_methods.py @@ -54,13 +54,16 @@ def parse_checksum(checksum_str: str) -> Checksum: return checksum -def set_value(parsed_value: YaccProduction, dict_to_fill: Dict[str, Any], argument_name: Optional[str] = None, - method_to_apply: Callable = lambda x: x): +def set_value( + parsed_value: YaccProduction, + dict_to_fill: Dict[str, Any], + argument_name: Optional[str] = None, + method_to_apply: Callable = lambda x: x, +): if not argument_name: argument_name = get_property_name(parsed_value[1]) if argument_name in dict_to_fill: - dict_to_fill["logger"].append( - f"Multiple values for {parsed_value[1]} found. Line: {parsed_value.lineno(1)}") + dict_to_fill["logger"].append(f"Multiple values for {parsed_value[1]} found. Line: {parsed_value.lineno(1)}") return try: dict_to_fill[argument_name] = method_to_apply(parsed_value[2]) @@ -82,31 +85,54 @@ def get_property_name(tag: str): # This mapping is not complete as we only list the values which can be parsed by a generic method and don't need any # individual logic. TAG_DATA_MODEL_FIELD = { - "SPDXVersion": (CreationInfo, "spdx_version"), "DataLicense": (CreationInfo, "data_license"), - "DocumentName": (CreationInfo, "name"), "DocumentComment": (CreationInfo, "document_comment"), - "DocumentNamespace": (CreationInfo, "document_namespace"), "Creator": (CreationInfo, "creator"), - "Created": (CreationInfo, "created"), "CreatorComment": (CreationInfo, "creator_comment"), + "SPDXVersion": (CreationInfo, "spdx_version"), + "DataLicense": (CreationInfo, "data_license"), + "DocumentName": (CreationInfo, "name"), + "DocumentComment": (CreationInfo, "document_comment"), + "DocumentNamespace": (CreationInfo, "document_namespace"), + "Creator": (CreationInfo, "creator"), + "Created": (CreationInfo, "created"), + "CreatorComment": (CreationInfo, "creator_comment"), "LicenseListVersion": (CreationInfo, "license_list_version"), "ExternalDocumentRef": (CreationInfo, "external_document_refs"), - "FileName": (File, "name"), "FileType": (File, "file_type"), "FileChecksum": (File, "checksums"), - "FileNotice": (File, "notice"), "FileCopyrightText": (File, "copyright_text"), - "LicenseComments": (File, "license_comment"), "FileComment": (File, "comment"), - "LicenseConcluded": (File, "license_concluded"), "LicenseDeclared": (File, "license_declared"), - "PackageName": (Package, "name"), "PackageComment": (Package, "comment"), - "PackageCopyrightText": (Package, "copyright_text"), "PackageLicenseComments": (Package, "license_comment"), - "PackageLicenseDeclared": (Package, "license_declared"), "PackageLicenseConcluded": (Package, "license_concluded"), - "PackageFileName": (Package, "file_name"), "PackageVersion": (Package, "version"), - "PackageDownloadLocation": (Package, "download_location"), "PackageSummary": (Package, "summary"), - "PackageSourceInfo": (Package, "source_info"), "PackageSupplier": (Package, "supplier"), - "PackageOriginator": (Package, "originator"), "PackageDescription": (Package, "description"), + "FileName": (File, "name"), + "FileType": (File, "file_type"), + "FileChecksum": (File, "checksums"), + "FileNotice": (File, "notice"), + "FileCopyrightText": (File, "copyright_text"), + "LicenseComments": (File, "license_comment"), + "FileComment": (File, "comment"), + "LicenseConcluded": (File, "license_concluded"), + "LicenseDeclared": (File, "license_declared"), + "PackageName": (Package, "name"), + "PackageComment": (Package, "comment"), + "PackageCopyrightText": (Package, "copyright_text"), + "PackageLicenseComments": (Package, "license_comment"), + "PackageLicenseDeclared": (Package, "license_declared"), + "PackageLicenseConcluded": (Package, "license_concluded"), + "PackageFileName": (Package, "file_name"), + "PackageVersion": (Package, "version"), + "PackageDownloadLocation": (Package, "download_location"), + "PackageSummary": (Package, "summary"), + "PackageSourceInfo": (Package, "source_info"), + "PackageSupplier": (Package, "supplier"), + "PackageOriginator": (Package, "originator"), + "PackageDescription": (Package, "description"), "PackageHomePage": (Package, "homepage"), - "SnippetSPDXID": (Snippet, "spdx_id"), "SnippetFromFileSPDXID": (Snippet, "file_spdx_id"), + "SnippetSPDXID": (Snippet, "spdx_id"), + "SnippetFromFileSPDXID": (Snippet, "file_spdx_id"), "SnippetName": (Snippet, "name"), - "SnippetComment": (Snippet, "comment"), "SnippetCopyrightText": (Snippet, "copyright_text"), - "SnippetLicenseComments": (Snippet, "license_comment"), "SnippetLicenseConcluded": (Snippet, "license_concluded"), - "SnippetByteRange": (Snippet, "byte_range"), "SnippetLineRange": (Snippet, "line_range"), + "SnippetComment": (Snippet, "comment"), + "SnippetCopyrightText": (Snippet, "copyright_text"), + "SnippetLicenseComments": (Snippet, "license_comment"), + "SnippetLicenseConcluded": (Snippet, "license_concluded"), + "SnippetByteRange": (Snippet, "byte_range"), + "SnippetLineRange": (Snippet, "line_range"), "Annotator": (Annotation, "annotator"), - "SPDXREF": (Annotation, "spdx_id"), "AnnotationComment": (Annotation, "annotation_comment"), - "LicenseID": (ExtractedLicensingInfo, "license_id"), "ExtractedText": (ExtractedLicensingInfo, "extracted_text"), - "LicenseComment": (ExtractedLicensingInfo, "comment"), "LicenseName": (ExtractedLicensingInfo, "license_name") + "SPDXREF": (Annotation, "spdx_id"), + "AnnotationComment": (Annotation, "annotation_comment"), + "LicenseID": (ExtractedLicensingInfo, "license_id"), + "ExtractedText": (ExtractedLicensingInfo, "extracted_text"), + "LicenseComment": (ExtractedLicensingInfo, "comment"), + "LicenseName": (ExtractedLicensingInfo, "license_name"), } diff --git a/src/spdx/parser/tagvalue/lexer.py b/src/spdx/parser/tagvalue/lexer.py index 8a103833f..319909717 100644 --- a/src/spdx/parser/tagvalue/lexer.py +++ b/src/spdx/parser/tagvalue/lexer.py @@ -97,20 +97,20 @@ class SPDXLexer: "SnippetLineRange": "SNIPPET_LINE_RANGE", # Common fields "NOASSERTION": "NO_ASSERTION", - "NONE": "NONE" + "NONE": "NONE", } states = (("text", "exclusive"),) tokens = [ - "TEXT", - "TOOL_VALUE", - "UNKNOWN_TAG", - "ORGANIZATION_VALUE", - "PERSON_VALUE", - "ISO8601_DATE", - "LINE", - "CHECKSUM" - ] + list(reserved.values()) + "TEXT", + "TOOL_VALUE", + "UNKNOWN_TAG", + "ORGANIZATION_VALUE", + "PERSON_VALUE", + "ISO8601_DATE", + "LINE", + "CHECKSUM", + ] + list(reserved.values()) def __init__(self): self.lexer = None @@ -123,7 +123,7 @@ def t_text(self, t): @TOKEN(r"\s*") def t_text_end(self, t): t.type = "TEXT" - t.value = t.lexer.lexdata[t.lexer.text_start: t.lexer.lexpos] + t.value = t.lexer.lexdata[t.lexer.text_start : t.lexer.lexpos] t.lexer.lineno += t.value.count("\n") t.value = t.value.strip() t.lexer.begin("INITIAL") @@ -137,7 +137,8 @@ def t_text_error(self, t): print("Lexer error in text state") @TOKEN( - r":\s*(ADLER32|BLAKE2b-256|BLAKE2b-384|BLAKE2b-512|BLAKE3|MD2|MD4|MD5|MD6|SHA1|SHA224|SHA256|SHA384|SHA512|SHA3-256|SHA3-384|SHA3-512):\s*([a-f0-9]*)") + r":\s*(ADLER32|BLAKE2b-256|BLAKE2b-384|BLAKE2b-512|BLAKE3|MD2|MD4|MD5|MD6|SHA1|SHA224|SHA256|SHA384|SHA512|SHA3-256|SHA3-384|SHA3-512):\s*([a-f0-9]*)" + ) def t_CHECKSUM(self, t): t.value = t.value[1:].strip() return t diff --git a/src/spdx/parser/tagvalue/parser.py b/src/spdx/parser/tagvalue/parser.py index d649695f3..8f4ec2790 100644 --- a/src/spdx/parser/tagvalue/parser.py +++ b/src/spdx/parser/tagvalue/parser.py @@ -48,10 +48,22 @@ ) from spdx.parser.tagvalue.lexer import SPDXLexer -CLASS_MAPPING = dict(File="files", Annotation="annotations", Relationship="relationships", Snippet="snippets", - Package="packages", ExtractedLicensingInfo="extracted_licensing_info") -ELEMENT_EXPECTED_START_TAG = dict(File="FileName", Annotation="Annotator", Relationship="Relationship", - Snippet="SnippetSPDXID", Package="PackageName", ExtractedLicensingInfo="LicenseID") +CLASS_MAPPING = dict( + File="files", + Annotation="annotations", + Relationship="relationships", + Snippet="snippets", + Package="packages", + ExtractedLicensingInfo="extracted_licensing_info", +) +ELEMENT_EXPECTED_START_TAG = dict( + File="FileName", + Annotation="Annotator", + Relationship="Relationship", + Snippet="SnippetSPDXID", + Package="PackageName", + ExtractedLicensingInfo="LicenseID", +) class Parser: @@ -84,7 +96,7 @@ def p_start_attrib(self, p): @grammar_rule( "attrib : spdx_version\n| spdx_id\n| data_license\n| doc_name\n| document_comment\n| document_namespace\n| " "creator\n| created\n| creator_comment\n| license_list_version\n| ext_doc_ref\n" - # attributes for file + # attributes for file "| file_name\n| file_type\n| file_checksum\n| file_license_concluded\n| file_license_info\n" "| file_copyright_text\n| file_license_comment\n| file_attribution_text\n| file_notice\n| file_comment\n" "| file_contributor\n" @@ -104,83 +116,91 @@ def p_start_attrib(self, p): "| pkg_external_ref\n| primary_package_purpose\n| built_date\n| release_date\n| valid_until_date\n" # attributes for extracted licensing info "| license_id\n| extracted_text\n| license_name\n| license_cross_ref\n| lic_comment\n" - "| unknown_tag ") + "| unknown_tag " + ) def p_attrib(self, p): pass # general parsing methods - @grammar_rule("license_id : LICENSE_ID error\n license_cross_ref : LICENSE_CROSS_REF error\n " - "lic_comment : LICENSE_COMMENT error\n license_name : LICENSE_NAME error\n " - "extracted_text : LICENSE_TEXT error\n " - "file_name : FILE_NAME error\n file_contributor : FILE_CONTRIBUTOR error\n " - "file_notice : FILE_NOTICE error\n file_copyright_text : FILE_COPYRIGHT_TEXT error\n " - "file_license_comment : FILE_LICENSE_COMMENT error\n " - "file_license_info : FILE_LICENSE_INFO error\n file_comment : FILE_COMMENT error\n " - "file_checksum : FILE_CHECKSUM error\n file_license_concluded : FILE_LICENSE_CONCLUDED error\n " - "file_type : FILE_TYPE error\n file_attribution_text : FILE_ATTRIBUTION_TEXT error\n " - "package_name : PKG_NAME error\n pkg_attribution_text : PKG_ATTRIBUTION_TEXT error\n " - "description : PKG_DESCRIPTION error\n pkg_comment : PKG_COMMENT error\n " - "summary : PKG_SUMMARY error\n pkg_copyright_text : PKG_COPYRIGHT_TEXT error\n " - "pkg_external_ref : PKG_EXTERNAL_REF error\n pkg_license_comment : PKG_LICENSE_COMMENT error\n " - "pkg_license_declared : PKG_LICENSE_DECLARED error\n pkg_license_info : PKG_LICENSE_INFO error \n " - "pkg_license_concluded : PKG_LICENSE_CONCLUDED error\n source_info : PKG_SOURCE_INFO error\n " - "homepage : PKG_HOMEPAGE error\n pkg_checksum : PKG_CHECKSUM error\n " - "verification_code : PKG_VERIFICATION_CODE error\n originator : PKG_ORIGINATOR error\n " - "download_location : PKG_DOWNLOAD_LOCATION error\n files_analyzed : PKG_FILES_ANALYZED error\n " - "supplier : PKG_SUPPLIER error\n pkg_file_name : PKG_FILE_NAME error\n " - "package_version : PKG_VERSION error\n primary_package_purpose : PRIMARY_PACKAGE_PURPOSE error\n " - "built_date : BUILT_DATE error\n release_date : RELEASE_DATE error\n " - "valid_until_date : VALID_UNTIL_DATE error\n snippet_spdx_id : SNIPPET_SPDX_ID error\n " - "snippet_name : SNIPPET_NAME error\n snippet_comment : SNIPPET_COMMENT error\n " - "snippet_attribution_text : SNIPPET_ATTRIBUTION_TEXT error\n " - "snippet_copyright_text : SNIPPET_COPYRIGHT_TEXT error\n " - "snippet_license_comment : SNIPPET_LICENSE_COMMENT error\n file_spdx_id : SNIPPET_FILE_SPDXID error\n " - "snippet_license_concluded : SNIPPET_LICENSE_CONCLUDED error\n " - "snippet_license_info : SNIPPET_LICENSE_INFO error\n " - "snippet_byte_range : SNIPPET_BYTE_RANGE error\n snippet_line_range : SNIPPET_LINE_RANGE error\n " - "annotator : ANNOTATOR error\n annotation_date : ANNOTATION_DATE error\n " - "annotation_comment : ANNOTATION_COMMENT error\n annotation_type : ANNOTATION_TYPE error\n " - "annotation_spdx_id : ANNOTATION_SPDX_ID error\n relationship : RELATIONSHIP error") + @grammar_rule( + "license_id : LICENSE_ID error\n license_cross_ref : LICENSE_CROSS_REF error\n " + "lic_comment : LICENSE_COMMENT error\n license_name : LICENSE_NAME error\n " + "extracted_text : LICENSE_TEXT error\n " + "file_name : FILE_NAME error\n file_contributor : FILE_CONTRIBUTOR error\n " + "file_notice : FILE_NOTICE error\n file_copyright_text : FILE_COPYRIGHT_TEXT error\n " + "file_license_comment : FILE_LICENSE_COMMENT error\n " + "file_license_info : FILE_LICENSE_INFO error\n file_comment : FILE_COMMENT error\n " + "file_checksum : FILE_CHECKSUM error\n file_license_concluded : FILE_LICENSE_CONCLUDED error\n " + "file_type : FILE_TYPE error\n file_attribution_text : FILE_ATTRIBUTION_TEXT error\n " + "package_name : PKG_NAME error\n pkg_attribution_text : PKG_ATTRIBUTION_TEXT error\n " + "description : PKG_DESCRIPTION error\n pkg_comment : PKG_COMMENT error\n " + "summary : PKG_SUMMARY error\n pkg_copyright_text : PKG_COPYRIGHT_TEXT error\n " + "pkg_external_ref : PKG_EXTERNAL_REF error\n pkg_license_comment : PKG_LICENSE_COMMENT error\n " + "pkg_license_declared : PKG_LICENSE_DECLARED error\n pkg_license_info : PKG_LICENSE_INFO error \n " + "pkg_license_concluded : PKG_LICENSE_CONCLUDED error\n source_info : PKG_SOURCE_INFO error\n " + "homepage : PKG_HOMEPAGE error\n pkg_checksum : PKG_CHECKSUM error\n " + "verification_code : PKG_VERIFICATION_CODE error\n originator : PKG_ORIGINATOR error\n " + "download_location : PKG_DOWNLOAD_LOCATION error\n files_analyzed : PKG_FILES_ANALYZED error\n " + "supplier : PKG_SUPPLIER error\n pkg_file_name : PKG_FILE_NAME error\n " + "package_version : PKG_VERSION error\n primary_package_purpose : PRIMARY_PACKAGE_PURPOSE error\n " + "built_date : BUILT_DATE error\n release_date : RELEASE_DATE error\n " + "valid_until_date : VALID_UNTIL_DATE error\n snippet_spdx_id : SNIPPET_SPDX_ID error\n " + "snippet_name : SNIPPET_NAME error\n snippet_comment : SNIPPET_COMMENT error\n " + "snippet_attribution_text : SNIPPET_ATTRIBUTION_TEXT error\n " + "snippet_copyright_text : SNIPPET_COPYRIGHT_TEXT error\n " + "snippet_license_comment : SNIPPET_LICENSE_COMMENT error\n file_spdx_id : SNIPPET_FILE_SPDXID error\n " + "snippet_license_concluded : SNIPPET_LICENSE_CONCLUDED error\n " + "snippet_license_info : SNIPPET_LICENSE_INFO error\n " + "snippet_byte_range : SNIPPET_BYTE_RANGE error\n snippet_line_range : SNIPPET_LINE_RANGE error\n " + "annotator : ANNOTATOR error\n annotation_date : ANNOTATION_DATE error\n " + "annotation_comment : ANNOTATION_COMMENT error\n annotation_type : ANNOTATION_TYPE error\n " + "annotation_spdx_id : ANNOTATION_SPDX_ID error\n relationship : RELATIONSHIP error" + ) def p_current_element_error(self, p): if p[1] in ELEMENT_EXPECTED_START_TAG.values(): self.initialize_new_current_element(TAG_DATA_MODEL_FIELD[p[1]][0]) self.current_element["logger"].append( - f"Error while parsing {p[1]}: Token did not match specified grammar rule. Line: {p.lineno(1)}") - - @grammar_rule("license_name : LICENSE_NAME line_or_no_assertion\n extracted_text : LICENSE_TEXT text_or_line\n " - "lic_comment : LICENSE_COMMENT text_or_line\n license_id : LICENSE_ID LINE\n " - "file_name : FILE_NAME LINE \n file_notice : FILE_NOTICE text_or_line\n " - "file_copyright_text : FILE_COPYRIGHT_TEXT line_or_no_assertion_or_none\n " - "file_license_comment : FILE_LICENSE_COMMENT text_or_line\n " - "file_comment : FILE_COMMENT text_or_line\n " - "file_license_concluded : FILE_LICENSE_CONCLUDED license_or_no_assertion_or_none\n " - "package_name : PKG_NAME LINE\n description : PKG_DESCRIPTION text_or_line\n " - "summary : PKG_SUMMARY text_or_line\n source_info : PKG_SOURCE_INFO text_or_line\n " - "homepage : PKG_HOMEPAGE line_or_no_assertion_or_none\n " - "download_location : PKG_DOWNLOAD_LOCATION line_or_no_assertion_or_none\n " - "originator : PKG_ORIGINATOR actor_or_no_assertion\n supplier : PKG_SUPPLIER actor_or_no_assertion\n " - "pkg_comment : PKG_COMMENT text_or_line\n " - "pkg_copyright_text : PKG_COPYRIGHT_TEXT line_or_no_assertion_or_none\n " - "pkg_license_declared : PKG_LICENSE_DECLARED license_or_no_assertion_or_none\n " - "pkg_file_name : PKG_FILE_NAME LINE\n " - "pkg_license_concluded : PKG_LICENSE_CONCLUDED license_or_no_assertion_or_none\n " - "package_version : PKG_VERSION LINE\n pkg_license_comment : PKG_LICENSE_COMMENT text_or_line\n " - "snippet_spdx_id : SNIPPET_SPDX_ID LINE\n snippet_name : SNIPPET_NAME LINE\n " - "snippet_comment : SNIPPET_COMMENT text_or_line\n " - "snippet_copyright_text : SNIPPET_COPYRIGHT_TEXT line_or_no_assertion_or_none\n " - "snippet_license_comment : SNIPPET_LICENSE_COMMENT text_or_line\n " - "file_spdx_id : SNIPPET_FILE_SPDXID LINE\n " - "snippet_license_concluded : SNIPPET_LICENSE_CONCLUDED license_or_no_assertion_or_none\n " - "annotation_spdx_id : ANNOTATION_SPDX_ID LINE\n " - "annotation_comment : ANNOTATION_COMMENT text_or_line") + f"Error while parsing {p[1]}: Token did not match specified grammar rule. Line: {p.lineno(1)}" + ) + + @grammar_rule( + "license_name : LICENSE_NAME line_or_no_assertion\n extracted_text : LICENSE_TEXT text_or_line\n " + "lic_comment : LICENSE_COMMENT text_or_line\n license_id : LICENSE_ID LINE\n " + "file_name : FILE_NAME LINE \n file_notice : FILE_NOTICE text_or_line\n " + "file_copyright_text : FILE_COPYRIGHT_TEXT line_or_no_assertion_or_none\n " + "file_license_comment : FILE_LICENSE_COMMENT text_or_line\n " + "file_comment : FILE_COMMENT text_or_line\n " + "file_license_concluded : FILE_LICENSE_CONCLUDED license_or_no_assertion_or_none\n " + "package_name : PKG_NAME LINE\n description : PKG_DESCRIPTION text_or_line\n " + "summary : PKG_SUMMARY text_or_line\n source_info : PKG_SOURCE_INFO text_or_line\n " + "homepage : PKG_HOMEPAGE line_or_no_assertion_or_none\n " + "download_location : PKG_DOWNLOAD_LOCATION line_or_no_assertion_or_none\n " + "originator : PKG_ORIGINATOR actor_or_no_assertion\n supplier : PKG_SUPPLIER actor_or_no_assertion\n " + "pkg_comment : PKG_COMMENT text_or_line\n " + "pkg_copyright_text : PKG_COPYRIGHT_TEXT line_or_no_assertion_or_none\n " + "pkg_license_declared : PKG_LICENSE_DECLARED license_or_no_assertion_or_none\n " + "pkg_file_name : PKG_FILE_NAME LINE\n " + "pkg_license_concluded : PKG_LICENSE_CONCLUDED license_or_no_assertion_or_none\n " + "package_version : PKG_VERSION LINE\n pkg_license_comment : PKG_LICENSE_COMMENT text_or_line\n " + "snippet_spdx_id : SNIPPET_SPDX_ID LINE\n snippet_name : SNIPPET_NAME LINE\n " + "snippet_comment : SNIPPET_COMMENT text_or_line\n " + "snippet_copyright_text : SNIPPET_COPYRIGHT_TEXT line_or_no_assertion_or_none\n " + "snippet_license_comment : SNIPPET_LICENSE_COMMENT text_or_line\n " + "file_spdx_id : SNIPPET_FILE_SPDXID LINE\n " + "snippet_license_concluded : SNIPPET_LICENSE_CONCLUDED license_or_no_assertion_or_none\n " + "annotation_spdx_id : ANNOTATION_SPDX_ID LINE\n " + "annotation_comment : ANNOTATION_COMMENT text_or_line" + ) def p_generic_value(self, p): if p[1] in ELEMENT_EXPECTED_START_TAG.values(): self.initialize_new_current_element(TAG_DATA_MODEL_FIELD[p[1]][0]) if self.check_that_current_element_matches_class_for_value(TAG_DATA_MODEL_FIELD[p[1]][0], p.lineno(1)): set_value(p, self.current_element) - @grammar_rule("unknown_tag : UNKNOWN_TAG text_or_line\n | UNKNOWN_TAG ISO8601_DATE\n | UNKNOWN_TAG PERSON_VALUE \n" - "| UNKNOWN_TAG") + @grammar_rule( + "unknown_tag : UNKNOWN_TAG text_or_line\n | UNKNOWN_TAG ISO8601_DATE\n | UNKNOWN_TAG PERSON_VALUE \n" + "| UNKNOWN_TAG" + ) def p_unknown_tag(self, p): self.logger.append(f"Unknown tag provided in line {p.lineno(1)}") @@ -192,8 +212,10 @@ def p_text(self, p): def p_line(self, p): p[0] = p[1] - @grammar_rule("license_or_no_assertion_or_none : NO_ASSERTION\n actor_or_no_assertion : NO_ASSERTION\n" - "line_or_no_assertion : NO_ASSERTION\n line_or_no_assertion_or_none : NO_ASSERTION") + @grammar_rule( + "license_or_no_assertion_or_none : NO_ASSERTION\n actor_or_no_assertion : NO_ASSERTION\n" + "line_or_no_assertion : NO_ASSERTION\n line_or_no_assertion_or_none : NO_ASSERTION" + ) def p_no_assertion(self, p): p[0] = SpdxNoAssertion() @@ -221,17 +243,22 @@ def p_spdx_id(self, p): # parsing methods for creation info / document level - @grammar_rule("license_list_version : LICENSE_LIST_VERSION error\n document_comment : DOC_COMMENT error\n " - "document_namespace : DOC_NAMESPACE error\n data_license : DOC_LICENSE error\n " - "doc_name : DOC_NAME error\n ext_doc_ref : EXT_DOC_REF error\n spdx_version : DOC_VERSION error\n " - "creator_comment : CREATOR_COMMENT error\n creator : CREATOR error\n created : CREATED error") + @grammar_rule( + "license_list_version : LICENSE_LIST_VERSION error\n document_comment : DOC_COMMENT error\n " + "document_namespace : DOC_NAMESPACE error\n data_license : DOC_LICENSE error\n " + "doc_name : DOC_NAME error\n ext_doc_ref : EXT_DOC_REF error\n spdx_version : DOC_VERSION error\n " + "creator_comment : CREATOR_COMMENT error\n creator : CREATOR error\n created : CREATED error" + ) def p_creation_info_value_error(self, p): self.creation_info["logger"].append( - f"Error while parsing {p[1]}: Token did not match specified grammar rule. Line: {p.lineno(1)}") + f"Error while parsing {p[1]}: Token did not match specified grammar rule. Line: {p.lineno(1)}" + ) - @grammar_rule("document_comment : DOC_COMMENT text_or_line\n document_namespace : DOC_NAMESPACE LINE\n " - "data_license : DOC_LICENSE LINE\n spdx_version : DOC_VERSION LINE\n " - "creator_comment : CREATOR_COMMENT text_or_line\n doc_name : DOC_NAME LINE") + @grammar_rule( + "document_comment : DOC_COMMENT text_or_line\n document_namespace : DOC_NAMESPACE LINE\n " + "data_license : DOC_LICENSE LINE\n spdx_version : DOC_VERSION LINE\n " + "creator_comment : CREATOR_COMMENT text_or_line\n doc_name : DOC_NAME LINE" + ) def p_generic_value_creation_info(self, p): set_value(p, self.creation_info) @@ -245,14 +272,16 @@ def p_external_document_ref(self, p): external_doc_ref_match = external_doc_ref_regex.match(p[2]) if not external_doc_ref_match: self.creation_info["logger"].append( - f"Error while parsing ExternalDocumentRef: Couldn\'t match Checksum. Line: {p.lineno(1)}") + f"Error while parsing ExternalDocumentRef: Couldn't match Checksum. Line: {p.lineno(1)}" + ) return try: document_ref_id, document_uri = external_doc_ref_match.group(1).strip().split(" ") except ValueError: self.creation_info["logger"].append( f"Error while parsing ExternalDocumentRef: Couldn't split the first part of the value into " - f"document_ref_id and document_uri. Line: {p.lineno(1)}") + f"document_ref_id and document_uri. Line: {p.lineno(1)}" + ) return checksum = parse_checksum(external_doc_ref_match.group(2).strip()) external_document_ref = ExternalDocumentRef(document_ref_id, document_uri, checksum) @@ -316,7 +345,8 @@ def p_pkg_attribution_text(self, p): self.current_element.setdefault("attribution_texts", []).append(p[2]) @grammar_rule( - "pkg_external_ref : PKG_EXTERNAL_REF LINE PKG_EXTERNAL_REF_COMMENT text_or_line\n | PKG_EXTERNAL_REF LINE") + "pkg_external_ref : PKG_EXTERNAL_REF LINE PKG_EXTERNAL_REF_COMMENT text_or_line\n | PKG_EXTERNAL_REF LINE" + ) def p_pkg_external_refs(self, p): if not self.check_that_current_element_matches_class_for_value(Package, p.lineno(1)): return @@ -324,7 +354,8 @@ def p_pkg_external_refs(self, p): category, reference_type, locator = p[2].split(" ") except ValueError: self.current_element["logger"].append( - f"Couldn't split PackageExternalRef in category, reference_type and locator. Line: {p.lineno(1)}") + f"Couldn't split PackageExternalRef in category, reference_type and locator. Line: {p.lineno(1)}" + ) return comment = None if len(p) == 5: @@ -333,14 +364,14 @@ def p_pkg_external_refs(self, p): category = ExternalPackageRefCategory[category.replace("-", "_")] except KeyError: self.current_element["logger"].append( - f"Invalid ExternalPackageRefCategory: {category}. Line: {p.lineno(1)}") + f"Invalid ExternalPackageRefCategory: {category}. Line: {p.lineno(1)}" + ) return try: - external_package_ref = construct_or_raise_parsing_error(ExternalPackageRef, - {"category": category, - "reference_type": reference_type, - "locator": locator, - "comment": comment}) + external_package_ref = construct_or_raise_parsing_error( + ExternalPackageRef, + {"category": category, "reference_type": reference_type, "locator": locator, "comment": comment}, + ) except SPDXParsingError as err: self.current_element["logger"].append(err.get_messages()) return @@ -372,7 +403,8 @@ def p_pkg_verification_code(self, p): match = verif_code_regex.match(p[2]) if not match: self.current_element["logger"].append( - f"Error while parsing {p[1]}: Value did not match expected format. Line: {p.lineno(1)}") + f"Error while parsing {p[1]}: Value did not match expected format. Line: {p.lineno(1)}" + ) return value = match.group(verif_code_code_grp) excluded_files = None @@ -387,15 +419,17 @@ def p_pkg_files_analyzed(self, p): if "files_analyzed" in self.current_element: self.current_element["logger"].append(f"Multiple values for {p[1]} found. Line: {p.lineno(1)}") return - self.current_element["files_analyzed"] = p[2] in ['true', 'True'] + self.current_element["files_analyzed"] = p[2] in ["true", "True"] @grammar_rule("primary_package_purpose : PRIMARY_PACKAGE_PURPOSE LINE") def p_primary_package_purpose(self, p): if self.check_that_current_element_matches_class_for_value(Package, p.lineno(1)): set_value(p, self.current_element, method_to_apply=lambda x: PackagePurpose[x.replace("-", "_")]) - @grammar_rule("built_date : BUILT_DATE ISO8601_DATE\n release_date : RELEASE_DATE ISO8601_DATE\n " - "valid_until_date : VALID_UNTIL_DATE ISO8601_DATE") + @grammar_rule( + "built_date : BUILT_DATE ISO8601_DATE\n release_date : RELEASE_DATE ISO8601_DATE\n " + "valid_until_date : VALID_UNTIL_DATE ISO8601_DATE" + ) def p_package_dates(self, p): if self.check_that_current_element_matches_class_for_value(Package, p.lineno(1)): set_value(p, self.current_element, method_to_apply=datetime_from_str) @@ -419,13 +453,13 @@ def p_snippet_range(self, p): argument_name = TAG_DATA_MODEL_FIELD[p[1]][1] if argument_name in self.current_element: - self.current_element["logger"].append( - f"Multiple values for {p[1]} found. Line: {p.lineno(1)}") + self.current_element["logger"].append(f"Multiple values for {p[1]} found. Line: {p.lineno(1)}") return range_re = re.compile(r"^(\d+):(\d+)$", re.UNICODE) if not range_re.match(p[2].strip()): - self.current_element["logger"].append(f"Value for {p[1]} doesn't match valid range pattern. " - f"Line: {p.lineno(1)}") + self.current_element["logger"].append( + f"Value for {p[1]} doesn't match valid range pattern. " f"Line: {p.lineno(1)}" + ) return startpoint = int(p[2].split(":")[0]) endpoint = int(p[2].split(":")[-1]) @@ -450,8 +484,7 @@ def p_annotation_type(self, p): # parsing methods for relationship - @grammar_rule("relationship : RELATIONSHIP LINE RELATIONSHIP_COMMENT text_or_line\n " - "| RELATIONSHIP LINE") + @grammar_rule("relationship : RELATIONSHIP LINE RELATIONSHIP_COMMENT text_or_line\n " "| RELATIONSHIP LINE") def p_relationship(self, p): self.initialize_new_current_element(Relationship) try: @@ -459,7 +492,8 @@ def p_relationship(self, p): except ValueError: self.current_element["logger"].append( f"Relationship couldn't be split in spdx_element_id, relationship_type and " - f"related_spdx_element. Line: {p.lineno(1)}") + f"related_spdx_element. Line: {p.lineno(1)}" + ) return try: self.current_element["relationship_type"] = RelationshipType[relationship_type] @@ -507,7 +541,8 @@ def check_that_current_element_matches_class_for_value(self, expected_class, lin self.logger.append( f"Element {expected_class.__name__} is not the current element in scope, probably the expected tag to " f"start the element ({ELEMENT_EXPECTED_START_TAG[expected_class.__name__]}) is missing. " - f"Line: {line_number}") + f"Line: {line_number}" + ) return False return True @@ -521,7 +556,8 @@ def construct_current_element(self): try: raise_parsing_error_if_logger_has_messages(self.current_element.pop("logger"), clazz.__name__) self.elements_built.setdefault(CLASS_MAPPING[clazz.__name__], []).append( - construct_or_raise_parsing_error(clazz, self.current_element)) + construct_or_raise_parsing_error(clazz, self.current_element) + ) if clazz == File: self.check_for_preceding_package_and_build_contains_relationship() except SPDXParsingError as err: diff --git a/src/spdx/parser/xml/xml_parser.py b/src/spdx/parser/xml/xml_parser.py index 38670c976..9f9189a45 100644 --- a/src/spdx/parser/xml/xml_parser.py +++ b/src/spdx/parser/xml/xml_parser.py @@ -40,8 +40,8 @@ "ranges", "licenseInfoInSnippets", "packageVerificationCodeExcludedFiles", - "attributionTexts" - ] + "attributionTexts", +] def parse_from_file(file_name: str) -> Document: diff --git a/src/spdx/validation/actor_validator.py b/src/spdx/validation/actor_validator.py index b105d5652..192b95774 100644 --- a/src/spdx/validation/actor_validator.py +++ b/src/spdx/validation/actor_validator.py @@ -30,7 +30,7 @@ def validate_actor(actor: Actor, parent_id: str) -> List[ValidationMessage]: validation_messages.append( ValidationMessage( f"email must be None if actor_type is TOOL, but is: {actor.email}", - ValidationContext(parent_id=parent_id, element_type=SpdxElementType.ACTOR, full_element=actor) + ValidationContext(parent_id=parent_id, element_type=SpdxElementType.ACTOR, full_element=actor), ) ) diff --git a/src/spdx/validation/annotation_validator.py b/src/spdx/validation/annotation_validator.py index 34a897f39..e162f2d1c 100644 --- a/src/spdx/validation/annotation_validator.py +++ b/src/spdx/validation/annotation_validator.py @@ -28,8 +28,7 @@ def validate_annotations(annotations: List[Annotation], document: Document) -> L def validate_annotation(annotation: Annotation, document: Document) -> List[ValidationMessage]: validation_messages = [] - context = ValidationContext(element_type=SpdxElementType.ANNOTATION, - full_element=annotation) + context = ValidationContext(element_type=SpdxElementType.ANNOTATION, full_element=annotation) validation_messages.extend(validate_actor(annotation.annotator, "annotation")) diff --git a/src/spdx/validation/checksum_validator.py b/src/spdx/validation/checksum_validator.py index 3d747e102..16bf157d7 100644 --- a/src/spdx/validation/checksum_validator.py +++ b/src/spdx/validation/checksum_validator.py @@ -48,17 +48,18 @@ def validate_checksums(checksums: List[Checksum], parent_id: str, spdx_version: def validate_checksum(checksum: Checksum, parent_id: str, spdx_version: str) -> List[ValidationMessage]: validation_messages = [] algorithm = checksum.algorithm - context = ValidationContext(parent_id=parent_id, element_type=SpdxElementType.CHECKSUM, - full_element=checksum) + context = ValidationContext(parent_id=parent_id, element_type=SpdxElementType.CHECKSUM, full_element=checksum) - if spdx_version == "SPDX-2.2" and algorithm in [ChecksumAlgorithm.SHA3_512, - ChecksumAlgorithm.SHA3_384, - ChecksumAlgorithm.SHA3_256, - ChecksumAlgorithm.BLAKE3, - ChecksumAlgorithm.BLAKE2B_512, - ChecksumAlgorithm.BLAKE2B_384, - ChecksumAlgorithm.BLAKE2B_256, - ChecksumAlgorithm.ADLER32]: + if spdx_version == "SPDX-2.2" and algorithm in [ + ChecksumAlgorithm.SHA3_512, + ChecksumAlgorithm.SHA3_384, + ChecksumAlgorithm.SHA3_256, + ChecksumAlgorithm.BLAKE3, + ChecksumAlgorithm.BLAKE2B_512, + ChecksumAlgorithm.BLAKE2B_384, + ChecksumAlgorithm.BLAKE2B_256, + ChecksumAlgorithm.ADLER32, + ]: return [ValidationMessage(f"{checksum.algorithm.name} is not supported in SPDX-2.2", context)] if not re.match("^[0-9a-f]{" + algorithm_length[algorithm] + "}$", checksum.value): @@ -71,7 +72,8 @@ def validate_checksum(checksum: Checksum, parent_id: str, spdx_version: str) -> validation_messages.append( ValidationMessage( f"value of {algorithm} must consist of {length} lowercase hexadecimal digits, but is: {checksum.value} (length: {len(checksum.value)} digits)", - context) + context, + ) ) return validation_messages diff --git a/src/spdx/validation/creation_info_validator.py b/src/spdx/validation/creation_info_validator.py index 286226351..a73e98635 100644 --- a/src/spdx/validation/creation_info_validator.py +++ b/src/spdx/validation/creation_info_validator.py @@ -25,29 +25,20 @@ def validate_creation_info(creation_info: CreationInfo, spdx_version: str) -> Li if creation_info.spdx_id != "SPDXRef-DOCUMENT": validation_messages.append( - ValidationMessage( - f'spdx_id must be "SPDXRef-DOCUMENT", but is: {creation_info.spdx_id}', - context - ) + ValidationMessage(f'spdx_id must be "SPDXRef-DOCUMENT", but is: {creation_info.spdx_id}', context) ) if creation_info.data_license != "CC0-1.0": validation_messages.append( - ValidationMessage( - f'data_license must be "CC0-1.0", but is: {creation_info.data_license}', - context - ) + ValidationMessage(f'data_license must be "CC0-1.0", but is: {creation_info.data_license}', context) ) for message in validate_uri(creation_info.document_namespace): - validation_messages.append( - ValidationMessage( - "document_namespace " + message, context - ) - ) + validation_messages.append(ValidationMessage("document_namespace " + message, context)) validation_messages.extend(validate_actors(creation_info.creators, creation_info.spdx_id)) validation_messages.extend( - validate_external_document_refs(creation_info.external_document_refs, creation_info.spdx_id, spdx_version)) + validate_external_document_refs(creation_info.external_document_refs, creation_info.spdx_id, spdx_version) + ) return validation_messages diff --git a/src/spdx/validation/document_validator.py b/src/spdx/validation/document_validator.py index becf5f401..c0da83f46 100644 --- a/src/spdx/validation/document_validator.py +++ b/src/spdx/validation/document_validator.py @@ -37,19 +37,27 @@ def validate_full_spdx_document(document: Document, spdx_version: str = None) -> validation_messages.append( ValidationMessage( f'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: {document_version}', - context + context, ) ) elif spdx_version != document_version: validation_messages.append( - ValidationMessage(f"provided SPDX version {spdx_version} does not match " - f"the document's SPDX version {document_version}", context) + ValidationMessage( + f"provided SPDX version {spdx_version} does not match " + f"the document's SPDX version {document_version}", + context, + ) ) if validation_messages: - validation_messages.append(ValidationMessage("There are issues concerning the SPDX version of the document. " - "As subsequent validation relies on the correct version, " - "the validation process has been cancelled.", context)) + validation_messages.append( + ValidationMessage( + "There are issues concerning the SPDX version of the document. " + "As subsequent validation relies on the correct version, " + "the validation process has been cancelled.", + context, + ) + ) return validation_messages validation_messages.extend(validate_creation_info(document.creation_info, spdx_version)) @@ -61,29 +69,34 @@ def validate_full_spdx_document(document: Document, spdx_version: str = None) -> validation_messages.extend(validate_extracted_licensing_infos(document.extracted_licensing_info)) document_id = document.creation_info.spdx_id - document_describes_relationships = filter_by_type_and_origin(document.relationships, RelationshipType.DESCRIBES, - document_id) - described_by_document_relationships = filter_by_type_and_target(document.relationships, - RelationshipType.DESCRIBED_BY, document_id) + document_describes_relationships = filter_by_type_and_origin( + document.relationships, RelationshipType.DESCRIBES, document_id + ) + described_by_document_relationships = filter_by_type_and_target( + document.relationships, RelationshipType.DESCRIBED_BY, document_id + ) if not document_describes_relationships + described_by_document_relationships: validation_messages.append( ValidationMessage( f'there must be at least one relationship "{document_id} DESCRIBES ..." or "... DESCRIBED_BY ' f'{document_id}"', - ValidationContext(spdx_id=document_id, - element_type=SpdxElementType.DOCUMENT))) + ValidationContext(spdx_id=document_id, element_type=SpdxElementType.DOCUMENT), + ) + ) all_spdx_ids: List[str] = get_list_of_all_spdx_ids(document) auxiliary_set = set() duplicated_spdx_ids = set( - spdx_id for spdx_id in all_spdx_ids if spdx_id in auxiliary_set or auxiliary_set.add(spdx_id)) + spdx_id for spdx_id in all_spdx_ids if spdx_id in auxiliary_set or auxiliary_set.add(spdx_id) + ) if duplicated_spdx_ids: validation_messages.append( ValidationMessage( f"every spdx_id must be unique within the document, but found the following duplicates: {sorted(duplicated_spdx_ids)}", - context) + context, + ) ) return validation_messages diff --git a/src/spdx/validation/external_document_ref_validator.py b/src/spdx/validation/external_document_ref_validator.py index b331d161e..c527a6c5c 100644 --- a/src/spdx/validation/external_document_ref_validator.py +++ b/src/spdx/validation/external_document_ref_validator.py @@ -18,8 +18,9 @@ from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage -def validate_external_document_refs(external_document_refs: List[ExternalDocumentRef], parent_id: str, - spdx_version: str) -> List[ValidationMessage]: +def validate_external_document_refs( + external_document_refs: List[ExternalDocumentRef], parent_id: str, spdx_version: str +) -> List[ValidationMessage]: validation_messages = [] for external_document_ref in external_document_refs: validation_messages.extend(validate_external_document_ref(external_document_ref, parent_id, spdx_version)) @@ -27,26 +28,24 @@ def validate_external_document_refs(external_document_refs: List[ExternalDocumen return validation_messages -def validate_external_document_ref(external_document_ref: ExternalDocumentRef, parent_id: str, spdx_version: str) -> \ -List[ValidationMessage]: +def validate_external_document_ref( + external_document_ref: ExternalDocumentRef, parent_id: str, spdx_version: str +) -> List[ValidationMessage]: validation_messages = [] - context = ValidationContext(parent_id=parent_id, element_type=SpdxElementType.EXTERNAL_DOCUMENT_REF, - full_element=external_document_ref) + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.EXTERNAL_DOCUMENT_REF, full_element=external_document_ref + ) if not is_valid_external_doc_ref_id(external_document_ref.document_ref_id): validation_messages.append( ValidationMessage( f'document_ref_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: {external_document_ref.document_ref_id}', - context + context, ) ) for message in validate_uri(external_document_ref.document_uri): - validation_messages.append( - ValidationMessage( - "document_uri " + message, context - ) - ) + validation_messages.append(ValidationMessage("document_uri " + message, context)) validation_messages.extend(validate_checksum(external_document_ref.checksum, parent_id, spdx_version)) diff --git a/src/spdx/validation/external_package_ref_validator.py b/src/spdx/validation/external_package_ref_validator.py index d49099c84..db7bc16eb 100644 --- a/src/spdx/validation/external_package_ref_validator.py +++ b/src/spdx/validation/external_package_ref_validator.py @@ -17,15 +17,15 @@ from spdx.validation.uri_validators import validate_url from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage -CPE22TYPE_REGEX = r'^c[pP][eE]:/[AHOaho]?(:[A-Za-z0-9._\-~%]*){0,6}$' +CPE22TYPE_REGEX = r"^c[pP][eE]:/[AHOaho]?(:[A-Za-z0-9._\-~%]*){0,6}$" CPE23TYPE_REGEX = r'^cpe:2\.3:[aho\*\-](:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!"#$$%&\'\(\)\+,\/:;<=>@\[\]\^`\{\|}~]))+(\?*|\*?))|[\*\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\*\-]))(:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!"#$$%&\'\(\)\+,\/:;<=>@\[\]\^`\{\|}~]))+(\?*|\*?))|[\*\-])){4}$' -MAVEN_CENTRAL_REGEX = r'^[^:]+:[^:]+(:[^:]+)?$' -NPM_REGEX = r'^[^@]+@[^@]+$' -NUGET_REGEX = r'^[^/]+/[^/]+$' -BOWER_REGEX = r'^[^#]+#[^#]+$' -PURL_REGEX = r'^pkg:.+(\/.+)?\/.+(@.+)?(\?.+)?(#.+)?$' -SWH_REGEX = r'^swh:1:(snp|rel|rev|dir|cnt):[0-9a-fA-F]{40}$' -GITOID_REGEX = r'^gitoid:(blob|tree|commit|tag):(sha1:[0-9a-fA-F]{40}|sha256:[0-9a-fA-F]{64})$' +MAVEN_CENTRAL_REGEX = r"^[^:]+:[^:]+(:[^:]+)?$" +NPM_REGEX = r"^[^@]+@[^@]+$" +NUGET_REGEX = r"^[^/]+/[^/]+$" +BOWER_REGEX = r"^[^#]+#[^#]+$" +PURL_REGEX = r"^pkg:.+(\/.+)?\/.+(@.+)?(\?.+)?(#.+)?$" +SWH_REGEX = r"^swh:1:(snp|rel|rev|dir|cnt):[0-9a-fA-F]{40}$" +GITOID_REGEX = r"^gitoid:(blob|tree|commit|tag):(sha1:[0-9a-fA-F]{40}|sha256:[0-9a-fA-F]{64})$" TYPE_TO_REGEX: Dict[str, str] = { "cpe22Type": CPE22TYPE_REGEX, @@ -36,12 +36,13 @@ "bower": BOWER_REGEX, "purl": PURL_REGEX, "swh": SWH_REGEX, - "gitoid": GITOID_REGEX + "gitoid": GITOID_REGEX, } -def validate_external_package_refs(external_package_refs: List[ExternalPackageRef], parent_id: str, - spdx_version: str) -> List[ValidationMessage]: +def validate_external_package_refs( + external_package_refs: List[ExternalPackageRef], parent_id: str, spdx_version: str +) -> List[ValidationMessage]: validation_messages = [] for external_package_ref in external_package_refs: validation_messages.extend(validate_external_package_ref(external_package_ref, parent_id, spdx_version)) @@ -49,11 +50,13 @@ def validate_external_package_refs(external_package_refs: List[ExternalPackageRe return validation_messages -def validate_external_package_ref(external_package_ref: ExternalPackageRef, parent_id: str, spdx_version: str) -> List[ - ValidationMessage]: +def validate_external_package_ref( + external_package_ref: ExternalPackageRef, parent_id: str, spdx_version: str +) -> List[ValidationMessage]: validation_messages = [] - context = ValidationContext(parent_id=parent_id, element_type=SpdxElementType.EXTERNAL_PACKAGE_REF, - full_element=external_package_ref) + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.EXTERNAL_PACKAGE_REF, full_element=external_package_ref + ) category = external_package_ref.category locator = external_package_ref.locator @@ -61,29 +64,40 @@ def validate_external_package_ref(external_package_ref: ExternalPackageRef, pare if category == ExternalPackageRefCategory.OTHER: if " " in locator: - validation_messages.append(ValidationMessage( - f"externalPackageRef locator in category OTHER must contain no spaces, but is: {locator}", - context)) + validation_messages.append( + ValidationMessage( + f"externalPackageRef locator in category OTHER must contain no spaces, but is: {locator}", context + ) + ) elif spdx_version == "SPDX-2.2" and reference_type in ["advisory", "fix", "url", "swid"]: return [ValidationMessage(f'externalPackageRef type "{reference_type}" is not supported in SPDX-2.2', context)] elif reference_type not in CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES[category]: - validation_messages.append(ValidationMessage( - f"externalPackageRef type in category {category.name} must be one of {CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES[category]}, but is: {reference_type}", - context)) + validation_messages.append( + ValidationMessage( + f"externalPackageRef type in category {category.name} must be one of {CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES[category]}, but is: {reference_type}", + context, + ) + ) elif reference_type in ["advisory", "fix", "url"]: if validate_url(locator): - validation_messages.append(ValidationMessage( - f'externalPackageRef locator of type "{reference_type}" must be a valid URL, but is: {locator}', - context)) + validation_messages.append( + ValidationMessage( + f'externalPackageRef locator of type "{reference_type}" must be a valid URL, but is: {locator}', + context, + ) + ) elif reference_type == "swid": if not uritools.isuri(locator) or not locator.startswith("swid"): - validation_messages.append(ValidationMessage( - f'externalPackageRef locator of type "swid" must be a valid URI with scheme swid, but is: {locator}', - context)) + validation_messages.append( + ValidationMessage( + f'externalPackageRef locator of type "swid" must be a valid URI with scheme swid, but is: {locator}', + context, + ) + ) else: validation_messages.extend(validate_against_regex(locator, reference_type, context)) @@ -91,11 +105,15 @@ def validate_external_package_ref(external_package_ref: ExternalPackageRef, pare return validation_messages -def validate_against_regex(string_to_validate: str, reference_type: str, context: ValidationContext) -> List[ - ValidationMessage]: +def validate_against_regex( + string_to_validate: str, reference_type: str, context: ValidationContext +) -> List[ValidationMessage]: regex = TYPE_TO_REGEX[reference_type] if not re.match(regex, string_to_validate): - return [ValidationMessage( - f'externalPackageRef locator of type "{reference_type}" must conform with the regex {regex}, but is: {string_to_validate}', - context)] + return [ + ValidationMessage( + f'externalPackageRef locator of type "{reference_type}" must conform with the regex {regex}, but is: {string_to_validate}', + context, + ) + ] return [] diff --git a/src/spdx/validation/extracted_licensing_info_validator.py b/src/spdx/validation/extracted_licensing_info_validator.py index be08dc630..52e2b35b0 100644 --- a/src/spdx/validation/extracted_licensing_info_validator.py +++ b/src/spdx/validation/extracted_licensing_info_validator.py @@ -17,8 +17,9 @@ from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage -def validate_extracted_licensing_infos(extracted_licensing_infos: Optional[List[ExtractedLicensingInfo]]) -> List[ - ValidationMessage]: +def validate_extracted_licensing_infos( + extracted_licensing_infos: Optional[List[ExtractedLicensingInfo]], +) -> List[ValidationMessage]: validation_messages = [] for extracted_licensing_info in extracted_licensing_infos: validation_messages.extend(validate_extracted_licensing_info(extracted_licensing_info)) @@ -26,18 +27,19 @@ def validate_extracted_licensing_infos(extracted_licensing_infos: Optional[List[ return validation_messages -def validate_extracted_licensing_info(extracted_licensing_infos: ExtractedLicensingInfo) -> List[ - ValidationMessage]: +def validate_extracted_licensing_info(extracted_licensing_infos: ExtractedLicensingInfo) -> List[ValidationMessage]: validation_messages: List[ValidationMessage] = [] - context = ValidationContext(element_type=SpdxElementType.EXTRACTED_LICENSING_INFO, - full_element=extracted_licensing_infos) + context = ValidationContext( + element_type=SpdxElementType.EXTRACTED_LICENSING_INFO, full_element=extracted_licensing_infos + ) license_id: str = extracted_licensing_infos.license_id if license_id and not re.match(r"^LicenseRef-[\da-zA-Z.-]+$", license_id): validation_messages.append( ValidationMessage( f'license_id must only contain letters, numbers, "." and "-" and must begin with "LicenseRef-", but is: {license_id}', - context) + context, + ) ) if license_id and not extracted_licensing_infos.extracted_text: @@ -47,8 +49,6 @@ def validate_extracted_licensing_info(extracted_licensing_infos: ExtractedLicens for cross_reference in extracted_licensing_infos.cross_references: for message in validate_url(cross_reference): - validation_messages.append( - ValidationMessage("cross_reference " + message, context) - ) + validation_messages.append(ValidationMessage("cross_reference " + message, context)) return validation_messages diff --git a/src/spdx/validation/file_validator.py b/src/spdx/validation/file_validator.py index 37bc880da..9e717f50c 100644 --- a/src/spdx/validation/file_validator.py +++ b/src/spdx/validation/file_validator.py @@ -20,8 +20,9 @@ from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage -def validate_files(files: List[File], spdx_version: str, document: Optional[Document] = None) -> List[ - ValidationMessage]: +def validate_files( + files: List[File], spdx_version: str, document: Optional[Document] = None +) -> List[ValidationMessage]: validation_messages = [] if document: for file in files: @@ -35,8 +36,12 @@ def validate_files(files: List[File], spdx_version: str, document: Optional[Docu def validate_file_within_document(file: File, spdx_version: str, document: Document) -> List[ValidationMessage]: validation_messages: List[ValidationMessage] = [] - context = ValidationContext(spdx_id=file.spdx_id, parent_id=document.creation_info.spdx_id, - element_type=SpdxElementType.FILE, full_element=file) + context = ValidationContext( + spdx_id=file.spdx_id, + parent_id=document.creation_info.spdx_id, + element_type=SpdxElementType.FILE, + full_element=file, + ) for message in validate_spdx_id(file.spdx_id, document): validation_messages.append(ValidationMessage(message, context)) @@ -50,8 +55,9 @@ def validate_file_within_document(file: File, spdx_version: str, document: Docum return validation_messages -def validate_file(file: File, spdx_version: str, context: Optional[ValidationContext] = None) -> List[ - ValidationMessage]: +def validate_file( + file: File, spdx_version: str, context: Optional[ValidationContext] = None +) -> List[ValidationMessage]: validation_messages = [] if not context: context = ValidationContext(spdx_id=file.spdx_id, element_type=SpdxElementType.FILE, full_element=file) @@ -59,27 +65,26 @@ def validate_file(file: File, spdx_version: str, context: Optional[ValidationCon if file.name.startswith("/"): validation_messages.append( ValidationMessage( - f'file name must not be an absolute path starting with "/", but is: {file.name}', context) + f'file name must not be an absolute path starting with "/", but is: {file.name}', context + ) ) if ChecksumAlgorithm.SHA1 not in [checksum.algorithm for checksum in file.checksums]: validation_messages.append( ValidationMessage( f"checksums must contain a SHA1 algorithm checksum, but only contains: {[checksum.algorithm for checksum in file.checksums]}", - context) + context, + ) ) validation_messages.extend(validate_checksums(file.checksums, file.spdx_id, spdx_version)) if spdx_version == "SPDX-2.2": if file.license_concluded is None: - validation_messages.append( - ValidationMessage(f"license_concluded is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage(f"license_concluded is mandatory in SPDX-2.2", context)) if not file.license_info_in_file: - validation_messages.append( - ValidationMessage(f"license_info_in_file is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage(f"license_info_in_file is mandatory in SPDX-2.2", context)) if file.copyright_text is None: - validation_messages.append( - ValidationMessage(f"copyright_text is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage(f"copyright_text is mandatory in SPDX-2.2", context)) return validation_messages diff --git a/src/spdx/validation/license_expression_validator.py b/src/spdx/validation/license_expression_validator.py index 546bbc8b4..45199417f 100644 --- a/src/spdx/validation/license_expression_validator.py +++ b/src/spdx/validation/license_expression_validator.py @@ -20,10 +20,11 @@ def validate_license_expressions( - license_expressions: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]], - document: Document, parent_id: str) -> List[ValidationMessage]: - context = ValidationContext(parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, - full_element=license_expressions) + license_expressions: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]], document: Document, parent_id: str +) -> List[ValidationMessage]: + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expressions + ) validation_messages = [] for license_expression in license_expressions: @@ -33,14 +34,18 @@ def validate_license_expressions( def validate_license_expression( - license_expression: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]], document: Document, - parent_id: str, context: ValidationContext = None) -> List[ValidationMessage]: + license_expression: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]], + document: Document, + parent_id: str, + context: ValidationContext = None, +) -> List[ValidationMessage]: if license_expression in [SpdxNoAssertion(), SpdxNone(), None]: return [] if not context: - context = ValidationContext(parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, - full_element=license_expression) + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expression + ) validation_messages = [] license_ref_ids: List[str] = [license_ref.license_id for license_ref in document.extracted_licensing_info] @@ -50,7 +55,8 @@ def validate_license_expression( validation_messages.append( ValidationMessage( f"Unrecognized license reference: {non_spdx_token}. license_expression must only use IDs from the license list or extracted licensing info, but is: {license_expression}", - context) + context, + ) ) try: @@ -58,11 +64,7 @@ def validate_license_expression( except ExpressionParseError as err: # This error is raised when an exception symbol is used as a license symbol and vice versa. # So far, it only catches the first such error in the provided string. - validation_messages.append( - ValidationMessage( - f"{err}. for license_expression: {license_expression}", - context) - ) + validation_messages.append(ValidationMessage(f"{err}. for license_expression: {license_expression}", context)) except ExpressionError: # This error is raised for invalid symbols within the license_expression, but it provides only a string of these. # On the other hand, get_spdx_licensing().validate() gives an actual list of invalid symbols, so this is handled above. diff --git a/src/spdx/validation/package_validator.py b/src/spdx/validation/package_validator.py index 4b11136b2..0cf4f577c 100644 --- a/src/spdx/validation/package_validator.py +++ b/src/spdx/validation/package_validator.py @@ -24,8 +24,9 @@ from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage -def validate_packages(packages: List[Package], spdx_version: str, document: Optional[Document] = None) -> List[ - ValidationMessage]: +def validate_packages( + packages: List[Package], spdx_version: str, document: Optional[Document] = None +) -> List[ValidationMessage]: validation_messages: List[ValidationMessage] = [] if document: for package in packages: @@ -37,28 +38,38 @@ def validate_packages(packages: List[Package], spdx_version: str, document: Opti return validation_messages -def validate_package_within_document(package: Package, spdx_version: str, document: Document) -> List[ - ValidationMessage]: +def validate_package_within_document( + package: Package, spdx_version: str, document: Document +) -> List[ValidationMessage]: validation_messages: List[ValidationMessage] = [] - context = ValidationContext(spdx_id=package.spdx_id, parent_id=document.creation_info.spdx_id, - element_type=SpdxElementType.PACKAGE, full_element=package) + context = ValidationContext( + spdx_id=package.spdx_id, + parent_id=document.creation_info.spdx_id, + element_type=SpdxElementType.PACKAGE, + full_element=package, + ) for message in validate_spdx_id(package.spdx_id, document): validation_messages.append(ValidationMessage(message, context)) if not package.files_analyzed: - package_contains_relationships = filter_by_type_and_origin(document.relationships, RelationshipType.CONTAINS, - package.spdx_id) - contained_in_package_relationships = filter_by_type_and_target(document.relationships, - RelationshipType.CONTAINED_BY, package.spdx_id) + package_contains_relationships = filter_by_type_and_origin( + document.relationships, RelationshipType.CONTAINS, package.spdx_id + ) + contained_in_package_relationships = filter_by_type_and_target( + document.relationships, RelationshipType.CONTAINED_BY, package.spdx_id + ) - combined_relationships: List[Relationship] = package_contains_relationships + contained_in_package_relationships + combined_relationships: List[Relationship] = ( + package_contains_relationships + contained_in_package_relationships + ) if combined_relationships: validation_messages.append( ValidationMessage( f"package must contain no elements if files_analyzed is False, but found {combined_relationships}", - context) + context, + ) ) validation_messages.extend(validate_license_expression(package.license_concluded, document, package.spdx_id)) @@ -69,10 +80,13 @@ def validate_package_within_document(package: Package, spdx_version: str, docume validation_messages.append( ValidationMessage( f"license_info_from_files must be None if files_analyzed is False, but is: {license_info_from_files}", - context) + context, + ) ) else: - validation_messages.extend(validate_license_expressions(license_info_from_files, document, package.spdx_id)) + validation_messages.extend( + validate_license_expressions(license_info_from_files, document, package.spdx_id) + ) validation_messages.extend(validate_license_expression(package.license_declared, document, package.spdx_id)) @@ -81,11 +95,14 @@ def validate_package_within_document(package: Package, spdx_version: str, docume return validation_messages -def validate_package(package: Package, spdx_version: str, context: Optional[ValidationContext] = None) -> List[ - ValidationMessage]: +def validate_package( + package: Package, spdx_version: str, context: Optional[ValidationContext] = None +) -> List[ValidationMessage]: validation_messages: List[ValidationMessage] = [] if not context: - context = ValidationContext(spdx_id=package.spdx_id, element_type=SpdxElementType.PACKAGE, full_element=package) + context = ValidationContext( + spdx_id=package.spdx_id, element_type=SpdxElementType.PACKAGE, full_element=package + ) download_location = package.download_location if isinstance(download_location, str): @@ -102,38 +119,35 @@ def validate_package(package: Package, spdx_version: str, context: Optional[Vali if not package.files_analyzed: validation_messages.append( ValidationMessage( - f"verification_code must be None if files_analyzed is False, but is: {verification_code}", - context)) + f"verification_code must be None if files_analyzed is False, but is: {verification_code}", context + ) + ) else: validation_messages.extend(validate_verification_code(verification_code, package.spdx_id)) validation_messages.extend(validate_checksums(package.checksums, package.spdx_id, spdx_version)) validation_messages.extend( - validate_external_package_refs(package.external_references, package.spdx_id, spdx_version)) + validate_external_package_refs(package.external_references, package.spdx_id, spdx_version) + ) if spdx_version == "SPDX-2.2": if package.primary_package_purpose is not None: validation_messages.append( - ValidationMessage(f"primary_package_purpose is not supported in SPDX-2.2", context)) + ValidationMessage(f"primary_package_purpose is not supported in SPDX-2.2", context) + ) if package.built_date is not None: - validation_messages.append( - ValidationMessage(f"built_date is not supported in SPDX-2.2", context)) + validation_messages.append(ValidationMessage(f"built_date is not supported in SPDX-2.2", context)) if package.release_date is not None: - validation_messages.append( - ValidationMessage(f"release_date is not supported in SPDX-2.2", context)) + validation_messages.append(ValidationMessage(f"release_date is not supported in SPDX-2.2", context)) if package.valid_until_date is not None: - validation_messages.append( - ValidationMessage(f"valid_until_date is not supported in SPDX-2.2", context)) + validation_messages.append(ValidationMessage(f"valid_until_date is not supported in SPDX-2.2", context)) if package.license_concluded is None: - validation_messages.append( - ValidationMessage(f"license_concluded is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage(f"license_concluded is mandatory in SPDX-2.2", context)) if package.license_declared is None: - validation_messages.append( - ValidationMessage(f"license_declared is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage(f"license_declared is mandatory in SPDX-2.2", context)) if package.copyright_text is None: - validation_messages.append( - ValidationMessage(f"copyright_text is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage(f"copyright_text is mandatory in SPDX-2.2", context)) return validation_messages diff --git a/src/spdx/validation/package_verification_code_validator.py b/src/spdx/validation/package_verification_code_validator.py index e12574bdd..69c6bd0ac 100644 --- a/src/spdx/validation/package_verification_code_validator.py +++ b/src/spdx/validation/package_verification_code_validator.py @@ -18,14 +18,14 @@ def validate_verification_code(verification_code: PackageVerificationCode, parent_id: str) -> List[ValidationMessage]: validation_messages: List[ValidationMessage] = [] - context = ValidationContext(parent_id=parent_id, element_type=SpdxElementType.PACKAGE_VERIFICATION_CODE, - full_element=verification_code) + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.PACKAGE_VERIFICATION_CODE, full_element=verification_code + ) for file in verification_code.excluded_files: if file.startswith("/"): validation_messages.append( - ValidationMessage( - f'file name must not be an absolute path starting with "/", but is: {file}', context) + ValidationMessage(f'file name must not be an absolute path starting with "/", but is: {file}', context) ) value: str = verification_code.value @@ -33,7 +33,8 @@ def validate_verification_code(verification_code: PackageVerificationCode, paren validation_messages.append( ValidationMessage( f"value of verification_code must consist of 40 lowercase hexadecimal digits, but is: {value} (length: {len(value)} digits)", - context) + context, + ) ) return validation_messages diff --git a/src/spdx/validation/relationship_validator.py b/src/spdx/validation/relationship_validator.py index b9c479675..11268d07c 100644 --- a/src/spdx/validation/relationship_validator.py +++ b/src/spdx/validation/relationship_validator.py @@ -19,8 +19,9 @@ from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage -def validate_relationships(relationships: List[Relationship], spdx_version: str, document: Document) -> List[ - ValidationMessage]: +def validate_relationships( + relationships: List[Relationship], spdx_version: str, document: Document +) -> List[ValidationMessage]: validation_messages = [] for relationship in relationships: validation_messages.extend(validate_relationship(relationship, spdx_version, document)) @@ -28,10 +29,11 @@ def validate_relationships(relationships: List[Relationship], spdx_version: str, return validation_messages -def validate_relationship(relationship: Relationship, spdx_version: str, document: Document) -> List[ValidationMessage]: +def validate_relationship( + relationship: Relationship, spdx_version: str, document: Document +) -> List[ValidationMessage]: validation_messages = [] - context = ValidationContext(element_type=SpdxElementType.RELATIONSHIP, - full_element=relationship) + context = ValidationContext(element_type=SpdxElementType.RELATIONSHIP, full_element=relationship) relationship_type: RelationshipType = relationship.relationship_type @@ -45,8 +47,10 @@ def validate_relationship(relationship: Relationship, spdx_version: str, documen validation_messages.append(ValidationMessage(message, context)) if spdx_version == "SPDX-2.2": - if relationship_type == RelationshipType.SPECIFICATION_FOR or relationship_type == RelationshipType.REQUIREMENT_DESCRIPTION_FOR: - validation_messages.append( - ValidationMessage(f"{relationship_type} is not supported in SPDX-2.2", context)) + if ( + relationship_type == RelationshipType.SPECIFICATION_FOR + or relationship_type == RelationshipType.REQUIREMENT_DESCRIPTION_FOR + ): + validation_messages.append(ValidationMessage(f"{relationship_type} is not supported in SPDX-2.2", context)) return validation_messages diff --git a/src/spdx/validation/snippet_validator.py b/src/spdx/validation/snippet_validator.py index 6a7f37378..27a049621 100644 --- a/src/spdx/validation/snippet_validator.py +++ b/src/spdx/validation/snippet_validator.py @@ -18,8 +18,9 @@ from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage -def validate_snippets(snippets: List[Snippet], spdx_version: str, document: Optional[Document] = None) -> List[ - ValidationMessage]: +def validate_snippets( + snippets: List[Snippet], spdx_version: str, document: Optional[Document] = None +) -> List[ValidationMessage]: validation_messages = [] if document: for snippet in snippets: @@ -31,11 +32,16 @@ def validate_snippets(snippets: List[Snippet], spdx_version: str, document: Opti return validation_messages -def validate_snippet_within_document(snippet: Snippet, spdx_version: str, document: Document) -> List[ - ValidationMessage]: +def validate_snippet_within_document( + snippet: Snippet, spdx_version: str, document: Document +) -> List[ValidationMessage]: validation_messages: List[ValidationMessage] = [] - context = ValidationContext(spdx_id=snippet.spdx_id, parent_id=document.creation_info.spdx_id, - element_type=SpdxElementType.SNIPPET, full_element=snippet) + context = ValidationContext( + spdx_id=snippet.spdx_id, + parent_id=document.creation_info.spdx_id, + element_type=SpdxElementType.SNIPPET, + full_element=snippet, + ) messages: List[str] = validate_spdx_id(snippet.spdx_id, document) for message in messages: @@ -47,54 +53,59 @@ def validate_snippet_within_document(snippet: Snippet, spdx_version: str, docume validation_messages.extend(validate_license_expression(snippet.license_concluded, document, snippet.spdx_id)) - validation_messages.extend(validate_license_expressions(snippet.license_info_in_snippet, document, snippet.spdx_id)) + validation_messages.extend( + validate_license_expressions(snippet.license_info_in_snippet, document, snippet.spdx_id) + ) validation_messages.extend(validate_snippet(snippet, spdx_version, context)) return validation_messages -def validate_snippet(snippet: Snippet, spdx_version: str, context: Optional[ValidationContext] = None) -> List[ - ValidationMessage]: +def validate_snippet( + snippet: Snippet, spdx_version: str, context: Optional[ValidationContext] = None +) -> List[ValidationMessage]: validation_messages = [] if not context: - context = ValidationContext(spdx_id=snippet.spdx_id, element_type=SpdxElementType.SNIPPET, full_element=snippet) + context = ValidationContext( + spdx_id=snippet.spdx_id, element_type=SpdxElementType.SNIPPET, full_element=snippet + ) if snippet.byte_range[0] < 1: validation_messages.append( ValidationMessage( - f"byte_range values must be greater than or equal to 1, but is: {snippet.byte_range}", - context) + f"byte_range values must be greater than or equal to 1, but is: {snippet.byte_range}", context + ) ) if snippet.byte_range[0] > snippet.byte_range[1]: validation_messages.append( ValidationMessage( f"the first value of byte_range must be less than or equal to the second, but is: {snippet.byte_range}", - context) + context, + ) ) if snippet.line_range: if snippet.line_range[0] < 1: validation_messages.append( ValidationMessage( - f"line_range values must be greater than or equal to 1, but is: {snippet.line_range}", - context) + f"line_range values must be greater than or equal to 1, but is: {snippet.line_range}", context + ) ) if snippet.line_range[0] > snippet.line_range[1]: validation_messages.append( ValidationMessage( f"the first value of line_range must be less than or equal to the second, but is: {snippet.line_range}", - context) + context, + ) ) if spdx_version == "SPDX-2.2": if snippet.license_concluded is None: - validation_messages.append( - ValidationMessage(f"license_concluded is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage(f"license_concluded is mandatory in SPDX-2.2", context)) if snippet.copyright_text is None: - validation_messages.append( - ValidationMessage(f"copyright_text is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage(f"copyright_text is mandatory in SPDX-2.2", context)) return validation_messages diff --git a/src/spdx/validation/spdx_id_validators.py b/src/spdx/validation/spdx_id_validators.py index cdf8f0c3a..8d941f06e 100644 --- a/src/spdx/validation/spdx_id_validators.py +++ b/src/spdx/validation/spdx_id_validators.py @@ -43,17 +43,19 @@ def get_list_of_all_spdx_ids(document: Document) -> List[str]: def is_external_doc_ref_present_in_document(external_ref_id: str, document: Document) -> bool: - all_external_doc_ref_ids_in_document = [external_doc_ref.document_ref_id for external_doc_ref in - document.creation_info.external_document_refs] + all_external_doc_ref_ids_in_document = [ + external_doc_ref.document_ref_id for external_doc_ref in document.creation_info.external_document_refs + ] return external_ref_id in all_external_doc_ref_ids_in_document -def validate_spdx_id(spdx_id: str, document: Document, check_document: bool = False, check_files: bool = False) -> List[ - str]: - """ Test that the given spdx_id (and a potential DocumentRef to an external document) is valid +def validate_spdx_id( + spdx_id: str, document: Document, check_document: bool = False, check_files: bool = False +) -> List[str]: + """Test that the given spdx_id (and a potential DocumentRef to an external document) is valid and, if it is a reference, actually exists in the document. Optionally checks files or the whole document - for the existence of the spdx_id (i.e. if it is used as a reference). Returns a list of validation messages. """ + for the existence of the spdx_id (i.e. if it is used as a reference). Returns a list of validation messages.""" validation_messages: List[str] = [] split_id: List[str] = spdx_id.split(":") @@ -61,26 +63,31 @@ def validate_spdx_id(spdx_id: str, document: Document, check_document: bool = Fa # # # invalid case # # # if len(split_id) > 2: return [ - f"spdx_id must not contain more than one colon in order to separate the external document reference id from the internal SPDX id, but is: {spdx_id}"] + f"spdx_id must not contain more than one colon in order to separate the external document reference id from the internal SPDX id, but is: {spdx_id}" + ] # # # case with external document ref prefix # # # if len(split_id) == 2: if not is_valid_external_doc_ref_id(split_id[0]): validation_messages.append( - f'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: {split_id[0]}') + f'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: {split_id[0]}' + ) if not is_valid_internal_spdx_id(split_id[1]): validation_messages.append( - f'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: {split_id[1]}') + f'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: {split_id[1]}' + ) if not is_external_doc_ref_present_in_document(split_id[0], document): validation_messages.append( - f'did not find the external document reference "{split_id[0]}" in the SPDX document') + f'did not find the external document reference "{split_id[0]}" in the SPDX document' + ) return validation_messages # # # "normal" case # # # if not is_valid_internal_spdx_id(spdx_id): validation_messages.append( - f'spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: {spdx_id}') + f'spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: {spdx_id}' + ) if check_document: if not is_spdx_id_present_in_document(spdx_id, document): @@ -88,6 +95,8 @@ def validate_spdx_id(spdx_id: str, document: Document, check_document: bool = Fa if check_files: if not is_spdx_id_present_in_files(spdx_id, document.files): - validation_messages.append(f'did not find the referenced spdx_id "{spdx_id}" in the SPDX document\'s files') + validation_messages.append( + f'did not find the referenced spdx_id "{spdx_id}" in the SPDX document\'s files' + ) return validation_messages diff --git a/src/spdx/validation/uri_validators.py b/src/spdx/validation/uri_validators.py index 3033e0458..1bc8608dc 100644 --- a/src/spdx/validation/uri_validators.py +++ b/src/spdx/validation/uri_validators.py @@ -19,7 +19,8 @@ git_pattern = "(git\\+git@[a-zA-Z0-9\\.\\-]+:[a-zA-Z0-9/\\\\.@\\-]+)" bazaar_pattern = "(bzr\\+lp:[a-zA-Z0-9\\.\\-]+)" download_location_pattern = ( - "^(((" + supported_download_repos + "\\+)?" + url_pattern + ")|" + git_pattern + "|" + bazaar_pattern + ")$") + "^(((" + supported_download_repos + "\\+)?" + url_pattern + ")|" + git_pattern + "|" + bazaar_pattern + ")$" +) def validate_url(url: str) -> List[str]: diff --git a/src/spdx/writer/rdf/annotation_writer.py b/src/spdx/writer/rdf/annotation_writer.py index 3f486a84c..6aa234ae6 100644 --- a/src/spdx/writer/rdf/annotation_writer.py +++ b/src/spdx/writer/rdf/annotation_writer.py @@ -19,16 +19,25 @@ from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id -def add_annotation_to_graph(annotation: Annotation, graph: Graph, doc_namespace: str, - external_doc_ref_to_namespace: Dict[str, str]): - annotation_resource = URIRef(add_namespace_to_spdx_id(annotation.spdx_id, doc_namespace, external_doc_ref_to_namespace)) +def add_annotation_to_graph( + annotation: Annotation, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str] +): + annotation_resource = URIRef( + add_namespace_to_spdx_id(annotation.spdx_id, doc_namespace, external_doc_ref_to_namespace) + ) annotation_node = BNode() graph.add((annotation_node, RDF.type, SPDX_NAMESPACE.Annotation)) - graph.add((annotation_node, SPDX_NAMESPACE.annotationType, - SPDX_NAMESPACE[f"annotationType_{snake_case_to_camel_case(annotation.annotation_type.name)}"])) + graph.add( + ( + annotation_node, + SPDX_NAMESPACE.annotationType, + SPDX_NAMESPACE[f"annotationType_{snake_case_to_camel_case(annotation.annotation_type.name)}"], + ) + ) graph.add((annotation_node, SPDX_NAMESPACE.annotator, Literal(annotation.annotator.to_serialized_string()))) graph.add( - (annotation_node, SPDX_NAMESPACE.annotationDate, Literal(datetime_to_iso_string(annotation.annotation_date)))) + (annotation_node, SPDX_NAMESPACE.annotationDate, Literal(datetime_to_iso_string(annotation.annotation_date))) + ) graph.add((annotation_node, RDFS.comment, Literal(annotation.annotation_comment))) graph.add((annotation_resource, SPDX_NAMESPACE.annotation, annotation_node)) diff --git a/src/spdx/writer/rdf/checksum_writer.py b/src/spdx/writer/rdf/checksum_writer.py index 319c144ae..335b89d31 100644 --- a/src/spdx/writer/rdf/checksum_writer.py +++ b/src/spdx/writer/rdf/checksum_writer.py @@ -22,9 +22,10 @@ def add_checksum_to_graph(checksum: Checksum, graph: Graph, parent: URIRef): graph.add((parent, SPDX_NAMESPACE.checksum, checksum_node)) + def algorithm_to_rdf_string(algorithm: ChecksumAlgorithm) -> URIRef: if "BLAKE2B" in algorithm.name: - algorithm_rdf_string = algorithm.name.replace("_","").lower() + algorithm_rdf_string = algorithm.name.replace("_", "").lower() else: algorithm_rdf_string = algorithm.name.lower() diff --git a/src/spdx/writer/rdf/creation_info_writer.py b/src/spdx/writer/rdf/creation_info_writer.py index b7e78f5d2..795ed2f1e 100644 --- a/src/spdx/writer/rdf/creation_info_writer.py +++ b/src/spdx/writer/rdf/creation_info_writer.py @@ -33,8 +33,9 @@ def add_creation_info_to_graph(creation_info: CreationInfo, graph: Graph): for creator in creation_info.creators: graph.add((creation_info_node, SPDX_NAMESPACE.creator, Literal(creator.to_serialized_string()))) - add_optional_literal(creation_info.license_list_version, graph, creation_info_node, - SPDX_NAMESPACE.licenseListVersion) + add_optional_literal( + creation_info.license_list_version, graph, creation_info_node, SPDX_NAMESPACE.licenseListVersion + ) add_optional_literal(creation_info.creator_comment, graph, creation_info_node, RDFS.comment) graph.add((doc_node, SPDX_NAMESPACE.creationInfo, creation_info_node)) diff --git a/src/spdx/writer/rdf/external_document_ref_writer.py b/src/spdx/writer/rdf/external_document_ref_writer.py index 1ee876830..85ef8da65 100644 --- a/src/spdx/writer/rdf/external_document_ref_writer.py +++ b/src/spdx/writer/rdf/external_document_ref_writer.py @@ -15,11 +15,14 @@ from spdx.writer.rdf.checksum_writer import add_checksum_to_graph -def add_external_document_ref_to_graph(external_document_ref: ExternalDocumentRef, graph: Graph, doc_node: URIRef, - doc_namespace: str): +def add_external_document_ref_to_graph( + external_document_ref: ExternalDocumentRef, graph: Graph, doc_node: URIRef, doc_namespace: str +): external_document_ref_resource = URIRef(f"{doc_namespace}#{external_document_ref.document_ref_id}") graph.add((external_document_ref_resource, RDF.type, SPDX_NAMESPACE.ExternalDocumentRef)) - graph.add((external_document_ref_resource, SPDX_NAMESPACE.spdxDocument, URIRef(external_document_ref.document_uri))) + graph.add( + (external_document_ref_resource, SPDX_NAMESPACE.spdxDocument, URIRef(external_document_ref.document_uri)) + ) add_checksum_to_graph(external_document_ref.checksum, graph, external_document_ref_resource) graph.add((doc_node, SPDX_NAMESPACE.externalDocumentRef, external_document_ref_resource)) diff --git a/src/spdx/writer/rdf/extracted_licensing_info_writer.py b/src/spdx/writer/rdf/extracted_licensing_info_writer.py index 7e8e4e727..96bd3888e 100644 --- a/src/spdx/writer/rdf/extracted_licensing_info_writer.py +++ b/src/spdx/writer/rdf/extracted_licensing_info_writer.py @@ -15,19 +15,23 @@ from spdx.writer.rdf.writer_utils import add_literal_or_no_assertion, add_optional_literal -def add_extracted_licensing_info_to_graph(extracted_licensing_info: ExtractedLicensingInfo, graph: Graph, doc_node, - doc_namespace: str): +def add_extracted_licensing_info_to_graph( + extracted_licensing_info: ExtractedLicensingInfo, graph: Graph, doc_node, doc_namespace: str +): if extracted_licensing_info.license_id: extracted_licensing_info_resource = URIRef(f"{doc_namespace}#{extracted_licensing_info.license_id}") graph.add((extracted_licensing_info_resource, RDF.type, SPDX_NAMESPACE.ExtractedLicensingInfo)) else: extracted_licensing_info_resource = BNode() - add_optional_literal(extracted_licensing_info.license_id, graph, extracted_licensing_info_resource, - SPDX_NAMESPACE.licenseId) - add_optional_literal(extracted_licensing_info.extracted_text, graph, extracted_licensing_info_resource, - SPDX_NAMESPACE.extractedText) - add_literal_or_no_assertion(extracted_licensing_info.license_name, graph, extracted_licensing_info_resource, - SPDX_NAMESPACE.name) + add_optional_literal( + extracted_licensing_info.license_id, graph, extracted_licensing_info_resource, SPDX_NAMESPACE.licenseId + ) + add_optional_literal( + extracted_licensing_info.extracted_text, graph, extracted_licensing_info_resource, SPDX_NAMESPACE.extractedText + ) + add_literal_or_no_assertion( + extracted_licensing_info.license_name, graph, extracted_licensing_info_resource, SPDX_NAMESPACE.name + ) for cross_reference in extracted_licensing_info.cross_references: graph.add((extracted_licensing_info_resource, RDFS.seeAlso, Literal(cross_reference))) add_optional_literal(extracted_licensing_info.comment, graph, extracted_licensing_info_resource, RDFS.comment) diff --git a/src/spdx/writer/rdf/file_writer.py b/src/spdx/writer/rdf/file_writer.py index c66b37ccc..c896cdea8 100644 --- a/src/spdx/writer/rdf/file_writer.py +++ b/src/spdx/writer/rdf/file_writer.py @@ -20,22 +20,28 @@ from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id, add_optional_literal -def add_file_to_graph(file: File, graph: Graph, doc_namespace: str, - external_doc_ref_to_namespace: Dict[str, str]): +def add_file_to_graph(file: File, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str]): file_resource = URIRef(add_namespace_to_spdx_id(file.spdx_id, doc_namespace, external_doc_ref_to_namespace)) graph.add((file_resource, RDF.type, SPDX_NAMESPACE.File)) graph.add((file_resource, SPDX_NAMESPACE.fileName, Literal(file.name))) for file_type in file.file_types: - graph.add((file_resource, SPDX_NAMESPACE.fileType, - SPDX_NAMESPACE[f"fileType_{snake_case_to_camel_case(file_type.name)}"])) + graph.add( + ( + file_resource, + SPDX_NAMESPACE.fileType, + SPDX_NAMESPACE[f"fileType_{snake_case_to_camel_case(file_type.name)}"], + ) + ) for checksum in file.checksums: add_checksum_to_graph(checksum, graph, file_resource) - add_license_expression_or_none_or_no_assertion(file.license_concluded, graph, file_resource, - SPDX_NAMESPACE.licenseConcluded, doc_namespace) - add_license_expression_or_none_or_no_assertion(file.license_info_in_file, graph, file_resource, - SPDX_NAMESPACE.licenseInfoInFile, doc_namespace) + add_license_expression_or_none_or_no_assertion( + file.license_concluded, graph, file_resource, SPDX_NAMESPACE.licenseConcluded, doc_namespace + ) + add_license_expression_or_none_or_no_assertion( + file.license_info_in_file, graph, file_resource, SPDX_NAMESPACE.licenseInfoInFile, doc_namespace + ) add_optional_literal(file.license_comment, graph, file_resource, SPDX_NAMESPACE.licenseComments) add_optional_literal(file.copyright_text, graph, file_resource, SPDX_NAMESPACE.copyrightText) diff --git a/src/spdx/writer/rdf/license_expression_writer.py b/src/spdx/writer/rdf/license_expression_writer.py index eb97eb3ff..bb584817f 100644 --- a/src/spdx/writer/rdf/license_expression_writer.py +++ b/src/spdx/writer/rdf/license_expression_writer.py @@ -28,9 +28,15 @@ from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE -def add_license_expression_or_none_or_no_assertion(value: Union[ - List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]], LicenseExpression, SpdxNoAssertion, SpdxNone], graph: Graph, parent: Node, predicate: Node, - doc_namespace: str): +def add_license_expression_or_none_or_no_assertion( + value: Union[ + List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]], LicenseExpression, SpdxNoAssertion, SpdxNone + ], + graph: Graph, + parent: Node, + predicate: Node, + doc_namespace: str, +): if isinstance(value, SpdxNoAssertion): graph.add((parent, predicate, SPDX_NAMESPACE.noassertion)) return @@ -44,8 +50,9 @@ def add_license_expression_or_none_or_no_assertion(value: Union[ add_license_expression_to_graph(value, graph, parent, predicate, doc_namespace) -def add_license_expression_to_graph(license_expression: Expression, graph: Graph, parent: Node, predicate: Node, - doc_namespace: str): +def add_license_expression_to_graph( + license_expression: Expression, graph: Graph, parent: Node, predicate: Node, doc_namespace: str +): if isinstance(license_expression, AND): member_node = BNode() graph.add((member_node, RDF.type, SPDX_NAMESPACE.ConjunctiveLicenseSet)) @@ -63,14 +70,14 @@ def add_license_expression_to_graph(license_expression: Expression, graph: Graph graph.add((member_node, RDF.type, SPDX_NAMESPACE.WithExceptionOperator)) graph.add((parent, predicate, member_node)) - add_license_expression_to_graph(license_expression.license_symbol, graph, member_node, SPDX_NAMESPACE.member, - doc_namespace) + add_license_expression_to_graph( + license_expression.license_symbol, graph, member_node, SPDX_NAMESPACE.member, doc_namespace + ) add_license_exception_to_graph(license_expression.exception_symbol, graph, member_node) if isinstance(license_expression, LicenseSymbol): if license_or_exception_is_on_spdx_licensing_list(license_expression): - graph.add( - (parent, predicate, LICENSE_NAMESPACE[str(license_expression)])) + graph.add((parent, predicate, LICENSE_NAMESPACE[str(license_expression)])) else: # assuming that the license expression is a LicenseRef to an instance of ExtractedLicensingInfo graph.add((parent, predicate, URIRef(f"{doc_namespace}#{license_expression}"))) diff --git a/src/spdx/writer/rdf/package_writer.py b/src/spdx/writer/rdf/package_writer.py index 99f22a3db..84cf94b8d 100644 --- a/src/spdx/writer/rdf/package_writer.py +++ b/src/spdx/writer/rdf/package_writer.py @@ -30,8 +30,9 @@ ) -def add_package_to_graph(package: Package, graph: Graph, doc_namespace: str, - external_doc_ref_to_namespace: Dict[str, str]): +def add_package_to_graph( + package: Package, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str] +): package_resource = URIRef(add_namespace_to_spdx_id(package.spdx_id, doc_namespace, external_doc_ref_to_namespace)) graph.add((package_resource, RDF.type, SPDX_NAMESPACE.Package)) @@ -40,8 +41,9 @@ def add_package_to_graph(package: Package, graph: Graph, doc_namespace: str, add_optional_literal(package.file_name, graph, package_resource, SPDX_NAMESPACE.packageFileName) add_optional_literal(package.supplier, graph, package_resource, SPDX_NAMESPACE.supplier) add_optional_literal(package.originator, graph, package_resource, SPDX_NAMESPACE.originator) - add_literal_or_no_assertion_or_none(package.download_location, graph, package_resource, - SPDX_NAMESPACE.downloadLocation) + add_literal_or_no_assertion_or_none( + package.download_location, graph, package_resource, SPDX_NAMESPACE.downloadLocation + ) graph.add((package_resource, SPDX_NAMESPACE.filesAnalyzed, Literal(package.files_analyzed, datatype=XSD.boolean))) add_package_verification_code_to_graph(package.verification_code, graph, package_resource) for checksum in package.checksums: @@ -49,12 +51,15 @@ def add_package_to_graph(package: Package, graph: Graph, doc_namespace: str, add_optional_literal(package.homepage, graph, package_resource, DOAP.homepage) add_optional_literal(package.source_info, graph, package_resource, SPDX_NAMESPACE.sourceInfo) - add_license_expression_or_none_or_no_assertion(package.license_concluded, graph, package_resource, - SPDX_NAMESPACE.licenseConcluded, doc_namespace) - add_license_expression_or_none_or_no_assertion(package.license_info_from_files, graph, package_resource, - SPDX_NAMESPACE.licenseInfoFromFiles, doc_namespace) - add_license_expression_or_none_or_no_assertion(package.license_declared, graph, package_resource, - SPDX_NAMESPACE.licenseDeclared, doc_namespace) + add_license_expression_or_none_or_no_assertion( + package.license_concluded, graph, package_resource, SPDX_NAMESPACE.licenseConcluded, doc_namespace + ) + add_license_expression_or_none_or_no_assertion( + package.license_info_from_files, graph, package_resource, SPDX_NAMESPACE.licenseInfoFromFiles, doc_namespace + ) + add_license_expression_or_none_or_no_assertion( + package.license_declared, graph, package_resource, SPDX_NAMESPACE.licenseDeclared, doc_namespace + ) add_optional_literal(package.license_comment, graph, package_resource, SPDX_NAMESPACE.licenseComments) add_optional_literal(package.copyright_text, graph, package_resource, SPDX_NAMESPACE.copyrightText) add_optional_literal(package.summary, graph, package_resource, SPDX_NAMESPACE.summary) @@ -65,42 +70,74 @@ def add_package_to_graph(package: Package, graph: Graph, doc_namespace: str, for attribution_text in package.attribution_texts: add_optional_literal(attribution_text, graph, package_resource, SPDX_NAMESPACE.attributionText) if package.primary_package_purpose: - graph.add((package_resource, SPDX_NAMESPACE.primaryPackagePurpose, - SPDX_NAMESPACE[f"purpose_{snake_case_to_camel_case(package.primary_package_purpose.name)}"])) + graph.add( + ( + package_resource, + SPDX_NAMESPACE.primaryPackagePurpose, + SPDX_NAMESPACE[f"purpose_{snake_case_to_camel_case(package.primary_package_purpose.name)}"], + ) + ) add_datetime_to_graph(package.release_date, graph, package_resource, SPDX_NAMESPACE.releaseDate) add_datetime_to_graph(package.built_date, graph, package_resource, SPDX_NAMESPACE.builtDate) add_datetime_to_graph(package.valid_until_date, graph, package_resource, SPDX_NAMESPACE.validUntilDate) -def add_package_verification_code_to_graph(package_verification_code: PackageVerificationCode, graph: Graph, - package_node: URIRef): +def add_package_verification_code_to_graph( + package_verification_code: PackageVerificationCode, graph: Graph, package_node: URIRef +): if not package_verification_code: return package_verification_code_node = BNode() graph.add((package_verification_code_node, RDF.type, SPDX_NAMESPACE.PackageVerificationCode)) - graph.add((package_verification_code_node, SPDX_NAMESPACE.packageVerificationCodeValue, - Literal(package_verification_code.value))) + graph.add( + ( + package_verification_code_node, + SPDX_NAMESPACE.packageVerificationCodeValue, + Literal(package_verification_code.value), + ) + ) for excluded_file in package_verification_code.excluded_files: - graph.add((package_verification_code_node, SPDX_NAMESPACE.packageVerificationCodeExcludedFile, - Literal(excluded_file))) + graph.add( + ( + package_verification_code_node, + SPDX_NAMESPACE.packageVerificationCodeExcludedFile, + Literal(excluded_file), + ) + ) graph.add((package_node, SPDX_NAMESPACE.packageVerificationCode, package_verification_code_node)) -def add_external_package_ref_to_graph(external_package_ref: ExternalPackageRef, graph: Graph, package_node: URIRef, - doc_namespace: str): +def add_external_package_ref_to_graph( + external_package_ref: ExternalPackageRef, graph: Graph, package_node: URIRef, doc_namespace: str +): external_package_ref_node = BNode() graph.add((external_package_ref_node, RDF.type, SPDX_NAMESPACE.ExternalRef)) - graph.add((external_package_ref_node, SPDX_NAMESPACE.referenceCategory, - SPDX_NAMESPACE[f"referenceCategory_{snake_case_to_camel_case(external_package_ref.category.name)}"])) + graph.add( + ( + external_package_ref_node, + SPDX_NAMESPACE.referenceCategory, + SPDX_NAMESPACE[f"referenceCategory_{snake_case_to_camel_case(external_package_ref.category.name)}"], + ) + ) if external_package_ref.reference_type in CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES[external_package_ref.category]: - graph.add((external_package_ref_node, SPDX_NAMESPACE.referenceType, - REFERENCE_NAMESPACE[external_package_ref.reference_type])) + graph.add( + ( + external_package_ref_node, + SPDX_NAMESPACE.referenceType, + REFERENCE_NAMESPACE[external_package_ref.reference_type], + ) + ) else: - graph.add((external_package_ref_node, SPDX_NAMESPACE.referenceType, - URIRef(f"{doc_namespace}#{external_package_ref.reference_type}"))) + graph.add( + ( + external_package_ref_node, + SPDX_NAMESPACE.referenceType, + URIRef(f"{doc_namespace}#{external_package_ref.reference_type}"), + ) + ) graph.add((external_package_ref_node, SPDX_NAMESPACE.referenceLocator, Literal(external_package_ref.locator))) if external_package_ref.comment: graph.add((external_package_ref_node, RDFS.comment, Literal(external_package_ref.comment))) diff --git a/src/spdx/writer/rdf/rdf_writer.py b/src/spdx/writer/rdf/rdf_writer.py index 9ef0f8b3c..64daf7389 100644 --- a/src/spdx/writer/rdf/rdf_writer.py +++ b/src/spdx/writer/rdf/rdf_writer.py @@ -34,8 +34,10 @@ def write_document_to_file(document: Document, file_name: str, validate: bool): graph = Graph() doc_namespace = document.creation_info.document_namespace - external_doc_ref_to_namespace: Dict[str, str] = {external_doc_ref.document_ref_id: external_doc_ref.document_uri for - external_doc_ref in document.creation_info.external_document_refs} + external_doc_ref_to_namespace: Dict[str, str] = { + external_doc_ref.document_ref_id: external_doc_ref.document_uri + for external_doc_ref in document.creation_info.external_document_refs + } doc_node = add_creation_info_to_graph(document.creation_info, graph) for annotation in document.annotations: add_annotation_to_graph(annotation, graph, doc_namespace, external_doc_ref_to_namespace) diff --git a/src/spdx/writer/rdf/relationship_writer.py b/src/spdx/writer/rdf/relationship_writer.py index 5f01fd668..a59a2f537 100644 --- a/src/spdx/writer/rdf/relationship_writer.py +++ b/src/spdx/writer/rdf/relationship_writer.py @@ -20,21 +20,36 @@ from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id -def add_relationship_to_graph(relationship: Relationship, graph: Graph, doc_namespace: str, - external_doc_ref_to_namespace: Dict[str, str]): +def add_relationship_to_graph( + relationship: Relationship, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str] +): relationship_node = BNode() graph.add((relationship_node, RDF.type, SPDX_NAMESPACE.Relationship)) - graph.add((relationship_node, SPDX_NAMESPACE.relationshipType, - SPDX_NAMESPACE[f"relationshipType_{snake_case_to_camel_case(relationship.relationship_type.name)}"])) + graph.add( + ( + relationship_node, + SPDX_NAMESPACE.relationshipType, + SPDX_NAMESPACE[f"relationshipType_{snake_case_to_camel_case(relationship.relationship_type.name)}"], + ) + ) if isinstance(relationship.related_spdx_element_id, SpdxNone): graph.add((relationship_node, SPDX_NAMESPACE.relatedSpdxElement, SPDX_NAMESPACE.none)) elif isinstance(relationship.related_spdx_element_id, SpdxNoAssertion): graph.add((relationship_node, SPDX_NAMESPACE.relatedSpdxElement, SPDX_NAMESPACE.noassertion)) else: - graph.add((relationship_node, SPDX_NAMESPACE.relatedSpdxElement, - URIRef(add_namespace_to_spdx_id(relationship.related_spdx_element_id, doc_namespace, - external_doc_ref_to_namespace)))) + graph.add( + ( + relationship_node, + SPDX_NAMESPACE.relatedSpdxElement, + URIRef( + add_namespace_to_spdx_id( + relationship.related_spdx_element_id, doc_namespace, external_doc_ref_to_namespace + ) + ), + ) + ) graph.add((relationship_node, RDFS.comment, Literal(relationship.comment))) relationship_resource = URIRef( - add_namespace_to_spdx_id(relationship.spdx_element_id, doc_namespace, external_doc_ref_to_namespace)) + add_namespace_to_spdx_id(relationship.spdx_element_id, doc_namespace, external_doc_ref_to_namespace) + ) graph.add((relationship_resource, SPDX_NAMESPACE.relationship, relationship_node)) diff --git a/src/spdx/writer/rdf/snippet_writer.py b/src/spdx/writer/rdf/snippet_writer.py index 94458a78c..ab50ddd9d 100644 --- a/src/spdx/writer/rdf/snippet_writer.py +++ b/src/spdx/writer/rdf/snippet_writer.py @@ -18,23 +18,28 @@ from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id, add_optional_literal -def add_snippet_to_graph(snippet: Snippet, graph: Graph, doc_namespace: str, - external_doc_ref_to_namespace: Dict[str, str]): +def add_snippet_to_graph( + snippet: Snippet, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str] +): snippet_resource = URIRef(add_namespace_to_spdx_id(snippet.spdx_id, doc_namespace, external_doc_ref_to_namespace)) graph.add((snippet_resource, RDF.type, SPDX_NAMESPACE.Snippet)) snippet_from_file_ref = URIRef( - add_namespace_to_spdx_id(snippet.file_spdx_id, doc_namespace, external_doc_ref_to_namespace)) - graph.add((snippet_resource, SPDX_NAMESPACE.snippetFromFile, - snippet_from_file_ref)) - add_range_to_graph(snippet.byte_range, graph, snippet_resource, snippet_from_file_ref, - POINTER_NAMESPACE.ByteOffsetPointer) - add_range_to_graph(snippet.line_range, graph, snippet_resource, snippet_from_file_ref, - POINTER_NAMESPACE.LineCharPointer) - add_license_expression_or_none_or_no_assertion(snippet.license_concluded, graph, snippet_resource, - SPDX_NAMESPACE.licenseConcluded, doc_namespace) - add_license_expression_or_none_or_no_assertion(snippet.license_info_in_snippet, graph, snippet_resource, - SPDX_NAMESPACE.licenseInfoInSnippet, doc_namespace) + add_namespace_to_spdx_id(snippet.file_spdx_id, doc_namespace, external_doc_ref_to_namespace) + ) + graph.add((snippet_resource, SPDX_NAMESPACE.snippetFromFile, snippet_from_file_ref)) + add_range_to_graph( + snippet.byte_range, graph, snippet_resource, snippet_from_file_ref, POINTER_NAMESPACE.ByteOffsetPointer + ) + add_range_to_graph( + snippet.line_range, graph, snippet_resource, snippet_from_file_ref, POINTER_NAMESPACE.LineCharPointer + ) + add_license_expression_or_none_or_no_assertion( + snippet.license_concluded, graph, snippet_resource, SPDX_NAMESPACE.licenseConcluded, doc_namespace + ) + add_license_expression_or_none_or_no_assertion( + snippet.license_info_in_snippet, graph, snippet_resource, SPDX_NAMESPACE.licenseInfoInSnippet, doc_namespace + ) add_optional_literal(snippet.license_comment, graph, snippet_resource, SPDX_NAMESPACE.licenseComments) add_optional_literal(snippet.copyright_text, graph, snippet_resource, SPDX_NAMESPACE.copyrightText) add_optional_literal(snippet.comment, graph, snippet_resource, RDFS.comment) @@ -43,12 +48,19 @@ def add_snippet_to_graph(snippet: Snippet, graph: Graph, doc_namespace: str, graph.add((snippet_resource, SPDX_NAMESPACE.attributionText, Literal(attribution_text))) -def add_range_to_graph(range_information: Optional[Tuple[int, int]], graph: Graph, snippet_node: URIRef, - snippet_from_file_ref: URIRef, pointer_class: URIRef): +def add_range_to_graph( + range_information: Optional[Tuple[int, int]], + graph: Graph, + snippet_node: URIRef, + snippet_from_file_ref: URIRef, + pointer_class: URIRef, +): start_end_pointer = BNode() graph.add((start_end_pointer, RDF.type, POINTER_NAMESPACE.StartEndPointer)) - for (predicate, value) in [(POINTER_NAMESPACE.startPointer, range_information[0]), - (POINTER_NAMESPACE.endPointer, range_information[1])]: + for predicate, value in [ + (POINTER_NAMESPACE.startPointer, range_information[0]), + (POINTER_NAMESPACE.endPointer, range_information[1]), + ]: pointer_node = BNode() graph.add((pointer_node, RDF.type, pointer_class)) graph.add((start_end_pointer, predicate, pointer_node)) diff --git a/src/spdx/writer/tagvalue/checksum_writer.py b/src/spdx/writer/tagvalue/checksum_writer.py index 80df31e35..230c0dbfc 100644 --- a/src/spdx/writer/tagvalue/checksum_writer.py +++ b/src/spdx/writer/tagvalue/checksum_writer.py @@ -27,5 +27,5 @@ def write_checksum_to_tag_value(checksum: Checksum) -> str: ChecksumAlgorithm.BLAKE2B_512.name: "BLAKE2b-512", ChecksumAlgorithm.SHA3_256.name: "SHA3-256", ChecksumAlgorithm.SHA3_384.name: "SHA3-384", - ChecksumAlgorithm.SHA3_512.name: "SHA3-512" + ChecksumAlgorithm.SHA3_512.name: "SHA3-512", } diff --git a/src/spdx/writer/tagvalue/creation_info_writer.py b/src/spdx/writer/tagvalue/creation_info_writer.py index 53d2da41e..798f7ed21 100644 --- a/src/spdx/writer/tagvalue/creation_info_writer.py +++ b/src/spdx/writer/tagvalue/creation_info_writer.py @@ -30,8 +30,13 @@ def write_creation_info(creation_info: CreationInfo, text_output: TextIO): write_optional_heading(creation_info.external_document_refs, "\n## External Document References\n", text_output) for external_document_ref in creation_info.external_document_refs: - external_document_ref_str = " ".join([external_document_ref.document_ref_id, external_document_ref.document_uri, - external_document_ref.checksum.algorithm.name + ": " + external_document_ref.checksum.value]) + external_document_ref_str = " ".join( + [ + external_document_ref.document_ref_id, + external_document_ref.document_uri, + external_document_ref.checksum.algorithm.name + ": " + external_document_ref.checksum.value, + ] + ) write_value("ExternalDocumentRef", external_document_ref_str, text_output) write_separator(text_output) diff --git a/src/spdx/writer/tagvalue/package_writer.py b/src/spdx/writer/tagvalue/package_writer.py index 0a6fbd283..4a7924685 100644 --- a/src/spdx/writer/tagvalue/package_writer.py +++ b/src/spdx/writer/tagvalue/package_writer.py @@ -56,8 +56,11 @@ def write_package(package: Package, text_output: TextIO): for external_reference in package.external_references: external_reference_str = " ".join( - [transform_enum_name_to_tv(external_reference.category.name), external_reference.reference_type, - external_reference.locator] + [ + transform_enum_name_to_tv(external_reference.category.name), + external_reference.reference_type, + external_reference.locator, + ] ) write_value("ExternalRef", external_reference_str, text_output) if external_reference.comment: @@ -67,8 +70,9 @@ def write_package(package: Package, text_output: TextIO): write_text_value("PackageAttributionText", attribution_text, text_output) if package.primary_package_purpose: - write_value("PrimaryPackagePurpose", transform_enum_name_to_tv(package.primary_package_purpose.name), - text_output) + write_value( + "PrimaryPackagePurpose", transform_enum_name_to_tv(package.primary_package_purpose.name), text_output + ) if package.release_date: write_value("ReleaseDate", datetime_to_iso_string(package.release_date), text_output) diff --git a/src/spdx/writer/tagvalue/relationship_writer.py b/src/spdx/writer/tagvalue/relationship_writer.py index 4af58466c..9cf7425fc 100644 --- a/src/spdx/writer/tagvalue/relationship_writer.py +++ b/src/spdx/writer/tagvalue/relationship_writer.py @@ -15,7 +15,15 @@ def write_relationship(relationship: Relationship, text_output: TextIO): - write_value("Relationship", " ".join( - [relationship.spdx_element_id, relationship.relationship_type.name, str(relationship.related_spdx_element_id)]), - text_output) + write_value( + "Relationship", + " ".join( + [ + relationship.spdx_element_id, + relationship.relationship_type.name, + str(relationship.related_spdx_element_id), + ] + ), + text_output, + ) write_text_value("RelationshipComment", relationship.comment, text_output) diff --git a/src/spdx/writer/tagvalue/tagvalue_writer.py b/src/spdx/writer/tagvalue/tagvalue_writer.py index 2fc36bbea..3c94e3dc4 100644 --- a/src/spdx/writer/tagvalue/tagvalue_writer.py +++ b/src/spdx/writer/tagvalue/tagvalue_writer.py @@ -40,13 +40,14 @@ def write_document_to_file(document: Document, file_name: str, validate: bool = def write_document(document: Document, text_output: TextIO): - relationships_to_write, contained_files_by_package_id = scan_relationships(document.relationships, - document.packages, document.files) + relationships_to_write, contained_files_by_package_id = scan_relationships( + document.relationships, document.packages, document.files + ) file_ids_with_contained_snippets = get_file_ids_with_contained_snippets(document.snippets, document.files) - packaged_file_ids = [file.spdx_id for files_list in contained_files_by_package_id.values() - for file in files_list] - filed_snippet_ids = [snippet.spdx_id for snippets_list in file_ids_with_contained_snippets.values() - for snippet in snippets_list] + packaged_file_ids = [file.spdx_id for files_list in contained_files_by_package_id.values() for file in files_list] + filed_snippet_ids = [ + snippet.spdx_id for snippets_list in file_ids_with_contained_snippets.values() for snippet in snippets_list + ] text_output.write("## Document Information\n") write_creation_info(document.creation_info, text_output) @@ -62,8 +63,9 @@ def write_document(document: Document, text_output: TextIO): write_file(file, text_output) write_separator(text_output) if file.spdx_id in file_ids_with_contained_snippets: - write_list_of_elements(file_ids_with_contained_snippets[file.spdx_id], write_snippet, text_output, - with_separator=True) + write_list_of_elements( + file_ids_with_contained_snippets[file.spdx_id], write_snippet, text_output, with_separator=True + ) for package in document.packages: write_package(package, text_output) @@ -73,12 +75,14 @@ def write_document(document: Document, text_output: TextIO): write_file(file, text_output) write_separator(text_output) if file.spdx_id in file_ids_with_contained_snippets: - write_list_of_elements(file_ids_with_contained_snippets[file.spdx_id], write_snippet, text_output, - with_separator=True) + write_list_of_elements( + file_ids_with_contained_snippets[file.spdx_id], write_snippet, text_output, with_separator=True + ) write_optional_heading(document.extracted_licensing_info, "## License Information\n", text_output) - write_list_of_elements(document.extracted_licensing_info, write_extracted_licensing_info, text_output, - with_separator=True) + write_list_of_elements( + document.extracted_licensing_info, write_extracted_licensing_info, text_output, with_separator=True + ) write_optional_heading(relationships_to_write, "## Relationships\n", text_output) write_list_of_elements(relationships_to_write, write_relationship, text_output) diff --git a/src/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py b/src/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py index 3b2d8518d..7b3ad849b 100644 --- a/src/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py +++ b/src/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py @@ -25,7 +25,9 @@ def write_separator(out: TextIO): out.write("\n") -def write_value(tag: str, value: Optional[Union[bool, str, SpdxNone, SpdxNoAssertion, LicenseExpression]], out: TextIO): +def write_value( + tag: str, value: Optional[Union[bool, str, SpdxNone, SpdxNoAssertion, LicenseExpression]], out: TextIO +): if value is not None: out.write(f"{tag}: {value}\n") @@ -51,8 +53,12 @@ def write_optional_heading(optional_field: Any, heading: str, text_output: TextI text_output.write(heading) -def write_list_of_elements(list_of_elements: List[Any], write_method: Callable[[Any, TextIO], None], - text_output: TextIO, with_separator: bool = False): +def write_list_of_elements( + list_of_elements: List[Any], + write_method: Callable[[Any, TextIO], None], + text_output: TextIO, + with_separator: bool = False, +): for element in list_of_elements: write_method(element, text_output) if with_separator: @@ -66,25 +72,32 @@ def write_actor(tag: str, element_to_write: Optional[Union[Actor, SpdxNoAssertio write_value(tag, element_to_write, text_output) -def scan_relationships(relationships: List[Relationship], packages: List[Package], files: List[File]) \ - -> Tuple[List, Dict]: +def scan_relationships( + relationships: List[Relationship], packages: List[Package], files: List[File] +) -> Tuple[List, Dict]: contained_files_by_package_id = dict() relationships_to_write = [] files_by_spdx_id = {file.spdx_id: file for file in files} packages_spdx_ids = [package.spdx_id for package in packages] for relationship in relationships: - if relationship.relationship_type == RelationshipType.CONTAINS and \ - relationship.spdx_element_id in packages_spdx_ids and \ - relationship.related_spdx_element_id in files_by_spdx_id.keys(): + if ( + relationship.relationship_type == RelationshipType.CONTAINS + and relationship.spdx_element_id in packages_spdx_ids + and relationship.related_spdx_element_id in files_by_spdx_id.keys() + ): contained_files_by_package_id.setdefault(relationship.spdx_element_id, []).append( - files_by_spdx_id[relationship.related_spdx_element_id]) + files_by_spdx_id[relationship.related_spdx_element_id] + ) if relationship.comment: relationships_to_write.append(relationship) - elif relationship.relationship_type == RelationshipType.CONTAINED_BY and \ - relationship.related_spdx_element_id in packages_spdx_ids and \ - relationship.spdx_element_id in files_by_spdx_id: + elif ( + relationship.relationship_type == RelationshipType.CONTAINED_BY + and relationship.related_spdx_element_id in packages_spdx_ids + and relationship.spdx_element_id in files_by_spdx_id + ): contained_files_by_package_id.setdefault(relationship.related_spdx_element_id, []).append( - files_by_spdx_id[relationship.spdx_element_id]) + files_by_spdx_id[relationship.spdx_element_id] + ) if relationship.comment: relationships_to_write.append(relationship) else: diff --git a/src/spdx/writer/xml/xml_writer.py b/src/spdx/writer/xml/xml_writer.py index 369bbfedc..d347b7d6d 100644 --- a/src/spdx/writer/xml/xml_writer.py +++ b/src/spdx/writer/xml/xml_writer.py @@ -18,8 +18,9 @@ from spdx.validation.validation_message import ValidationMessage -def write_document_to_file(document: Document, file_name: str, validate: bool = True, - converter: DocumentConverter = None): +def write_document_to_file( + document: Document, file_name: str, validate: bool = True, converter: DocumentConverter = None +): """ Serializes the provided document to XML and writes it to a file with the provided name. Unless validate is set to False, validates the document before serialization. Unless a DocumentConverter instance is provided, diff --git a/src/spdx/writer/yaml/yaml_writer.py b/src/spdx/writer/yaml/yaml_writer.py index 2db63cb8c..2dc365f95 100644 --- a/src/spdx/writer/yaml/yaml_writer.py +++ b/src/spdx/writer/yaml/yaml_writer.py @@ -18,8 +18,9 @@ from spdx.validation.validation_message import ValidationMessage -def write_document_to_file(document: Document, file_name: str, validate: bool = True, - converter: DocumentConverter = None): +def write_document_to_file( + document: Document, file_name: str, validate: bool = True, converter: DocumentConverter = None +): """ Serializes the provided document to yaml and writes it to a file with the provided name. Unless validate is set to False, validates the document before serialization. Unless a DocumentConverter instance is provided, diff --git a/tests/spdx/fixtures.py b/tests/spdx/fixtures.py index 3191678a9..56e6d2271 100644 --- a/tests/spdx/fixtures.py +++ b/tests/spdx/fixtures.py @@ -44,125 +44,270 @@ def checksum_fixture(algorithm=ChecksumAlgorithm.SHA1, value="71c4025dd9897b364f return Checksum(algorithm, value) -def package_verification_code_fixture(value="85ed0817af83a24ad8da68c2b5094de69833983c", - excluded_files=None) -> PackageVerificationCode: +def package_verification_code_fixture( + value="85ed0817af83a24ad8da68c2b5094de69833983c", excluded_files=None +) -> PackageVerificationCode: excluded_files = ["./exclude.py"] if excluded_files is None else excluded_files return PackageVerificationCode(value, excluded_files) -def creation_info_fixture(spdx_version="SPDX-2.3", spdx_id="SPDXRef-DOCUMENT", name="documentName", - document_namespace="https://some.namespace", creators=None, created=datetime(2022, 12, 1), - creator_comment="creatorComment", data_license="CC0-1.0", external_document_refs=None, - license_list_version=Version(3, 19), document_comment="documentComment") -> CreationInfo: +def creation_info_fixture( + spdx_version="SPDX-2.3", + spdx_id="SPDXRef-DOCUMENT", + name="documentName", + document_namespace="https://some.namespace", + creators=None, + created=datetime(2022, 12, 1), + creator_comment="creatorComment", + data_license="CC0-1.0", + external_document_refs=None, + license_list_version=Version(3, 19), + document_comment="documentComment", +) -> CreationInfo: creators = [actor_fixture(name="creatorName")] if creators is None else creators - external_document_refs = [ - external_document_ref_fixture()] if external_document_refs is None else external_document_refs - return CreationInfo(spdx_version, spdx_id, name, document_namespace, creators, created, creator_comment, - data_license, - external_document_refs, license_list_version, document_comment) + external_document_refs = ( + [external_document_ref_fixture()] if external_document_refs is None else external_document_refs + ) + return CreationInfo( + spdx_version, + spdx_id, + name, + document_namespace, + creators, + created, + creator_comment, + data_license, + external_document_refs, + license_list_version, + document_comment, + ) -def file_fixture(name="./fileName.py", spdx_id="SPDXRef-File", checksums=None, file_types=None, - license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"), license_info_in_file=None, - license_comment="licenseComment", copyright_text="copyrightText", comment="fileComment", - notice="fileNotice", contributors=None, attribution_texts=None) -> File: +def file_fixture( + name="./fileName.py", + spdx_id="SPDXRef-File", + checksums=None, + file_types=None, + license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"), + license_info_in_file=None, + license_comment="licenseComment", + copyright_text="copyrightText", + comment="fileComment", + notice="fileNotice", + contributors=None, + attribution_texts=None, +) -> File: checksums = [checksum_fixture()] if checksums is None else checksums file_types = [FileType.TEXT] if file_types is None else file_types - license_info_in_file = [get_spdx_licensing().parse("MIT"), - get_spdx_licensing().parse("GPL-2.0"), - SpdxNoAssertion()] if license_info_in_file is None else license_info_in_file + license_info_in_file = ( + [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()] + if license_info_in_file is None + else license_info_in_file + ) contributors = ["fileContributor"] if contributors is None else contributors attribution_texts = ["fileAttributionText"] if attribution_texts is None else attribution_texts - return File(name=name, spdx_id=spdx_id, checksums=checksums, file_types=file_types, - license_concluded=license_concluded, license_info_in_file=license_info_in_file, - license_comment=license_comment, copyright_text=copyright_text, comment=comment, notice=notice, - contributors=contributors, attribution_texts=attribution_texts) - - -def package_fixture(spdx_id="SPDXRef-Package", name="packageName", download_location="https://download.com", - version="12.2", file_name="./packageFileName", - supplier=actor_fixture(name="supplierName"), originator=actor_fixture(name="originatorName"), - files_analyzed=True, verification_code=package_verification_code_fixture(), checksums=None, - homepage="https://homepage.com", source_info="sourceInfo", - license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"), license_info_from_files=None, - license_declared=get_spdx_licensing().parse("MIT and GPL-2.0"), - license_comment="packageLicenseComment", copyright_text="packageCopyrightText", - summary="packageSummary", description="packageDescription", comment="packageComment", - external_references=None, attribution_texts=None, primary_package_purpose=PackagePurpose.SOURCE, - release_date=datetime(2022, 12, 1), built_date=datetime(2022, 12, 2), - valid_until_date=datetime(2022, 12, 3)) -> Package: + return File( + name=name, + spdx_id=spdx_id, + checksums=checksums, + file_types=file_types, + license_concluded=license_concluded, + license_info_in_file=license_info_in_file, + license_comment=license_comment, + copyright_text=copyright_text, + comment=comment, + notice=notice, + contributors=contributors, + attribution_texts=attribution_texts, + ) + + +def package_fixture( + spdx_id="SPDXRef-Package", + name="packageName", + download_location="https://download.com", + version="12.2", + file_name="./packageFileName", + supplier=actor_fixture(name="supplierName"), + originator=actor_fixture(name="originatorName"), + files_analyzed=True, + verification_code=package_verification_code_fixture(), + checksums=None, + homepage="https://homepage.com", + source_info="sourceInfo", + license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"), + license_info_from_files=None, + license_declared=get_spdx_licensing().parse("MIT and GPL-2.0"), + license_comment="packageLicenseComment", + copyright_text="packageCopyrightText", + summary="packageSummary", + description="packageDescription", + comment="packageComment", + external_references=None, + attribution_texts=None, + primary_package_purpose=PackagePurpose.SOURCE, + release_date=datetime(2022, 12, 1), + built_date=datetime(2022, 12, 2), + valid_until_date=datetime(2022, 12, 3), +) -> Package: checksums = [checksum_fixture()] if checksums is None else checksums - license_info_from_files = [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse( - "GPL-2.0"), SpdxNoAssertion()] if license_info_from_files is None else license_info_from_files + license_info_from_files = ( + [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()] + if license_info_from_files is None + else license_info_from_files + ) external_references = [external_package_ref_fixture()] if external_references is None else external_references attribution_texts = ["packageAttributionText"] if attribution_texts is None else attribution_texts - return Package(spdx_id=spdx_id, name=name, download_location=download_location, version=version, - file_name=file_name, supplier=supplier, originator=originator, files_analyzed=files_analyzed, - verification_code=verification_code, checksums=checksums, homepage=homepage, source_info=source_info, - license_concluded=license_concluded, license_info_from_files=license_info_from_files, - license_declared=license_declared, license_comment=license_comment, copyright_text=copyright_text, - summary=summary, description=description, comment=comment, external_references=external_references, - attribution_texts=attribution_texts, primary_package_purpose=primary_package_purpose, - release_date=release_date, built_date=built_date, valid_until_date=valid_until_date) - - -def external_document_ref_fixture(document_ref_id="DocumentRef-external", document_uri="https://namespace.com", - checksum=checksum_fixture()) -> ExternalDocumentRef: + return Package( + spdx_id=spdx_id, + name=name, + download_location=download_location, + version=version, + file_name=file_name, + supplier=supplier, + originator=originator, + files_analyzed=files_analyzed, + verification_code=verification_code, + checksums=checksums, + homepage=homepage, + source_info=source_info, + license_concluded=license_concluded, + license_info_from_files=license_info_from_files, + license_declared=license_declared, + license_comment=license_comment, + copyright_text=copyright_text, + summary=summary, + description=description, + comment=comment, + external_references=external_references, + attribution_texts=attribution_texts, + primary_package_purpose=primary_package_purpose, + release_date=release_date, + built_date=built_date, + valid_until_date=valid_until_date, + ) + + +def external_document_ref_fixture( + document_ref_id="DocumentRef-external", document_uri="https://namespace.com", checksum=checksum_fixture() +) -> ExternalDocumentRef: return ExternalDocumentRef(document_ref_id=document_ref_id, document_uri=document_uri, checksum=checksum) -def external_package_ref_fixture(category=ExternalPackageRefCategory.PACKAGE_MANAGER, - reference_type="maven-central", - locator="org.apache.tomcat:tomcat:9.0.0.M4", - comment="externalPackageRefComment") -> ExternalPackageRef: +def external_package_ref_fixture( + category=ExternalPackageRefCategory.PACKAGE_MANAGER, + reference_type="maven-central", + locator="org.apache.tomcat:tomcat:9.0.0.M4", + comment="externalPackageRefComment", +) -> ExternalPackageRef: return ExternalPackageRef(category=category, reference_type=reference_type, locator=locator, comment=comment) -def snippet_fixture(spdx_id="SPDXRef-Snippet", file_spdx_id="SPDXRef-File", byte_range=(1, 2), - line_range=(3, 4), license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"), - license_info_in_snippet=None, license_comment="snippetLicenseComment", - copyright_text="licenseCopyrightText", comment="snippetComment", name="snippetName", - attribution_texts=None) -> Snippet: - license_info_in_snippet = [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse( - "GPL-2.0"), SpdxNone()] if license_info_in_snippet is None else license_info_in_snippet +def snippet_fixture( + spdx_id="SPDXRef-Snippet", + file_spdx_id="SPDXRef-File", + byte_range=(1, 2), + line_range=(3, 4), + license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"), + license_info_in_snippet=None, + license_comment="snippetLicenseComment", + copyright_text="licenseCopyrightText", + comment="snippetComment", + name="snippetName", + attribution_texts=None, +) -> Snippet: + license_info_in_snippet = ( + [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNone()] + if license_info_in_snippet is None + else license_info_in_snippet + ) attribution_texts = ["snippetAttributionText"] if attribution_texts is None else attribution_texts - return Snippet(spdx_id=spdx_id, file_spdx_id=file_spdx_id, byte_range=byte_range, line_range=line_range, - license_concluded=license_concluded, license_info_in_snippet=license_info_in_snippet, - license_comment=license_comment, copyright_text=copyright_text, comment=comment, name=name, - attribution_texts=attribution_texts) + return Snippet( + spdx_id=spdx_id, + file_spdx_id=file_spdx_id, + byte_range=byte_range, + line_range=line_range, + license_concluded=license_concluded, + license_info_in_snippet=license_info_in_snippet, + license_comment=license_comment, + copyright_text=copyright_text, + comment=comment, + name=name, + attribution_texts=attribution_texts, + ) -def annotation_fixture(spdx_id="SPDXRef-File", annotation_type=AnnotationType.REVIEW, - annotator=actor_fixture(name="annotatorName"), annotation_date=datetime(2022, 12, 1), - annotation_comment="annotationComment") -> Annotation: - return Annotation(spdx_id=spdx_id, annotation_type=annotation_type, annotator=annotator, - annotation_date=annotation_date, annotation_comment=annotation_comment) +def annotation_fixture( + spdx_id="SPDXRef-File", + annotation_type=AnnotationType.REVIEW, + annotator=actor_fixture(name="annotatorName"), + annotation_date=datetime(2022, 12, 1), + annotation_comment="annotationComment", +) -> Annotation: + return Annotation( + spdx_id=spdx_id, + annotation_type=annotation_type, + annotator=annotator, + annotation_date=annotation_date, + annotation_comment=annotation_comment, + ) -def extracted_licensing_info_fixture(license_id="LicenseRef-1", extracted_text="extractedText", - license_name="licenseName", - cross_references=None, comment="licenseComment") -> ExtractedLicensingInfo: +def extracted_licensing_info_fixture( + license_id="LicenseRef-1", + extracted_text="extractedText", + license_name="licenseName", + cross_references=None, + comment="licenseComment", +) -> ExtractedLicensingInfo: cross_references = ["https://see.also"] if cross_references is None else cross_references - return ExtractedLicensingInfo(license_id=license_id, extracted_text=extracted_text, license_name=license_name, - cross_references=cross_references, comment=comment) + return ExtractedLicensingInfo( + license_id=license_id, + extracted_text=extracted_text, + license_name=license_name, + cross_references=cross_references, + comment=comment, + ) -def relationship_fixture(spdx_element_id="SPDXRef-DOCUMENT", relationship_type=RelationshipType.DESCRIBES, - related_spdx_element_id="SPDXRef-File", comment="relationshipComment") -> Relationship: - return Relationship(spdx_element_id=spdx_element_id, relationship_type=relationship_type, - related_spdx_element_id=related_spdx_element_id, comment=comment) +def relationship_fixture( + spdx_element_id="SPDXRef-DOCUMENT", + relationship_type=RelationshipType.DESCRIBES, + related_spdx_element_id="SPDXRef-File", + comment="relationshipComment", +) -> Relationship: + return Relationship( + spdx_element_id=spdx_element_id, + relationship_type=relationship_type, + related_spdx_element_id=related_spdx_element_id, + comment=comment, + ) -def document_fixture(creation_info=None, packages=None, files=None, snippets=None, annotations=None, relationships=None, - extracted_licensing_info=None) -> Document: +def document_fixture( + creation_info=None, + packages=None, + files=None, + snippets=None, + annotations=None, + relationships=None, + extracted_licensing_info=None, +) -> Document: creation_info = creation_info_fixture() if creation_info is None else creation_info packages = [package_fixture()] if packages is None else packages files = [file_fixture()] if files is None else files snippets = [snippet_fixture()] if snippets is None else snippets annotations = [annotation_fixture()] if annotations is None else annotations relationships = [relationship_fixture()] if relationships is None else relationships - extracted_licensing_info = [ - extracted_licensing_info_fixture()] if extracted_licensing_info is None else extracted_licensing_info - return Document(creation_info=creation_info, packages=packages, files=files, snippets=snippets, - annotations=annotations, relationships=relationships, - extracted_licensing_info=extracted_licensing_info) + extracted_licensing_info = ( + [extracted_licensing_info_fixture()] if extracted_licensing_info is None else extracted_licensing_info + ) + return Document( + creation_info=creation_info, + packages=packages, + files=files, + snippets=snippets, + annotations=annotations, + relationships=relationships, + extracted_licensing_info=extracted_licensing_info, + ) diff --git a/tests/spdx/jsonschema/test_annotation_converter.py b/tests/spdx/jsonschema/test_annotation_converter.py index b843ff275..15b2d17f8 100644 --- a/tests/spdx/jsonschema/test_annotation_converter.py +++ b/tests/spdx/jsonschema/test_annotation_converter.py @@ -24,10 +24,15 @@ def converter() -> AnnotationConverter: return AnnotationConverter() -@pytest.mark.parametrize("annotation_property,expected", [(AnnotationProperty.ANNOTATION_DATE, "annotationDate"), - (AnnotationProperty.ANNOTATION_TYPE, "annotationType"), - (AnnotationProperty.ANNOTATOR, "annotator"), - (AnnotationProperty.COMMENT, "comment")]) +@pytest.mark.parametrize( + "annotation_property,expected", + [ + (AnnotationProperty.ANNOTATION_DATE, "annotationDate"), + (AnnotationProperty.ANNOTATION_TYPE, "annotationType"), + (AnnotationProperty.ANNOTATOR, "annotator"), + (AnnotationProperty.COMMENT, "comment"), + ], +) def test_json_property_names(converter: AnnotationConverter, annotation_property: AnnotationProperty, expected: str): assert converter.json_property_name(annotation_property) == expected @@ -43,8 +48,7 @@ def test_data_model_type(converter: AnnotationConverter): def test_successful_conversion(converter: AnnotationConverter): date = datetime(2022, 12, 1) annotator = Actor(ActorType.PERSON, "actorName") - annotation = Annotation("spdxId", AnnotationType.REVIEW, annotator, - date, "comment") + annotation = Annotation("spdxId", AnnotationType.REVIEW, annotator, date, "comment") converted_dict = converter.convert(annotation) @@ -52,5 +56,5 @@ def test_successful_conversion(converter: AnnotationConverter): converter.json_property_name(AnnotationProperty.ANNOTATION_DATE): datetime_to_iso_string(date), converter.json_property_name(AnnotationProperty.ANNOTATION_TYPE): "REVIEW", converter.json_property_name(AnnotationProperty.ANNOTATOR): annotator.to_serialized_string(), - converter.json_property_name(AnnotationProperty.COMMENT): "comment" + converter.json_property_name(AnnotationProperty.COMMENT): "comment", } diff --git a/tests/spdx/jsonschema/test_checksum_converter.py b/tests/spdx/jsonschema/test_checksum_converter.py index 857745b7c..60393d7e6 100644 --- a/tests/spdx/jsonschema/test_checksum_converter.py +++ b/tests/spdx/jsonschema/test_checksum_converter.py @@ -20,8 +20,10 @@ def converter() -> ChecksumConverter: return ChecksumConverter() -@pytest.mark.parametrize("checksum_property,expected", [(ChecksumProperty.ALGORITHM, "algorithm"), - (ChecksumProperty.CHECKSUM_VALUE, "checksumValue")]) +@pytest.mark.parametrize( + "checksum_property,expected", + [(ChecksumProperty.ALGORITHM, "algorithm"), (ChecksumProperty.CHECKSUM_VALUE, "checksumValue")], +) def test_json_property_names(converter: ChecksumConverter, checksum_property: ChecksumProperty, expected: str): assert converter.json_property_name(checksum_property) == expected @@ -33,7 +35,7 @@ def test_successful_conversion(converter: ChecksumConverter): assert converted_dict == { converter.json_property_name(ChecksumProperty.ALGORITHM): "SHA1", - converter.json_property_name(ChecksumProperty.CHECKSUM_VALUE): "123" + converter.json_property_name(ChecksumProperty.CHECKSUM_VALUE): "123", } diff --git a/tests/spdx/jsonschema/test_converter.py b/tests/spdx/jsonschema/test_converter.py index 20b8bed01..e5dff510b 100644 --- a/tests/spdx/jsonschema/test_converter.py +++ b/tests/spdx/jsonschema/test_converter.py @@ -43,8 +43,9 @@ def json_property_name(self, test_property: TestPropertyType) -> str: else: return "jsonSecondName" - def _get_property_value(self, instance: TestDataModelType, test_property: TestPropertyType, - _document: Document = None) -> Any: + def _get_property_value( + self, instance: TestDataModelType, test_property: TestPropertyType, _document: Document = None + ) -> Any: if test_property == TestPropertyType.FIRST_NAME: return instance.first_property elif test_property == TestPropertyType.SECOND_NAME: @@ -63,10 +64,7 @@ def test_conversion(): converted_dict = converter.convert(test_instance) - assert converted_dict == { - "jsonFirstName": "firstPropertyValue", - "jsonSecondName": 3 - } + assert converted_dict == {"jsonFirstName": "firstPropertyValue", "jsonSecondName": 3} def test_wrong_type(): diff --git a/tests/spdx/jsonschema/test_creation_info_converter.py b/tests/spdx/jsonschema/test_creation_info_converter.py index 7e20cbbbe..f527b586f 100644 --- a/tests/spdx/jsonschema/test_creation_info_converter.py +++ b/tests/spdx/jsonschema/test_creation_info_converter.py @@ -26,12 +26,18 @@ def converter() -> CreationInfoConverter: return CreationInfoConverter() -@pytest.mark.parametrize("creation_info_property,expected", - [(CreationInfoProperty.CREATED, "created"), (CreationInfoProperty.CREATORS, "creators"), - (CreationInfoProperty.LICENSE_LIST_VERSION, "licenseListVersion"), - (CreationInfoProperty.COMMENT, "comment")]) -def test_json_property_names(converter: CreationInfoConverter, creation_info_property: CreationInfoProperty, - expected: str): +@pytest.mark.parametrize( + "creation_info_property,expected", + [ + (CreationInfoProperty.CREATED, "created"), + (CreationInfoProperty.CREATORS, "creators"), + (CreationInfoProperty.LICENSE_LIST_VERSION, "licenseListVersion"), + (CreationInfoProperty.COMMENT, "comment"), + ], +) +def test_json_property_names( + converter: CreationInfoConverter, creation_info_property: CreationInfoProperty, expected: str +): assert converter.json_property_name(creation_info_property) == expected @@ -40,14 +46,16 @@ def test_successful_conversion(converter: CreationInfoConverter): created = datetime(2022, 12, 1) converted_dict = converter.convert( - creation_info_fixture(creators=creators, created=created, creator_comment="comment", - license_list_version=Version(1, 2))) + creation_info_fixture( + creators=creators, created=created, creator_comment="comment", license_list_version=Version(1, 2) + ) + ) assert converted_dict == { converter.json_property_name(CreationInfoProperty.CREATED): datetime_to_iso_string(created), converter.json_property_name(CreationInfoProperty.CREATORS): ["Person: personName", "Tool: toolName"], converter.json_property_name(CreationInfoProperty.LICENSE_LIST_VERSION): "1.2", - converter.json_property_name(CreationInfoProperty.COMMENT): "comment" + converter.json_property_name(CreationInfoProperty.COMMENT): "comment", } diff --git a/tests/spdx/jsonschema/test_document_converter.py b/tests/spdx/jsonschema/test_document_converter.py index f2742ce26..8832b852f 100644 --- a/tests/spdx/jsonschema/test_document_converter.py +++ b/tests/spdx/jsonschema/test_document_converter.py @@ -38,18 +38,24 @@ @pytest.fixture -@mock.patch('spdx.jsonschema.creation_info_converter.CreationInfoConverter', autospec=True) -@mock.patch('spdx.jsonschema.external_document_ref_converter.ExternalDocumentRefConverter', autospec=True) -@mock.patch('spdx.jsonschema.package_converter.PackageConverter', autospec=True) -@mock.patch('spdx.jsonschema.annotation_converter.AnnotationConverter', autospec=True) -@mock.patch('spdx.jsonschema.extracted_licensing_info_converter.ExtractedLicensingInfoConverter', autospec=True) -@mock.patch('spdx.jsonschema.file_converter.FileConverter', autospec=True) -@mock.patch('spdx.jsonschema.snippet_converter.SnippetConverter', autospec=True) -@mock.patch('spdx.jsonschema.relationship_converter.RelationshipConverter', autospec=True) -def converter(relationship_converter_mock: MagicMock, snippet_converter_mock: MagicMock, file_converter_mock: MagicMock, - extracted_licensing_info_converter_mock: MagicMock, annotation_converter_mock: MagicMock, - package_converter_mock: MagicMock, external_ref_converter_mock: MagicMock, - creation_info_converter_mock: MagicMock) -> DocumentConverter: +@mock.patch("spdx.jsonschema.creation_info_converter.CreationInfoConverter", autospec=True) +@mock.patch("spdx.jsonschema.external_document_ref_converter.ExternalDocumentRefConverter", autospec=True) +@mock.patch("spdx.jsonschema.package_converter.PackageConverter", autospec=True) +@mock.patch("spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) +@mock.patch("spdx.jsonschema.extracted_licensing_info_converter.ExtractedLicensingInfoConverter", autospec=True) +@mock.patch("spdx.jsonschema.file_converter.FileConverter", autospec=True) +@mock.patch("spdx.jsonschema.snippet_converter.SnippetConverter", autospec=True) +@mock.patch("spdx.jsonschema.relationship_converter.RelationshipConverter", autospec=True) +def converter( + relationship_converter_mock: MagicMock, + snippet_converter_mock: MagicMock, + file_converter_mock: MagicMock, + extracted_licensing_info_converter_mock: MagicMock, + annotation_converter_mock: MagicMock, + package_converter_mock: MagicMock, + external_ref_converter_mock: MagicMock, + creation_info_converter_mock: MagicMock, +) -> DocumentConverter: converter = DocumentConverter() converter.creation_info_converter = creation_info_converter_mock() converter.external_document_ref_converter = external_ref_converter_mock() @@ -62,32 +68,59 @@ def converter(relationship_converter_mock: MagicMock, snippet_converter_mock: Ma return converter -@pytest.mark.parametrize("document_property,expected", - [(DocumentProperty.SPDX_VERSION, "spdxVersion"), (DocumentProperty.SPDX_ID, "SPDXID"), - (DocumentProperty.NAME, "name"), (DocumentProperty.DOCUMENT_NAMESPACE, "documentNamespace"), - (DocumentProperty.DATA_LICENSE, "dataLicense"), - (DocumentProperty.EXTERNAL_DOCUMENT_REFS, "externalDocumentRefs"), - (DocumentProperty.COMMENT, "comment"), (DocumentProperty.CREATION_INFO, "creationInfo"), - (DocumentProperty.PACKAGES, "packages"), (DocumentProperty.FILES, "files"), - (DocumentProperty.SNIPPETS, "snippets"), (DocumentProperty.ANNOTATIONS, "annotations"), - (DocumentProperty.RELATIONSHIPS, "relationships"), - (DocumentProperty.HAS_EXTRACTED_LICENSING_INFOS, "hasExtractedLicensingInfos")]) -def test_json_property_names(converter: DocumentConverter, document_property: DocumentProperty, - expected: str): +@pytest.mark.parametrize( + "document_property,expected", + [ + (DocumentProperty.SPDX_VERSION, "spdxVersion"), + (DocumentProperty.SPDX_ID, "SPDXID"), + (DocumentProperty.NAME, "name"), + (DocumentProperty.DOCUMENT_NAMESPACE, "documentNamespace"), + (DocumentProperty.DATA_LICENSE, "dataLicense"), + (DocumentProperty.EXTERNAL_DOCUMENT_REFS, "externalDocumentRefs"), + (DocumentProperty.COMMENT, "comment"), + (DocumentProperty.CREATION_INFO, "creationInfo"), + (DocumentProperty.PACKAGES, "packages"), + (DocumentProperty.FILES, "files"), + (DocumentProperty.SNIPPETS, "snippets"), + (DocumentProperty.ANNOTATIONS, "annotations"), + (DocumentProperty.RELATIONSHIPS, "relationships"), + (DocumentProperty.HAS_EXTRACTED_LICENSING_INFOS, "hasExtractedLicensingInfos"), + ], +) +def test_json_property_names(converter: DocumentConverter, document_property: DocumentProperty, expected: str): assert converter.json_property_name(document_property) == expected def test_successful_conversion(converter: DocumentConverter): - creation_info = creation_info_fixture(spdx_version="spdxVersion", spdx_id="spdxId", name="name", - document_namespace="namespace", document_comment="comment", data_license="dataLicense", - external_document_refs=[external_document_ref_fixture()]) - document = Document(creation_info, annotations=[ - Annotation("annotationId", AnnotationType.REVIEW, Actor(ActorType.PERSON, "reviewerName"), - datetime(2022, 12, 1), "reviewComment")], - extracted_licensing_info=[ExtractedLicensingInfo("licenseId", "licenseText")], relationships=[ + creation_info = creation_info_fixture( + spdx_version="spdxVersion", + spdx_id="spdxId", + name="name", + document_namespace="namespace", + document_comment="comment", + data_license="dataLicense", + external_document_refs=[external_document_ref_fixture()], + ) + document = Document( + creation_info, + annotations=[ + Annotation( + "annotationId", + AnnotationType.REVIEW, + Actor(ActorType.PERSON, "reviewerName"), + datetime(2022, 12, 1), + "reviewComment", + ) + ], + extracted_licensing_info=[ExtractedLicensingInfo("licenseId", "licenseText")], + relationships=[ Relationship(creation_info.spdx_id, RelationshipType.DESCRIBES, "describedElementId"), - Relationship("relationshipOriginId", RelationshipType.AMENDS, "relationShipTargetId")], - packages=[package_fixture()], files=[file_fixture()], snippets=[snippet_fixture()]) + Relationship("relationshipOriginId", RelationshipType.AMENDS, "relationShipTargetId"), + ], + packages=[package_fixture()], + files=[file_fixture()], + snippets=[snippet_fixture()], + ) converter.external_document_ref_converter.convert.return_value = "mock_converted_external_ref" converter.creation_info_converter.convert.return_value = "mock_converted_creation_info" converter.package_converter.convert.return_value = "mock_converted_package" @@ -108,7 +141,8 @@ def test_successful_conversion(converter: DocumentConverter): converter.json_property_name(DocumentProperty.DATA_LICENSE): "dataLicense", converter.json_property_name(DocumentProperty.EXTERNAL_DOCUMENT_REFS): ["mock_converted_external_ref"], converter.json_property_name(DocumentProperty.HAS_EXTRACTED_LICENSING_INFOS): [ - "mock_converted_extracted_licensing_info"], + "mock_converted_extracted_licensing_info" + ], converter.json_property_name(DocumentProperty.NAME): "name", converter.json_property_name(DocumentProperty.SPDX_VERSION): "spdxVersion", converter.json_property_name(DocumentProperty.DOCUMENT_NAMESPACE): "namespace", @@ -116,7 +150,7 @@ def test_successful_conversion(converter: DocumentConverter): converter.json_property_name(DocumentProperty.PACKAGES): ["mock_converted_package"], converter.json_property_name(DocumentProperty.FILES): ["mock_converted_file"], converter.json_property_name(DocumentProperty.SNIPPETS): ["mock_converted_snippet"], - converter.json_property_name(DocumentProperty.RELATIONSHIPS): ["mock_converted_relationship"] + converter.json_property_name(DocumentProperty.RELATIONSHIPS): ["mock_converted_relationship"], } @@ -154,11 +188,20 @@ def test_document_annotations(converter: DocumentConverter): # those elements, so the document should receive the other two. document_annotation = annotation_fixture(spdx_id=document_id) other_annotation = annotation_fixture(spdx_id="otherId") - annotations = [annotation_fixture(spdx_id=file.spdx_id), annotation_fixture(spdx_id=package.spdx_id), - annotation_fixture(spdx_id=snippet.spdx_id), document_annotation, - other_annotation] - document = Document(creation_info_fixture(spdx_id=document_id), files=[file], packages=[package], - snippets=[snippet], annotations=annotations) + annotations = [ + annotation_fixture(spdx_id=file.spdx_id), + annotation_fixture(spdx_id=package.spdx_id), + annotation_fixture(spdx_id=snippet.spdx_id), + document_annotation, + other_annotation, + ] + document = Document( + creation_info_fixture(spdx_id=document_id), + files=[file], + packages=[package], + snippets=[snippet], + annotations=annotations, + ) # Weird type hint to make warnings about unresolved references from the mock class disappear annotation_converter: Union[AnnotationConverter, NonCallableMagicMock] = converter.annotation_converter @@ -174,23 +217,34 @@ def test_document_annotations(converter: DocumentConverter): def test_document_describes(converter: DocumentConverter): document = document_fixture() document_id = document.creation_info.spdx_id - document_describes_relationship = relationship_fixture(spdx_element_id=document_id, - relationship_type=RelationshipType.DESCRIBES, - related_spdx_element_id="describesId") - described_by_document_relationship = relationship_fixture(related_spdx_element_id=document_id, - relationship_type=RelationshipType.DESCRIBED_BY, - spdx_element_id="describedById") - other_describes_relationship = relationship_fixture(spdx_element_id="DocumentRef-external", - relationship_type=RelationshipType.DESCRIBES) + document_describes_relationship = relationship_fixture( + spdx_element_id=document_id, + relationship_type=RelationshipType.DESCRIBES, + related_spdx_element_id="describesId", + ) + described_by_document_relationship = relationship_fixture( + related_spdx_element_id=document_id, + relationship_type=RelationshipType.DESCRIBED_BY, + spdx_element_id="describedById", + ) + other_describes_relationship = relationship_fixture( + spdx_element_id="DocumentRef-external", relationship_type=RelationshipType.DESCRIBES + ) other_relationship = relationship_fixture(spdx_element_id=document_id, relationship_type=RelationshipType.CONTAINS) - document.relationships = [document_describes_relationship, described_by_document_relationship, - other_describes_relationship, other_relationship] + document.relationships = [ + document_describes_relationship, + described_by_document_relationship, + other_describes_relationship, + other_relationship, + ] converted_dict = converter.convert(document) document_describes = converted_dict.get(converter.json_property_name(DocumentProperty.DOCUMENT_DESCRIBES)) - assert document_describes == [document_describes_relationship.related_spdx_element_id, - described_by_document_relationship.spdx_element_id] + assert document_describes == [ + document_describes_relationship.related_spdx_element_id, + described_by_document_relationship.spdx_element_id, + ] DOCUMENT_ID = "docConverterTestDocumentId" @@ -198,26 +252,36 @@ def test_document_describes(converter: DocumentConverter): FILE_ID = "docConverterTestFileId" -@pytest.mark.parametrize("relationship,should_be_written", - [(relationship_fixture(DOCUMENT_ID, RelationshipType.DESCRIBES), True), - (relationship_fixture(DOCUMENT_ID, RelationshipType.DESCRIBES, comment=None), False), - (relationship_fixture(relationship_type=RelationshipType.DESCRIBED_BY, - related_spdx_element_id=DOCUMENT_ID), True), - (relationship_fixture(relationship_type=RelationshipType.DESCRIBED_BY, - related_spdx_element_id=DOCUMENT_ID, comment=None), False), - (relationship_fixture(DOCUMENT_ID, RelationshipType.AMENDS, comment=None), True), - (relationship_fixture(PACKAGE_ID, RelationshipType.CONTAINS, FILE_ID), True), - (relationship_fixture(PACKAGE_ID, RelationshipType.CONTAINS, FILE_ID, comment=None), False), - (relationship_fixture(FILE_ID, RelationshipType.CONTAINED_BY, PACKAGE_ID), True), - (relationship_fixture(FILE_ID, RelationshipType.CONTAINED_BY, PACKAGE_ID, comment=None), - False), - (relationship_fixture(PACKAGE_ID, RelationshipType.CONTAINS, comment=None), True), - (relationship_fixture(PACKAGE_ID, RelationshipType.COPY_OF, FILE_ID, comment=None), True)]) +@pytest.mark.parametrize( + "relationship,should_be_written", + [ + (relationship_fixture(DOCUMENT_ID, RelationshipType.DESCRIBES), True), + (relationship_fixture(DOCUMENT_ID, RelationshipType.DESCRIBES, comment=None), False), + ( + relationship_fixture(relationship_type=RelationshipType.DESCRIBED_BY, related_spdx_element_id=DOCUMENT_ID), + True, + ), + ( + relationship_fixture( + relationship_type=RelationshipType.DESCRIBED_BY, related_spdx_element_id=DOCUMENT_ID, comment=None + ), + False, + ), + (relationship_fixture(DOCUMENT_ID, RelationshipType.AMENDS, comment=None), True), + (relationship_fixture(PACKAGE_ID, RelationshipType.CONTAINS, FILE_ID), True), + (relationship_fixture(PACKAGE_ID, RelationshipType.CONTAINS, FILE_ID, comment=None), False), + (relationship_fixture(FILE_ID, RelationshipType.CONTAINED_BY, PACKAGE_ID), True), + (relationship_fixture(FILE_ID, RelationshipType.CONTAINED_BY, PACKAGE_ID, comment=None), False), + (relationship_fixture(PACKAGE_ID, RelationshipType.CONTAINS, comment=None), True), + (relationship_fixture(PACKAGE_ID, RelationshipType.COPY_OF, FILE_ID, comment=None), True), + ], +) def test_document_relationships(converter: DocumentConverter, relationship: Relationship, should_be_written: bool): package = package_fixture(spdx_id=PACKAGE_ID) file = file_fixture(spdx_id=FILE_ID) - document = document_fixture(creation_info_fixture(spdx_id=DOCUMENT_ID), packages=[package], files=[file], - relationships=[relationship]) + document = document_fixture( + creation_info_fixture(spdx_id=DOCUMENT_ID), packages=[package], files=[file], relationships=[relationship] + ) # Weird type hint to make warnings about unresolved references from the mock class disappear relationship_converter: Union[RelationshipConverter, NonCallableMagicMock] = converter.relationship_converter diff --git a/tests/spdx/jsonschema/test_external_document_ref_converter.py b/tests/spdx/jsonschema/test_external_document_ref_converter.py index dc85c42b9..53bfb3bd4 100644 --- a/tests/spdx/jsonschema/test_external_document_ref_converter.py +++ b/tests/spdx/jsonschema/test_external_document_ref_converter.py @@ -20,7 +20,7 @@ @pytest.fixture -@mock.patch('spdx.jsonschema.checksum_converter.ChecksumConverter', autospec=True) +@mock.patch("spdx.jsonschema.checksum_converter.ChecksumConverter", autospec=True) def converter(checksum_converter_magic_mock: MagicMock) -> ExternalDocumentRefConverter: mocked_checksum_converter = checksum_converter_magic_mock() converter = ExternalDocumentRefConverter() @@ -28,12 +28,17 @@ def converter(checksum_converter_magic_mock: MagicMock) -> ExternalDocumentRefCo return converter -@pytest.mark.parametrize("external_document_ref_property,expected", - [(ExternalDocumentRefProperty.EXTERNAL_DOCUMENT_ID, "externalDocumentId"), - (ExternalDocumentRefProperty.SPDX_DOCUMENT, "spdxDocument"), - (ExternalDocumentRefProperty.CHECKSUM, "checksum")]) -def test_json_property_names(converter: ExternalDocumentRefConverter, - external_document_ref_property: ExternalDocumentRefProperty, expected: str): +@pytest.mark.parametrize( + "external_document_ref_property,expected", + [ + (ExternalDocumentRefProperty.EXTERNAL_DOCUMENT_ID, "externalDocumentId"), + (ExternalDocumentRefProperty.SPDX_DOCUMENT, "spdxDocument"), + (ExternalDocumentRefProperty.CHECKSUM, "checksum"), + ], +) +def test_json_property_names( + converter: ExternalDocumentRefConverter, external_document_ref_property: ExternalDocumentRefProperty, expected: str +): assert converter.json_property_name(external_document_ref_property) == expected @@ -47,7 +52,7 @@ def test_successful_conversion(converter: ExternalDocumentRefConverter): assert converted_dict == { converter.json_property_name(ExternalDocumentRefProperty.EXTERNAL_DOCUMENT_ID): "document_ref_id", converter.json_property_name(ExternalDocumentRefProperty.SPDX_DOCUMENT): "document_uri", - converter.json_property_name(ExternalDocumentRefProperty.CHECKSUM): "mock_converted_checksum" + converter.json_property_name(ExternalDocumentRefProperty.CHECKSUM): "mock_converted_checksum", } diff --git a/tests/spdx/jsonschema/test_external_package_ref_converter.py b/tests/spdx/jsonschema/test_external_package_ref_converter.py index 64c61228e..323df18d4 100644 --- a/tests/spdx/jsonschema/test_external_package_ref_converter.py +++ b/tests/spdx/jsonschema/test_external_package_ref_converter.py @@ -20,13 +20,18 @@ def converter() -> ExternalPackageRefConverter: return ExternalPackageRefConverter() -@pytest.mark.parametrize("external_package_ref_property,expected", - [(ExternalPackageRefProperty.COMMENT, "comment"), - (ExternalPackageRefProperty.REFERENCE_CATEGORY, "referenceCategory"), - (ExternalPackageRefProperty.REFERENCE_LOCATOR, "referenceLocator"), - (ExternalPackageRefProperty.REFERENCE_TYPE, "referenceType")]) -def test_json_property_names(converter: ExternalPackageRefConverter, - external_package_ref_property: ExternalPackageRefProperty, expected: str): +@pytest.mark.parametrize( + "external_package_ref_property,expected", + [ + (ExternalPackageRefProperty.COMMENT, "comment"), + (ExternalPackageRefProperty.REFERENCE_CATEGORY, "referenceCategory"), + (ExternalPackageRefProperty.REFERENCE_LOCATOR, "referenceLocator"), + (ExternalPackageRefProperty.REFERENCE_TYPE, "referenceType"), + ], +) +def test_json_property_names( + converter: ExternalPackageRefConverter, external_package_ref_property: ExternalPackageRefProperty, expected: str +): assert converter.json_property_name(external_package_ref_property) == expected @@ -47,5 +52,5 @@ def test_successful_conversion(converter: ExternalPackageRefConverter): converter.json_property_name(ExternalPackageRefProperty.COMMENT): "comment", converter.json_property_name(ExternalPackageRefProperty.REFERENCE_CATEGORY): "PACKAGE_MANAGER", converter.json_property_name(ExternalPackageRefProperty.REFERENCE_LOCATOR): "locator", - converter.json_property_name(ExternalPackageRefProperty.REFERENCE_TYPE): "type" + converter.json_property_name(ExternalPackageRefProperty.REFERENCE_TYPE): "type", } diff --git a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py index 780f57a04..7d62fa150 100644 --- a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py +++ b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py @@ -22,14 +22,21 @@ def converter() -> ExtractedLicensingInfoConverter: return ExtractedLicensingInfoConverter() -@pytest.mark.parametrize("extracted_licensing_info_property,expected", - [(ExtractedLicensingInfoProperty.LICENSE_ID, "licenseId"), - (ExtractedLicensingInfoProperty.EXTRACTED_TEXT, "extractedText"), - (ExtractedLicensingInfoProperty.NAME, "name"), - (ExtractedLicensingInfoProperty.COMMENT, "comment"), - (ExtractedLicensingInfoProperty.SEE_ALSOS, "seeAlsos")]) -def test_json_property_names(converter: ExtractedLicensingInfoConverter, - extracted_licensing_info_property: ExtractedLicensingInfoProperty, expected: str): +@pytest.mark.parametrize( + "extracted_licensing_info_property,expected", + [ + (ExtractedLicensingInfoProperty.LICENSE_ID, "licenseId"), + (ExtractedLicensingInfoProperty.EXTRACTED_TEXT, "extractedText"), + (ExtractedLicensingInfoProperty.NAME, "name"), + (ExtractedLicensingInfoProperty.COMMENT, "comment"), + (ExtractedLicensingInfoProperty.SEE_ALSOS, "seeAlsos"), + ], +) +def test_json_property_names( + converter: ExtractedLicensingInfoConverter, + extracted_licensing_info_property: ExtractedLicensingInfoProperty, + expected: str, +): assert converter.json_property_name(extracted_licensing_info_property) == expected @@ -42,9 +49,13 @@ def test_data_model_type(converter: ExtractedLicensingInfoConverter): def test_successful_conversion(converter: ExtractedLicensingInfoConverter): - extracted_licensing_info = ExtractedLicensingInfo(license_id="licenseId", extracted_text="Extracted text", - license_name="license name", - cross_references=["reference1", "reference2"], comment="comment") + extracted_licensing_info = ExtractedLicensingInfo( + license_id="licenseId", + extracted_text="Extracted text", + license_name="license name", + cross_references=["reference1", "reference2"], + comment="comment", + ) converted_dict = converter.convert(extracted_licensing_info) @@ -53,7 +64,7 @@ def test_successful_conversion(converter: ExtractedLicensingInfoConverter): converter.json_property_name(ExtractedLicensingInfoProperty.EXTRACTED_TEXT): "Extracted text", converter.json_property_name(ExtractedLicensingInfoProperty.NAME): "license name", converter.json_property_name(ExtractedLicensingInfoProperty.SEE_ALSOS): ["reference1", "reference2"], - converter.json_property_name(ExtractedLicensingInfoProperty.COMMENT): "comment" + converter.json_property_name(ExtractedLicensingInfoProperty.COMMENT): "comment", } @@ -74,4 +85,6 @@ def test_spdx_no_assertion(converter: ExtractedLicensingInfoConverter): converted_dict = converter.convert(extracted_licensing_info) - assert converted_dict[converter.json_property_name(ExtractedLicensingInfoProperty.NAME)] == SPDX_NO_ASSERTION_STRING + assert ( + converted_dict[converter.json_property_name(ExtractedLicensingInfoProperty.NAME)] == SPDX_NO_ASSERTION_STRING + ) diff --git a/tests/spdx/jsonschema/test_file_converter.py b/tests/spdx/jsonschema/test_file_converter.py index 4885e367a..e78e63681 100644 --- a/tests/spdx/jsonschema/test_file_converter.py +++ b/tests/spdx/jsonschema/test_file_converter.py @@ -31,8 +31,8 @@ @pytest.fixture -@mock.patch('spdx.jsonschema.checksum_converter.ChecksumConverter', autospec=True) -@mock.patch('spdx.jsonschema.annotation_converter.AnnotationConverter', autospec=True) +@mock.patch("spdx.jsonschema.checksum_converter.ChecksumConverter", autospec=True) +@mock.patch("spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) def converter(annotation_converter_mock: MagicMock, checksum_converter_mock: MagicMock) -> FileConverter: converter = FileConverter() converter.checksum_converter = checksum_converter_mock() @@ -40,22 +40,26 @@ def converter(annotation_converter_mock: MagicMock, checksum_converter_mock: Mag return converter -@pytest.mark.parametrize("file_property,expected", - [(FileProperty.SPDX_ID, "SPDXID"), - (FileProperty.ANNOTATIONS, "annotations"), - (FileProperty.ARTIFACT_OFS, "artifactOfs"), - (FileProperty.ATTRIBUTION_TEXTS, "attributionTexts"), - (FileProperty.CHECKSUMS, "checksums"), - (FileProperty.COMMENT, "comment"), - (FileProperty.COPYRIGHT_TEXT, "copyrightText"), - (FileProperty.FILE_CONTRIBUTORS, "fileContributors"), - (FileProperty.FILE_DEPENDENCIES, "fileDependencies"), - (FileProperty.FILE_NAME, "fileName"), - (FileProperty.FILE_TYPES, "fileTypes"), - (FileProperty.LICENSE_COMMENTS, "licenseComments"), - (FileProperty.LICENSE_CONCLUDED, "licenseConcluded"), - (FileProperty.LICENSE_INFO_IN_FILES, "licenseInfoInFiles"), - (FileProperty.NOTICE_TEXT, "noticeText")]) +@pytest.mark.parametrize( + "file_property,expected", + [ + (FileProperty.SPDX_ID, "SPDXID"), + (FileProperty.ANNOTATIONS, "annotations"), + (FileProperty.ARTIFACT_OFS, "artifactOfs"), + (FileProperty.ATTRIBUTION_TEXTS, "attributionTexts"), + (FileProperty.CHECKSUMS, "checksums"), + (FileProperty.COMMENT, "comment"), + (FileProperty.COPYRIGHT_TEXT, "copyrightText"), + (FileProperty.FILE_CONTRIBUTORS, "fileContributors"), + (FileProperty.FILE_DEPENDENCIES, "fileDependencies"), + (FileProperty.FILE_NAME, "fileName"), + (FileProperty.FILE_TYPES, "fileTypes"), + (FileProperty.LICENSE_COMMENTS, "licenseComments"), + (FileProperty.LICENSE_CONCLUDED, "licenseConcluded"), + (FileProperty.LICENSE_INFO_IN_FILES, "licenseInfoInFiles"), + (FileProperty.NOTICE_TEXT, "noticeText"), + ], +) def test_json_property_names(converter: FileConverter, file_property: FileProperty, expected: str): assert converter.json_property_name(file_property) == expected @@ -71,16 +75,30 @@ def test_data_model_type(converter: FileConverter): def test_successful_conversion(converter: FileConverter): converter.checksum_converter.convert.return_value = "mock_converted_checksum" converter.annotation_converter.convert.return_value = "mock_converted_annotation" - file = File(name="name", spdx_id="spdxId", - checksums=[Checksum(ChecksumAlgorithm.SHA224, "sha224"), Checksum(ChecksumAlgorithm.MD2, "md2")], - file_types=[FileType.SPDX, FileType.OTHER], license_concluded=Licensing().parse("MIT and GPL-2.0"), - license_info_in_file=[Licensing().parse("MIT"), Licensing().parse("GPL-2.0"), SpdxNoAssertion()], - license_comment="licenseComment", copyright_text="copyrightText", comment="comment", notice="notice", - contributors=["contributor1", "contributor2"], - attribution_texts=["attributionText1", "attributionText2"]) - - annotations = [Annotation(file.spdx_id, AnnotationType.REVIEW, Actor(ActorType.PERSON, "annotatorName"), - datetime(2022, 12, 5), "review comment")] + file = File( + name="name", + spdx_id="spdxId", + checksums=[Checksum(ChecksumAlgorithm.SHA224, "sha224"), Checksum(ChecksumAlgorithm.MD2, "md2")], + file_types=[FileType.SPDX, FileType.OTHER], + license_concluded=Licensing().parse("MIT and GPL-2.0"), + license_info_in_file=[Licensing().parse("MIT"), Licensing().parse("GPL-2.0"), SpdxNoAssertion()], + license_comment="licenseComment", + copyright_text="copyrightText", + comment="comment", + notice="notice", + contributors=["contributor1", "contributor2"], + attribution_texts=["attributionText1", "attributionText2"], + ) + + annotations = [ + Annotation( + file.spdx_id, + AnnotationType.REVIEW, + Actor(ActorType.PERSON, "annotatorName"), + datetime(2022, 12, 5), + "review comment", + ) + ] document = Document(creation_info_fixture(), files=[file], annotations=annotations) converted_dict = converter.convert(file, document) @@ -98,13 +116,23 @@ def test_successful_conversion(converter: FileConverter): converter.json_property_name(FileProperty.LICENSE_COMMENTS): "licenseComment", converter.json_property_name(FileProperty.LICENSE_CONCLUDED): "MIT AND GPL-2.0", converter.json_property_name(FileProperty.LICENSE_INFO_IN_FILES): ["MIT", "GPL-2.0", "NOASSERTION"], - converter.json_property_name(FileProperty.NOTICE_TEXT): "notice" + converter.json_property_name(FileProperty.NOTICE_TEXT): "notice", } def test_null_values(converter: FileConverter): - file = file_fixture(copyright_text=None, license_concluded=None, license_comment=None, comment=None, notice=None, - attribution_texts=[], checksums=[], contributors=[], file_types=[], license_info_in_file=[]) + file = file_fixture( + copyright_text=None, + license_concluded=None, + license_comment=None, + comment=None, + notice=None, + attribution_texts=[], + checksums=[], + contributors=[], + file_types=[], + license_info_in_file=[], + ) document = Document(creation_info_fixture(), files=[file]) converted_dict = converter.convert(file, document) @@ -123,16 +151,18 @@ def test_null_values(converter: FileConverter): def test_spdx_no_assertion(converter: FileConverter): - file = file_fixture(license_concluded=SpdxNoAssertion(), license_info_in_file=[SpdxNoAssertion()], - copyright_text=SpdxNoAssertion()) + file = file_fixture( + license_concluded=SpdxNoAssertion(), license_info_in_file=[SpdxNoAssertion()], copyright_text=SpdxNoAssertion() + ) document = Document(creation_info_fixture(), files=[file]) converted_dict = converter.convert(file, document) - assert converted_dict[ - converter.json_property_name(FileProperty.COPYRIGHT_TEXT)] == SPDX_NO_ASSERTION_STRING + assert converted_dict[converter.json_property_name(FileProperty.COPYRIGHT_TEXT)] == SPDX_NO_ASSERTION_STRING assert converted_dict[converter.json_property_name(FileProperty.LICENSE_CONCLUDED)] == SPDX_NO_ASSERTION_STRING - assert converted_dict[converter.json_property_name(FileProperty.LICENSE_INFO_IN_FILES)] == [SPDX_NO_ASSERTION_STRING] + assert converted_dict[converter.json_property_name(FileProperty.LICENSE_INFO_IN_FILES)] == [ + SPDX_NO_ASSERTION_STRING + ] def test_spdx_none(converter: FileConverter): @@ -141,8 +171,7 @@ def test_spdx_none(converter: FileConverter): converted_dict = converter.convert(file, document) - assert converted_dict[ - converter.json_property_name(FileProperty.COPYRIGHT_TEXT)] == SPDX_NONE_STRING + assert converted_dict[converter.json_property_name(FileProperty.COPYRIGHT_TEXT)] == SPDX_NONE_STRING assert converted_dict[converter.json_property_name(FileProperty.LICENSE_CONCLUDED)] == SPDX_NONE_STRING assert converted_dict[converter.json_property_name(FileProperty.LICENSE_INFO_IN_FILES)] == [SPDX_NONE_STRING] @@ -156,8 +185,14 @@ def test_file_annotations(converter: FileConverter): package_annotation = annotation_fixture(spdx_id=document.packages[0].spdx_id) snippet_annotation = annotation_fixture(spdx_id=document.snippets[0].spdx_id) other_annotation = annotation_fixture(spdx_id="otherId") - annotations = [first_file_annotation, second_file_annotation, document_annotation, package_annotation, - snippet_annotation, other_annotation] + annotations = [ + first_file_annotation, + second_file_annotation, + document_annotation, + package_annotation, + snippet_annotation, + other_annotation, + ] document.annotations = annotations # Weird type hint to make warnings about unresolved references from the mock class disappear @@ -166,7 +201,8 @@ def test_file_annotations(converter: FileConverter): converted_dict = converter.convert(file, document) - assert_mock_method_called_with_arguments(annotation_converter, "convert", first_file_annotation, - second_file_annotation) + assert_mock_method_called_with_arguments( + annotation_converter, "convert", first_file_annotation, second_file_annotation + ) converted_file_annotations = converted_dict.get(converter.json_property_name(FileProperty.ANNOTATIONS)) assert converted_file_annotations == ["mock_converted_annotation", "mock_converted_annotation"] diff --git a/tests/spdx/jsonschema/test_package_converter.py b/tests/spdx/jsonschema/test_package_converter.py index a8e2ba9f2..31516fa0f 100644 --- a/tests/spdx/jsonschema/test_package_converter.py +++ b/tests/spdx/jsonschema/test_package_converter.py @@ -41,12 +41,16 @@ @pytest.fixture -@mock.patch('spdx.jsonschema.checksum_converter.ChecksumConverter', autospec=True) -@mock.patch('spdx.jsonschema.annotation_converter.AnnotationConverter', autospec=True) -@mock.patch('spdx.jsonschema.package_verification_code_converter.PackageVerificationCodeConverter', autospec=True) -@mock.patch('spdx.jsonschema.external_package_ref_converter.ExternalPackageRefConverter', autospec=True) -def converter(package_ref_converter_mock: MagicMock, verification_code_converter_mock: MagicMock, - annotation_converter_mock: MagicMock, checksum_converter_mock: MagicMock) -> PackageConverter: +@mock.patch("spdx.jsonschema.checksum_converter.ChecksumConverter", autospec=True) +@mock.patch("spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) +@mock.patch("spdx.jsonschema.package_verification_code_converter.PackageVerificationCodeConverter", autospec=True) +@mock.patch("spdx.jsonschema.external_package_ref_converter.ExternalPackageRefConverter", autospec=True) +def converter( + package_ref_converter_mock: MagicMock, + verification_code_converter_mock: MagicMock, + annotation_converter_mock: MagicMock, + checksum_converter_mock: MagicMock, +) -> PackageConverter: converter = PackageConverter() converter.checksum_converter = checksum_converter_mock() converter.annotation_converter = annotation_converter_mock() @@ -55,37 +59,42 @@ def converter(package_ref_converter_mock: MagicMock, verification_code_converter return converter -@pytest.mark.parametrize("external_package_ref_property,expected", - [(PackageProperty.SPDX_ID, "SPDXID"), - (PackageProperty.ANNOTATIONS, "annotations"), - (PackageProperty.ATTRIBUTION_TEXTS, "attributionTexts"), - (PackageProperty.BUILT_DATE, "builtDate"), - (PackageProperty.CHECKSUMS, "checksums"), - (PackageProperty.COMMENT, "comment"), - (PackageProperty.COPYRIGHT_TEXT, "copyrightText"), - (PackageProperty.DESCRIPTION, "description"), - (PackageProperty.DOWNLOAD_LOCATION, "downloadLocation"), - (PackageProperty.EXTERNAL_REFS, "externalRefs"), - (PackageProperty.FILES_ANALYZED, "filesAnalyzed"), - (PackageProperty.HAS_FILES, "hasFiles"), - (PackageProperty.HOMEPAGE, "homepage"), - (PackageProperty.LICENSE_COMMENTS, "licenseComments"), - (PackageProperty.LICENSE_CONCLUDED, "licenseConcluded"), - (PackageProperty.LICENSE_DECLARED, "licenseDeclared"), - (PackageProperty.LICENSE_INFO_FROM_FILES, "licenseInfoFromFiles"), - (PackageProperty.NAME, "name"), - (PackageProperty.ORIGINATOR, "originator"), - (PackageProperty.PACKAGE_FILE_NAME, "packageFileName"), - (PackageProperty.PACKAGE_VERIFICATION_CODE, "packageVerificationCode"), - (PackageProperty.PRIMARY_PACKAGE_PURPOSE, "primaryPackagePurpose"), - (PackageProperty.RELEASE_DATE, "releaseDate"), - (PackageProperty.SOURCE_INFO, "sourceInfo"), - (PackageProperty.SUMMARY, "summary"), - (PackageProperty.SUPPLIER, "supplier"), - (PackageProperty.VALID_UNTIL_DATE, "validUntilDate"), - (PackageProperty.VERSION_INFO, "versionInfo")]) -def test_json_property_names(converter: PackageConverter, - external_package_ref_property: PackageProperty, expected: str): +@pytest.mark.parametrize( + "external_package_ref_property,expected", + [ + (PackageProperty.SPDX_ID, "SPDXID"), + (PackageProperty.ANNOTATIONS, "annotations"), + (PackageProperty.ATTRIBUTION_TEXTS, "attributionTexts"), + (PackageProperty.BUILT_DATE, "builtDate"), + (PackageProperty.CHECKSUMS, "checksums"), + (PackageProperty.COMMENT, "comment"), + (PackageProperty.COPYRIGHT_TEXT, "copyrightText"), + (PackageProperty.DESCRIPTION, "description"), + (PackageProperty.DOWNLOAD_LOCATION, "downloadLocation"), + (PackageProperty.EXTERNAL_REFS, "externalRefs"), + (PackageProperty.FILES_ANALYZED, "filesAnalyzed"), + (PackageProperty.HAS_FILES, "hasFiles"), + (PackageProperty.HOMEPAGE, "homepage"), + (PackageProperty.LICENSE_COMMENTS, "licenseComments"), + (PackageProperty.LICENSE_CONCLUDED, "licenseConcluded"), + (PackageProperty.LICENSE_DECLARED, "licenseDeclared"), + (PackageProperty.LICENSE_INFO_FROM_FILES, "licenseInfoFromFiles"), + (PackageProperty.NAME, "name"), + (PackageProperty.ORIGINATOR, "originator"), + (PackageProperty.PACKAGE_FILE_NAME, "packageFileName"), + (PackageProperty.PACKAGE_VERIFICATION_CODE, "packageVerificationCode"), + (PackageProperty.PRIMARY_PACKAGE_PURPOSE, "primaryPackagePurpose"), + (PackageProperty.RELEASE_DATE, "releaseDate"), + (PackageProperty.SOURCE_INFO, "sourceInfo"), + (PackageProperty.SUMMARY, "summary"), + (PackageProperty.SUPPLIER, "supplier"), + (PackageProperty.VALID_UNTIL_DATE, "validUntilDate"), + (PackageProperty.VERSION_INFO, "versionInfo"), + ], +) +def test_json_property_names( + converter: PackageConverter, external_package_ref_property: PackageProperty, expected: str +): assert converter.json_property_name(external_package_ref_property) == expected @@ -102,24 +111,42 @@ def test_successful_conversion(converter: PackageConverter): converter.annotation_converter.convert.return_value = "mock_converted_annotation" converter.package_verification_code_converter.convert.return_value = "mock_converted_verification_code" converter.external_package_ref_converter.convert.return_value = "mock_package_ref" - package = Package(spdx_id="packageId", name="name", download_location="downloadLocation", version="version", - file_name="fileName", supplier=Actor(ActorType.PERSON, "supplierName"), - originator=Actor(ActorType.PERSON, "originatorName"), files_analyzed=True, - verification_code=PackageVerificationCode("value"), - checksums=[Checksum(ChecksumAlgorithm.SHA1, "sha1"), - Checksum(ChecksumAlgorithm.BLAKE2B_256, "blake")], homepage="homepage", - source_info="sourceInfo", license_concluded=Licensing().parse("MIT and GPL-2.0"), - license_info_from_files=[Licensing().parse("MIT"), - Licensing().parse("GPL-2.0")], - license_declared=Licensing().parse("MIT or GPL-2.0 "), license_comment="licenseComment", - copyright_text="copyrightText", summary="summary", description="description", comment="comment", - external_references=[external_package_ref_fixture()], - attribution_texts=["attributionText1", "attributionText2"], - primary_package_purpose=PackagePurpose.APPLICATION, release_date=datetime(2022, 12, 1), - built_date=datetime(2022, 12, 2), valid_until_date=datetime(2022, 12, 3)) - - annotation = Annotation(package.spdx_id, AnnotationType.REVIEW, Actor(ActorType.TOOL, "toolName"), - datetime(2022, 12, 5), "review comment") + package = Package( + spdx_id="packageId", + name="name", + download_location="downloadLocation", + version="version", + file_name="fileName", + supplier=Actor(ActorType.PERSON, "supplierName"), + originator=Actor(ActorType.PERSON, "originatorName"), + files_analyzed=True, + verification_code=PackageVerificationCode("value"), + checksums=[Checksum(ChecksumAlgorithm.SHA1, "sha1"), Checksum(ChecksumAlgorithm.BLAKE2B_256, "blake")], + homepage="homepage", + source_info="sourceInfo", + license_concluded=Licensing().parse("MIT and GPL-2.0"), + license_info_from_files=[Licensing().parse("MIT"), Licensing().parse("GPL-2.0")], + license_declared=Licensing().parse("MIT or GPL-2.0 "), + license_comment="licenseComment", + copyright_text="copyrightText", + summary="summary", + description="description", + comment="comment", + external_references=[external_package_ref_fixture()], + attribution_texts=["attributionText1", "attributionText2"], + primary_package_purpose=PackagePurpose.APPLICATION, + release_date=datetime(2022, 12, 1), + built_date=datetime(2022, 12, 2), + valid_until_date=datetime(2022, 12, 3), + ) + + annotation = Annotation( + package.spdx_id, + AnnotationType.REVIEW, + Actor(ActorType.TOOL, "toolName"), + datetime(2022, 12, 5), + "review comment", + ) document = Document(creation_info_fixture(), packages=[package], annotations=[annotation]) converted_dict = converter.convert(package, document) @@ -136,7 +163,10 @@ def test_successful_conversion(converter: PackageConverter): converter.json_property_name(PackageProperty.ORIGINATOR): "Person: originatorName", converter.json_property_name(PackageProperty.FILES_ANALYZED): True, converter.json_property_name(PackageProperty.PACKAGE_VERIFICATION_CODE): "mock_converted_verification_code", - converter.json_property_name(PackageProperty.CHECKSUMS): ["mock_converted_checksum", "mock_converted_checksum"], + converter.json_property_name(PackageProperty.CHECKSUMS): [ + "mock_converted_checksum", + "mock_converted_checksum", + ], converter.json_property_name(PackageProperty.HOMEPAGE): "homepage", converter.json_property_name(PackageProperty.SOURCE_INFO): "sourceInfo", converter.json_property_name(PackageProperty.LICENSE_CONCLUDED): "MIT AND GPL-2.0", @@ -151,17 +181,35 @@ def test_successful_conversion(converter: PackageConverter): converter.json_property_name(PackageProperty.PRIMARY_PACKAGE_PURPOSE): "APPLICATION", converter.json_property_name(PackageProperty.RELEASE_DATE): "2022-12-01T00:00:00Z", converter.json_property_name(PackageProperty.BUILT_DATE): "2022-12-02T00:00:00Z", - converter.json_property_name(PackageProperty.VALID_UNTIL_DATE): "2022-12-03T00:00:00Z" + converter.json_property_name(PackageProperty.VALID_UNTIL_DATE): "2022-12-03T00:00:00Z", } def test_null_values(converter: PackageConverter): - package = package_fixture(built_date=None, release_date=None, valid_until_date=None, homepage=None, - license_concluded=None, license_declared=None, originator=None, verification_code=None, - primary_package_purpose=None, supplier=None, version=None, file_name=None, - source_info=None, license_comment=None, copyright_text=None, summary=None, - description=None, comment=None, attribution_texts=[], checksums=[], - external_references=[], license_info_from_files=[]) + package = package_fixture( + built_date=None, + release_date=None, + valid_until_date=None, + homepage=None, + license_concluded=None, + license_declared=None, + originator=None, + verification_code=None, + primary_package_purpose=None, + supplier=None, + version=None, + file_name=None, + source_info=None, + license_comment=None, + copyright_text=None, + summary=None, + description=None, + comment=None, + attribution_texts=[], + checksums=[], + external_references=[], + license_info_from_files=[], + ) document = Document(creation_info_fixture(), packages=[package]) @@ -194,10 +242,16 @@ def test_null_values(converter: PackageConverter): def test_spdx_no_assertion(converter: PackageConverter): - package = package_fixture(download_location=SpdxNoAssertion(), supplier=SpdxNoAssertion(), - originator=SpdxNoAssertion(), homepage=SpdxNoAssertion(), - license_concluded=SpdxNoAssertion(), license_info_from_files=[SpdxNoAssertion()], - license_declared=SpdxNoAssertion(), copyright_text=SpdxNoAssertion()) + package = package_fixture( + download_location=SpdxNoAssertion(), + supplier=SpdxNoAssertion(), + originator=SpdxNoAssertion(), + homepage=SpdxNoAssertion(), + license_concluded=SpdxNoAssertion(), + license_info_from_files=[SpdxNoAssertion()], + license_declared=SpdxNoAssertion(), + copyright_text=SpdxNoAssertion(), + ) document = Document(creation_info_fixture(), packages=[package]) @@ -208,16 +262,22 @@ def test_spdx_no_assertion(converter: PackageConverter): assert converted_dict[converter.json_property_name(PackageProperty.ORIGINATOR)] == SPDX_NO_ASSERTION_STRING assert converted_dict[converter.json_property_name(PackageProperty.HOMEPAGE)] == SPDX_NO_ASSERTION_STRING assert converted_dict[converter.json_property_name(PackageProperty.LICENSE_CONCLUDED)] == SPDX_NO_ASSERTION_STRING - assert converted_dict[ - converter.json_property_name(PackageProperty.LICENSE_INFO_FROM_FILES)] == [SPDX_NO_ASSERTION_STRING] + assert converted_dict[converter.json_property_name(PackageProperty.LICENSE_INFO_FROM_FILES)] == [ + SPDX_NO_ASSERTION_STRING + ] assert converted_dict[converter.json_property_name(PackageProperty.LICENSE_DECLARED)] == SPDX_NO_ASSERTION_STRING assert converted_dict[converter.json_property_name(PackageProperty.COPYRIGHT_TEXT)] == SPDX_NO_ASSERTION_STRING def test_spdx_none(converter: PackageConverter): - package = package_fixture(download_location=SpdxNone(), homepage=SpdxNone(), - license_concluded=SpdxNone(), license_info_from_files=[SpdxNone()], - license_declared=SpdxNone(), copyright_text=SpdxNone()) + package = package_fixture( + download_location=SpdxNone(), + homepage=SpdxNone(), + license_concluded=SpdxNone(), + license_info_from_files=[SpdxNone()], + license_declared=SpdxNone(), + copyright_text=SpdxNone(), + ) document = Document(creation_info_fixture(), packages=[package]) @@ -240,8 +300,14 @@ def test_package_annotations(converter: PackageConverter): file_annotation = annotation_fixture(spdx_id=document.files[0].spdx_id) snippet_annotation = annotation_fixture(spdx_id=document.snippets[0].spdx_id) other_annotation = annotation_fixture(spdx_id="otherId") - annotations = [first_package_annotation, second_package_annotation, document_annotation, file_annotation, - snippet_annotation, other_annotation] + annotations = [ + first_package_annotation, + second_package_annotation, + document_annotation, + file_annotation, + snippet_annotation, + other_annotation, + ] document.annotations = annotations # Weird type hint to make warnings about unresolved references from the mock class disappear @@ -250,8 +316,9 @@ def test_package_annotations(converter: PackageConverter): converted_dict = converter.convert(package, document) - assert_mock_method_called_with_arguments(annotation_converter, "convert", first_package_annotation, - second_package_annotation) + assert_mock_method_called_with_arguments( + annotation_converter, "convert", first_package_annotation, second_package_annotation + ) converted_file_annotations = converted_dict.get(converter.json_property_name(PackageProperty.ANNOTATIONS)) assert converted_file_annotations == ["mock_converted_annotation", "mock_converted_annotation"] @@ -262,23 +329,35 @@ def test_has_files(converter: PackageConverter): second_contained_file = file_fixture(spdx_id="secondFileId") non_contained_file = file_fixture(spdx_id="otherFileId") snippet = snippet_fixture() - document = document_fixture(packages=[package], - files=[first_contained_file, second_contained_file, non_contained_file], - snippets=[snippet]) - package_contains_file_relationship = relationship_fixture(spdx_element_id=package.spdx_id, - relationship_type=RelationshipType.CONTAINS, - related_spdx_element_id=first_contained_file.spdx_id) - file_contained_in_package_relationship = relationship_fixture(spdx_element_id=second_contained_file.spdx_id, - relationship_type=RelationshipType.CONTAINED_BY, - related_spdx_element_id=package.spdx_id) - package_contains_snippet_relationship = relationship_fixture(spdx_element_id=package.spdx_id, - relationship_type=RelationshipType.CONTAINS, - related_spdx_element_id=snippet.spdx_id) - package_describes_file_relationship = relationship_fixture(spdx_element_id=package.spdx_id, - relationship_type=RelationshipType.DESCRIBES, - related_spdx_element_id=non_contained_file.spdx_id) - document.relationships = [package_contains_file_relationship, file_contained_in_package_relationship, - package_contains_snippet_relationship, package_describes_file_relationship] + document = document_fixture( + packages=[package], files=[first_contained_file, second_contained_file, non_contained_file], snippets=[snippet] + ) + package_contains_file_relationship = relationship_fixture( + spdx_element_id=package.spdx_id, + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id=first_contained_file.spdx_id, + ) + file_contained_in_package_relationship = relationship_fixture( + spdx_element_id=second_contained_file.spdx_id, + relationship_type=RelationshipType.CONTAINED_BY, + related_spdx_element_id=package.spdx_id, + ) + package_contains_snippet_relationship = relationship_fixture( + spdx_element_id=package.spdx_id, + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id=snippet.spdx_id, + ) + package_describes_file_relationship = relationship_fixture( + spdx_element_id=package.spdx_id, + relationship_type=RelationshipType.DESCRIBES, + related_spdx_element_id=non_contained_file.spdx_id, + ) + document.relationships = [ + package_contains_file_relationship, + file_contained_in_package_relationship, + package_contains_snippet_relationship, + package_describes_file_relationship, + ] converted_dict = converter.convert(package, document) diff --git a/tests/spdx/jsonschema/test_package_verification_code_converter.py b/tests/spdx/jsonschema/test_package_verification_code_converter.py index 2ee715484..66daf34e0 100644 --- a/tests/spdx/jsonschema/test_package_verification_code_converter.py +++ b/tests/spdx/jsonschema/test_package_verification_code_converter.py @@ -20,13 +20,21 @@ def converter() -> PackageVerificationCodeConverter: return PackageVerificationCodeConverter() -@pytest.mark.parametrize("package_verification_code_property,expected", - [(PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES, - "packageVerificationCodeExcludedFiles"), - (PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_VALUE, - "packageVerificationCodeValue")]) -def test_json_property_names(converter: PackageVerificationCodeConverter, - package_verification_code_property: PackageVerificationCodeProperty, expected: str): +@pytest.mark.parametrize( + "package_verification_code_property,expected", + [ + ( + PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES, + "packageVerificationCodeExcludedFiles", + ), + (PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_VALUE, "packageVerificationCodeValue"), + ], +) +def test_json_property_names( + converter: PackageVerificationCodeConverter, + package_verification_code_property: PackageVerificationCodeProperty, + expected: str, +): assert converter.json_property_name(package_verification_code_property) == expected @@ -45,8 +53,10 @@ def test_successful_conversion(converter: PackageVerificationCodeConverter): assert converted_dict == { converter.json_property_name(PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES): [ - "file1", "file2"], - converter.json_property_name(PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_VALUE): "value" + "file1", + "file2", + ], + converter.json_property_name(PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_VALUE): "value", } @@ -55,5 +65,7 @@ def test_null_values(converter: PackageVerificationCodeConverter): converted_dict = converter.convert(package_verification_code) - assert converter.json_property_name( - PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES) not in converted_dict + assert ( + converter.json_property_name(PackageVerificationCodeProperty.PACKAGE_VERIFICATION_CODE_EXCLUDED_FILES) + not in converted_dict + ) diff --git a/tests/spdx/jsonschema/test_relationship_converter.py b/tests/spdx/jsonschema/test_relationship_converter.py index 0926ca5c7..d03d6271d 100644 --- a/tests/spdx/jsonschema/test_relationship_converter.py +++ b/tests/spdx/jsonschema/test_relationship_converter.py @@ -23,13 +23,18 @@ def converter() -> RelationshipConverter: return RelationshipConverter() -@pytest.mark.parametrize("relationship_property,expected", - [(RelationshipProperty.SPDX_ELEMENT_ID, "spdxElementId"), - (RelationshipProperty.COMMENT, "comment"), - (RelationshipProperty.RELATED_SPDX_ELEMENT, "relatedSpdxElement"), - (RelationshipProperty.RELATIONSHIP_TYPE, "relationshipType")]) -def test_json_property_names(converter: RelationshipConverter, relationship_property: RelationshipProperty, - expected: str): +@pytest.mark.parametrize( + "relationship_property,expected", + [ + (RelationshipProperty.SPDX_ELEMENT_ID, "spdxElementId"), + (RelationshipProperty.COMMENT, "comment"), + (RelationshipProperty.RELATED_SPDX_ELEMENT, "relatedSpdxElement"), + (RelationshipProperty.RELATIONSHIP_TYPE, "relationshipType"), + ], +) +def test_json_property_names( + converter: RelationshipConverter, relationship_property: RelationshipProperty, expected: str +): assert converter.json_property_name(relationship_property) == expected @@ -50,7 +55,7 @@ def test_successful_conversion(converter: RelationshipConverter): converter.json_property_name(RelationshipProperty.SPDX_ELEMENT_ID): "spdxElementId", converter.json_property_name(RelationshipProperty.COMMENT): "comment", converter.json_property_name(RelationshipProperty.RELATED_SPDX_ELEMENT): "relatedElementId", - converter.json_property_name(RelationshipProperty.RELATIONSHIP_TYPE): "COPY_OF" + converter.json_property_name(RelationshipProperty.RELATIONSHIP_TYPE): "COPY_OF", } @@ -59,8 +64,10 @@ def test_spdx_no_assertion(converter: RelationshipConverter): converted_dict = converter.convert(relationship) - assert converted_dict[ - converter.json_property_name(RelationshipProperty.RELATED_SPDX_ELEMENT)] == SPDX_NO_ASSERTION_STRING + assert ( + converted_dict[converter.json_property_name(RelationshipProperty.RELATED_SPDX_ELEMENT)] + == SPDX_NO_ASSERTION_STRING + ) def test_spdx_none(converter: RelationshipConverter): diff --git a/tests/spdx/jsonschema/test_snippet_converter.py b/tests/spdx/jsonschema/test_snippet_converter.py index b7d07193d..a77b70ea0 100644 --- a/tests/spdx/jsonschema/test_snippet_converter.py +++ b/tests/spdx/jsonschema/test_snippet_converter.py @@ -30,27 +30,30 @@ @pytest.fixture -@mock.patch('spdx.jsonschema.annotation_converter.AnnotationConverter', autospec=True) +@mock.patch("spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) def converter(annotation_converter_mock: MagicMock) -> SnippetConverter: converter = SnippetConverter() converter.annotation_converter = annotation_converter_mock() return converter -@pytest.mark.parametrize("snippet_property,expected", - [(SnippetProperty.SPDX_ID, "SPDXID"), - (SnippetProperty.ANNOTATIONS, "annotations"), - (SnippetProperty.ATTRIBUTION_TEXTS, "attributionTexts"), - (SnippetProperty.COMMENT, "comment"), - (SnippetProperty.COPYRIGHT_TEXT, "copyrightText"), - (SnippetProperty.LICENSE_COMMENTS, "licenseComments"), - (SnippetProperty.LICENSE_CONCLUDED, "licenseConcluded"), - (SnippetProperty.LICENSE_INFO_IN_SNIPPETS, "licenseInfoInSnippets"), - (SnippetProperty.NAME, "name"), - (SnippetProperty.RANGES, "ranges"), - (SnippetProperty.SNIPPET_FROM_FILE, "snippetFromFile")]) -def test_json_property_names(converter: SnippetConverter, snippet_property: SnippetProperty, - expected: str): +@pytest.mark.parametrize( + "snippet_property,expected", + [ + (SnippetProperty.SPDX_ID, "SPDXID"), + (SnippetProperty.ANNOTATIONS, "annotations"), + (SnippetProperty.ATTRIBUTION_TEXTS, "attributionTexts"), + (SnippetProperty.COMMENT, "comment"), + (SnippetProperty.COPYRIGHT_TEXT, "copyrightText"), + (SnippetProperty.LICENSE_COMMENTS, "licenseComments"), + (SnippetProperty.LICENSE_CONCLUDED, "licenseConcluded"), + (SnippetProperty.LICENSE_INFO_IN_SNIPPETS, "licenseInfoInSnippets"), + (SnippetProperty.NAME, "name"), + (SnippetProperty.RANGES, "ranges"), + (SnippetProperty.SNIPPET_FROM_FILE, "snippetFromFile"), + ], +) +def test_json_property_names(converter: SnippetConverter, snippet_property: SnippetProperty, expected: str): assert converter.json_property_name(snippet_property) == expected @@ -65,15 +68,27 @@ def test_data_model_type(converter: SnippetConverter): def test_successful_conversion(converter: SnippetConverter): converter.annotation_converter.convert.return_value = "mock_converted_annotation" file_spdx_id = "fileSpdxId" - snippet = Snippet("spdxId", file_spdx_id=file_spdx_id, byte_range=(1, 2), line_range=(3, 4), - license_concluded=Licensing().parse("MIT and GPL-2.0"), - license_info_in_snippet=[Licensing().parse("MIT"), - Licensing().parse("GPL-2.0")], - license_comment="licenseComment", copyright_text="copyrightText", comment="comment", name="name", - attribution_texts=["attributionText1", "attributionText2"]) - - annotation = Annotation(snippet.spdx_id, AnnotationType.OTHER, Actor(ActorType.PERSON, "annotatorName"), - datetime(2022, 12, 5), "other comment") + snippet = Snippet( + "spdxId", + file_spdx_id=file_spdx_id, + byte_range=(1, 2), + line_range=(3, 4), + license_concluded=Licensing().parse("MIT and GPL-2.0"), + license_info_in_snippet=[Licensing().parse("MIT"), Licensing().parse("GPL-2.0")], + license_comment="licenseComment", + copyright_text="copyrightText", + comment="comment", + name="name", + attribution_texts=["attributionText1", "attributionText2"], + ) + + annotation = Annotation( + snippet.spdx_id, + AnnotationType.OTHER, + Actor(ActorType.PERSON, "annotatorName"), + datetime(2022, 12, 5), + "other comment", + ) document = Document(creation_info_fixture(), snippets=[snippet], annotations=[annotation]) converted_dict = converter.convert(snippet, document) @@ -88,17 +103,29 @@ def test_successful_conversion(converter: SnippetConverter): converter.json_property_name(SnippetProperty.LICENSE_INFO_IN_SNIPPETS): ["MIT", "GPL-2.0"], converter.json_property_name(SnippetProperty.NAME): "name", converter.json_property_name(SnippetProperty.RANGES): [ - {"startPointer": {"reference": file_spdx_id, "offset": 1}, - "endPointer": {"reference": file_spdx_id, "offset": 2}}, - {"startPointer": {"reference": file_spdx_id, "lineNumber": 3}, - "endPointer": {"reference": file_spdx_id, "lineNumber": 4}}], - converter.json_property_name(SnippetProperty.SNIPPET_FROM_FILE): file_spdx_id + { + "startPointer": {"reference": file_spdx_id, "offset": 1}, + "endPointer": {"reference": file_spdx_id, "offset": 2}, + }, + { + "startPointer": {"reference": file_spdx_id, "lineNumber": 3}, + "endPointer": {"reference": file_spdx_id, "lineNumber": 4}, + }, + ], + converter.json_property_name(SnippetProperty.SNIPPET_FROM_FILE): file_spdx_id, } def test_null_values(converter: SnippetConverter): - snippet = snippet_fixture(license_concluded=None, license_comment=None, copyright_text=None, comment=None, - name=None, attribution_texts=[], license_info_in_snippet=[]) + snippet = snippet_fixture( + license_concluded=None, + license_comment=None, + copyright_text=None, + comment=None, + name=None, + attribution_texts=[], + license_info_in_snippet=[], + ) document = Document(creation_info_fixture(), snippets=[snippet]) converted_dict = converter.convert(snippet, document) @@ -121,7 +148,8 @@ def test_spdx_no_assertion(converter: SnippetConverter): assert converted_dict[converter.json_property_name(SnippetProperty.LICENSE_CONCLUDED)] == SPDX_NO_ASSERTION_STRING assert converted_dict[converter.json_property_name(SnippetProperty.LICENSE_INFO_IN_SNIPPETS)] == [ - SPDX_NO_ASSERTION_STRING] + SPDX_NO_ASSERTION_STRING + ] def test_spdx_none(converter: SnippetConverter): @@ -143,8 +171,14 @@ def test_snippet_annotations(converter: SnippetConverter): package_annotation = annotation_fixture(spdx_id=document.packages[0].spdx_id) file_annotation = annotation_fixture(spdx_id=document.files[0].spdx_id) other_annotation = annotation_fixture(spdx_id="otherId") - annotations = [first_snippet_annotation, second_snippet_annotation, document_annotation, package_annotation, - file_annotation, other_annotation] + annotations = [ + first_snippet_annotation, + second_snippet_annotation, + document_annotation, + package_annotation, + file_annotation, + other_annotation, + ] document.annotations = annotations # Weird type hint to make warnings about unresolved references from the mock class disappear @@ -153,7 +187,8 @@ def test_snippet_annotations(converter: SnippetConverter): converted_dict = converter.convert(snippet, document) - assert_mock_method_called_with_arguments(annotation_converter, "convert", first_snippet_annotation, - second_snippet_annotation) + assert_mock_method_called_with_arguments( + annotation_converter, "convert", first_snippet_annotation, second_snippet_annotation + ) converted_file_annotations = converted_dict.get(converter.json_property_name(SnippetProperty.ANNOTATIONS)) assert converted_file_annotations == ["mock_converted_annotation", "mock_converted_annotation"] diff --git a/tests/spdx/model/test_actor.py b/tests/spdx/model/test_actor.py index 9a0ba5a14..ff8398ebf 100644 --- a/tests/spdx/model/test_actor.py +++ b/tests/spdx/model/test_actor.py @@ -38,14 +38,16 @@ def test_wrong_type_in_email_after_initializing(): actor.email = [] -@pytest.mark.parametrize("actor,expected_string", [(Actor(ActorType.PERSON, "personName"), "Person: personName"), - (Actor(ActorType.PERSON, "personName", "personEmail"), - "Person: personName (personEmail)"), - (Actor(ActorType.ORGANIZATION, "orgName"), "Organization: orgName"), - (Actor(ActorType.ORGANIZATION, "orgName", "orgEmail"), - "Organization: orgName (orgEmail)"), - (Actor(ActorType.TOOL, "toolName"), "Tool: toolName"), - (Actor(ActorType.TOOL, "toolName", "toolEmail"), - "Tool: toolName (toolEmail)")]) +@pytest.mark.parametrize( + "actor,expected_string", + [ + (Actor(ActorType.PERSON, "personName"), "Person: personName"), + (Actor(ActorType.PERSON, "personName", "personEmail"), "Person: personName (personEmail)"), + (Actor(ActorType.ORGANIZATION, "orgName"), "Organization: orgName"), + (Actor(ActorType.ORGANIZATION, "orgName", "orgEmail"), "Organization: orgName (orgEmail)"), + (Actor(ActorType.TOOL, "toolName"), "Tool: toolName"), + (Actor(ActorType.TOOL, "toolName", "toolEmail"), "Tool: toolName (toolEmail)"), + ], +) def test_serialization(actor: Actor, expected_string: str): assert actor.to_serialized_string() == expected_string diff --git a/tests/spdx/model/test_annotation.py b/tests/spdx/model/test_annotation.py index c2d357c43..1caab2ccb 100644 --- a/tests/spdx/model/test_annotation.py +++ b/tests/spdx/model/test_annotation.py @@ -6,7 +6,7 @@ from spdx.model.annotation import Annotation, AnnotationType -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_correct_initialization(actor): annotation = Annotation("id", AnnotationType.OTHER, actor, datetime(2022, 1, 1), "comment") assert annotation.spdx_id == "id" @@ -16,31 +16,31 @@ def test_correct_initialization(actor): assert annotation.annotation_comment == "comment" -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_spdx_id(actor): with pytest.raises(TypeError): Annotation(42, AnnotationType.OTHER, actor, datetime(2022, 1, 1), "comment") -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_annotation_type(actor): with pytest.raises(TypeError): Annotation("id", 42, actor, datetime(2022, 1, 1), "comment") -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_annotator(actor): with pytest.raises(TypeError): Annotation("id", AnnotationType.OTHER, 42, datetime(2022, 1, 1), "comment") -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_annotation_date(actor): with pytest.raises(TypeError): Annotation("id", AnnotationType.OTHER, actor, 42, "comment") -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_annotation_comment(actor): with pytest.raises(TypeError): Annotation("id", AnnotationType.OTHER, actor, datetime(2022, 1, 1), 42) diff --git a/tests/spdx/model/test_creation_info.py b/tests/spdx/model/test_creation_info.py index 70be62dc7..0d7213135 100644 --- a/tests/spdx/model/test_creation_info.py +++ b/tests/spdx/model/test_creation_info.py @@ -7,11 +7,22 @@ from spdx.model.version import Version -@mock.patch('spdx.model.external_document_ref.ExternalDocumentRef', autospec=True) -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.external_document_ref.ExternalDocumentRef", autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_correct_initialization(actor, ext_ref): - creation_info = CreationInfo("version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), - "creator_comment", "CC0-1.1", [ext_ref, ext_ref], Version(6, 3), "doc_comment") + creation_info = CreationInfo( + "version", + "id", + "name", + "namespace", + [actor, actor], + datetime(2022, 1, 1), + "creator_comment", + "CC0-1.1", + [ext_ref, ext_ref], + Version(6, 3), + "doc_comment", + ) assert creation_info.spdx_version == "version" assert creation_info.spdx_id == "id" assert creation_info.name == "name" @@ -25,25 +36,25 @@ def test_correct_initialization(actor, ext_ref): assert creation_info.document_comment == "doc_comment" -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_spdx_version(actor): with pytest.raises(TypeError): CreationInfo(42, "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1)) -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_spdx_id(actor): with pytest.raises(TypeError): CreationInfo("version", 42, "name", "namespace", [actor, actor], datetime(2022, 1, 1)) -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_name(actor): with pytest.raises(TypeError): CreationInfo("version", "id", 42, "namespace", [actor, actor], datetime(2022, 1, 1)) -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_document_namespace(actor): with pytest.raises(TypeError): CreationInfo("version", "id", "name", 42, [actor, actor], datetime(2022, 1, 1)) @@ -54,40 +65,45 @@ def test_wrong_type_in_creators(): CreationInfo("version", "id", "name", "namespace", ["person"], datetime(2022, 1, 1)) -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_created(actor): with pytest.raises(TypeError): CreationInfo("version", "id", "name", "namespace", [actor, actor], "2022-01-01") -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_creator_comment(actor): with pytest.raises(TypeError): - CreationInfo("version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), - creator_comment=["string"]) + CreationInfo( + "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), creator_comment=["string"] + ) -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_data_license(actor): with pytest.raises(TypeError): CreationInfo("version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), data_license=42) -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_external_document_refs(actor): with pytest.raises(TypeError): - CreationInfo("version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), - external_document_refs=()) + CreationInfo( + "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), external_document_refs=() + ) -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_license_list_version(actor): with pytest.raises(TypeError): - CreationInfo("version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), - license_list_version="6.4") + CreationInfo( + "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), license_list_version="6.4" + ) -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_document_comment(actor): with pytest.raises(TypeError): - CreationInfo("version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), document_comment=["1"]) + CreationInfo( + "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), document_comment=["1"] + ) diff --git a/tests/spdx/model/test_document.py b/tests/spdx/model/test_document.py index c60742587..35fa3f176 100644 --- a/tests/spdx/model/test_document.py +++ b/tests/spdx/model/test_document.py @@ -5,17 +5,23 @@ from spdx.model.document import Document -@mock.patch('spdx.model.extracted_licensing_info.ExtractedLicensingInfo', autospec=True) -@mock.patch('spdx.model.relationship.Relationship', autospec=True) -@mock.patch('spdx.model.annotation.Annotation', autospec=True) -@mock.patch('spdx.model.snippet.Snippet', autospec=True) -@mock.patch('spdx.model.file.File', autospec=True) -@mock.patch('spdx.model.package.Package', autospec=True) -@mock.patch('spdx.model.document.CreationInfo', autospec=True) -def test_correct_initialization(creation_info, package, file, snippet, annotation, relationship, - extracted_lic): - document = Document(creation_info, [package, package], [file, file], [snippet, snippet], [annotation, annotation], - [relationship, relationship], [extracted_lic, extracted_lic]) +@mock.patch("spdx.model.extracted_licensing_info.ExtractedLicensingInfo", autospec=True) +@mock.patch("spdx.model.relationship.Relationship", autospec=True) +@mock.patch("spdx.model.annotation.Annotation", autospec=True) +@mock.patch("spdx.model.snippet.Snippet", autospec=True) +@mock.patch("spdx.model.file.File", autospec=True) +@mock.patch("spdx.model.package.Package", autospec=True) +@mock.patch("spdx.model.document.CreationInfo", autospec=True) +def test_correct_initialization(creation_info, package, file, snippet, annotation, relationship, extracted_lic): + document = Document( + creation_info, + [package, package], + [file, file], + [snippet, snippet], + [annotation, annotation], + [relationship, relationship], + [extracted_lic, extracted_lic], + ) assert document.creation_info == creation_info assert document.packages == [package, package] assert document.files == [file, file] @@ -25,7 +31,7 @@ def test_correct_initialization(creation_info, package, file, snippet, annotatio assert document.extracted_licensing_info == [extracted_lic, extracted_lic] -@mock.patch('spdx.model.document.CreationInfo', autospec=True) +@mock.patch("spdx.model.document.CreationInfo", autospec=True) def test_correct_initialization_with_default_values(creation_info): document = Document(creation_info) assert document.creation_info == creation_info @@ -42,37 +48,37 @@ def test_wrong_type_in_creation_info(): Document("string") -@mock.patch('spdx.model.document.CreationInfo', autospec=True) +@mock.patch("spdx.model.document.CreationInfo", autospec=True) def test_wrong_type_in_packages(creation_info): with pytest.raises(TypeError): Document(creation_info, packages=["string"]) -@mock.patch('spdx.model.document.CreationInfo', autospec=True) +@mock.patch("spdx.model.document.CreationInfo", autospec=True) def test_wrong_type_in_files(creation_info): with pytest.raises(TypeError): Document(creation_info, files={}) -@mock.patch('spdx.model.document.CreationInfo', autospec=True) +@mock.patch("spdx.model.document.CreationInfo", autospec=True) def test_wrong_type_in_snippets(creation_info): with pytest.raises(TypeError): Document(creation_info, snippets=()) -@mock.patch('spdx.model.document.CreationInfo', autospec=True) +@mock.patch("spdx.model.document.CreationInfo", autospec=True) def test_wrong_type_in_annotations(creation_info): with pytest.raises(TypeError): Document(creation_info, annotations=["string"]) -@mock.patch('spdx.model.document.CreationInfo', autospec=True) +@mock.patch("spdx.model.document.CreationInfo", autospec=True) def test_wrong_type_in_relationships(creation_info): with pytest.raises(TypeError): Document(creation_info, relationships="string") -@mock.patch('spdx.model.document.CreationInfo', autospec=True) +@mock.patch("spdx.model.document.CreationInfo", autospec=True) def test_wrong_type_in_extracted_licensing_info(creation_info): with pytest.raises(TypeError): Document(creation_info, extracted_licensing_info=42) diff --git a/tests/spdx/model/test_external_document_ref.py b/tests/spdx/model/test_external_document_ref.py index c210910af..28c2829cf 100644 --- a/tests/spdx/model/test_external_document_ref.py +++ b/tests/spdx/model/test_external_document_ref.py @@ -5,7 +5,7 @@ from spdx.model.external_document_ref import ExternalDocumentRef -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_correct_initialization(checksum): external_document_ref = ExternalDocumentRef("id", "uri", checksum) assert external_document_ref.document_ref_id == "id" @@ -13,13 +13,13 @@ def test_correct_initialization(checksum): assert external_document_ref.checksum == checksum -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_spdx_id(checksum): with pytest.raises(TypeError): ExternalDocumentRef(42, "uri", checksum) -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_document_uri(checksum): with pytest.raises(TypeError): ExternalDocumentRef("id", 42, checksum) diff --git a/tests/spdx/model/test_external_package_reference.py b/tests/spdx/model/test_external_package_reference.py index 768e56329..74027bd9f 100644 --- a/tests/spdx/model/test_external_package_reference.py +++ b/tests/spdx/model/test_external_package_reference.py @@ -4,8 +4,7 @@ def test_correct_initialization(): - external_package_reference = ExternalPackageRef(ExternalPackageRefCategory.OTHER, "type", "locator", - "comment") + external_package_reference = ExternalPackageRef(ExternalPackageRefCategory.OTHER, "type", "locator", "comment") assert external_package_reference.category == ExternalPackageRefCategory.OTHER assert external_package_reference.reference_type == "type" assert external_package_reference.locator == "locator" diff --git a/tests/spdx/model/test_file.py b/tests/spdx/model/test_file.py index 70ecab4a6..d6ea58e74 100644 --- a/tests/spdx/model/test_file.py +++ b/tests/spdx/model/test_file.py @@ -8,10 +8,22 @@ from spdx.model.spdx_none import SpdxNone -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_correct_initialization(checksum): - file = File("name", "id", [checksum, checksum], [FileType.OTHER, FileType.SPDX], SpdxNone(), [SpdxNoAssertion()], - "comment on license", "copyright", "comment", "notice", ["contributor"], ["attribution"]) + file = File( + "name", + "id", + [checksum, checksum], + [FileType.OTHER, FileType.SPDX], + SpdxNone(), + [SpdxNoAssertion()], + "comment on license", + "copyright", + "comment", + "notice", + ["contributor"], + ["attribution"], + ) assert file.name == "name" assert file.spdx_id == "id" assert file.checksums == [checksum, checksum] @@ -26,7 +38,7 @@ def test_correct_initialization(checksum): assert file.attribution_texts == ["attribution"] -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_correct_initialization_with_default_values(checksum): file = File("name", "id", [checksum, checksum]) assert file.name == "name" @@ -43,13 +55,13 @@ def test_correct_initialization_with_default_values(checksum): assert file.attribution_texts == [] -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_name(checksum): with pytest.raises(TypeError): File(42, "id", [checksum]) -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_spdx_id(checksum): with pytest.raises(TypeError): File("name", 42, [checksum]) @@ -61,55 +73,55 @@ def test_wrong_type_in_checksum(): File("name", "id", checksum) -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_file_type(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], file_types=FileType.OTHER) -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_license_concluded(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], license_concluded="NONE") -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_license_info_in_file(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], license_info_in_file=[SpdxNone]) -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_license_comment(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], license_comment=42) -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_copyright_text(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], copyright_text=[SpdxNone()]) -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_comment(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], comment=42) -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_notice(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], notice=["notice"]) -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_contributors(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], contributors="contributor") -@mock.patch('spdx.model.checksum.Checksum', autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_attribution_texts(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], attribution_texts=["attribution", 42]) diff --git a/tests/spdx/model/test_package.py b/tests/spdx/model/test_package.py index c1c538f16..193924df2 100644 --- a/tests/spdx/model/test_package.py +++ b/tests/spdx/model/test_package.py @@ -10,16 +10,39 @@ from spdx.model.spdx_none import SpdxNone -@mock.patch('spdx.model.package.ExternalPackageRef', autospec=True) -@mock.patch('spdx.model.checksum.Checksum', autospec=True) -@mock.patch('spdx.model.package.PackageVerificationCode', autospec=True) -@mock.patch('spdx.model.actor.Actor', autospec=True) +@mock.patch("spdx.model.package.ExternalPackageRef", autospec=True) +@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx.model.package.PackageVerificationCode", autospec=True) +@mock.patch("spdx.model.actor.Actor", autospec=True) def test_correct_initialization(actor, verif_code, checksum, ext_ref): - package = Package("id", "name", SpdxNoAssertion(), "version", "file_name", SpdxNoAssertion(), actor, True, - verif_code, [checksum], "homepage", "source_info", None, - [Licensing().parse("license and expression"), SpdxNoAssertion()], SpdxNone(), - "comment on license", "copyright", "summary", "description", "comment", [ext_ref, ext_ref], - ["text"], PackagePurpose.OTHER, datetime(2022, 1, 1), None, None) + package = Package( + "id", + "name", + SpdxNoAssertion(), + "version", + "file_name", + SpdxNoAssertion(), + actor, + True, + verif_code, + [checksum], + "homepage", + "source_info", + None, + [Licensing().parse("license and expression"), SpdxNoAssertion()], + SpdxNone(), + "comment on license", + "copyright", + "summary", + "description", + "comment", + [ext_ref, ext_ref], + ["text"], + PackagePurpose.OTHER, + datetime(2022, 1, 1), + None, + None, + ) assert package.spdx_id == "id" assert package.name == "name" assert package.download_location == SpdxNoAssertion() diff --git a/tests/spdx/model/test_snippet.py b/tests/spdx/model/test_snippet.py index 77219c5de..8b5d3b556 100644 --- a/tests/spdx/model/test_snippet.py +++ b/tests/spdx/model/test_snippet.py @@ -6,8 +6,19 @@ def test_correct_initialization(): - snippet = Snippet("id", "file_id", (200, 400), (20, 40), SpdxNone(), [SpdxNoAssertion()], "comment on license", - "copyright", "comment", "name", ["attribution"]) + snippet = Snippet( + "id", + "file_id", + (200, 400), + (20, 40), + SpdxNone(), + [SpdxNoAssertion()], + "comment on license", + "copyright", + "comment", + "name", + ["attribution"], + ) assert snippet.spdx_id == "id" assert snippet.file_spdx_id == "file_id" assert snippet.byte_range == (200, 400) diff --git a/tests/spdx/parser/json/test_json_parser.py b/tests/spdx/parser/json/test_json_parser.py index f83a62be8..b61a01ad8 100644 --- a/tests/spdx/parser/json/test_json_parser.py +++ b/tests/spdx/parser/json/test_json_parser.py @@ -19,31 +19,33 @@ def test_parse_json_file_not_found(): with pytest.raises(FileNotFoundError) as err: - wrong_file_path = os.path.join(os.path.dirname(__file__), 'hnjfkjsedhnflsiafg.json') + wrong_file_path = os.path.join(os.path.dirname(__file__), "hnjfkjsedhnflsiafg.json") json_parser.parse_from_file(wrong_file_path) assert err.value.args[1] == "No such file or directory" def test_parse_json_with_2_3_example(): - doc = json_parser.parse_from_file(os.path.join(os.path.dirname(__file__), - "../../data/formats/SPDXJSONExample-v2.3.spdx.json")) + doc = json_parser.parse_from_file( + os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXJSONExample-v2.3.spdx.json") + ) assert type(doc) == Document assert len(doc.annotations) == 5 assert len(doc.files) == 5 assert len(doc.packages) == 4 - assert len(doc.snippets) == 1 + assert len(doc.snippets) == 1 assert len(doc.relationships) == 13 assert len(doc.extracted_licensing_info) == 5 + def test_parse_json_with_2_2_example(): - doc = json_parser.parse_from_file(os.path.join(os.path.dirname(__file__), - "../../data/formats/SPDXJSONExample-v2.2.spdx.json")) + doc = json_parser.parse_from_file( + os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXJSONExample-v2.2.spdx.json") + ) assert type(doc) == Document assert len(doc.annotations) == 5 assert len(doc.files) == 4 assert len(doc.packages) == 4 - assert len(doc.snippets) == 1 + assert len(doc.snippets) == 1 assert len(doc.relationships) == 11 assert len(doc.extracted_licensing_info) == 5 - diff --git a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py index f68944cbd..2e2da39cf 100644 --- a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py @@ -25,7 +25,7 @@ def test_parse_annotation(): "annotationDate": "2010-01-29T18:30:22Z", "annotationType": "OTHER", "annotator": "Person: Jane Doe ()", - "comment": "Document level annotation" + "comment": "Document level annotation", } annotation = annotation_parser.parse_annotation(annotation_dict, spdx_id="SPDXRef-DOCUMENT") @@ -42,36 +42,47 @@ def test_parse_all_annotations(): doc_dict = { "SPDXID": "SPDXRef-DOCUMENT", "packages": [ - {"SPDXID": "SPDXRef-Package", - "annotations": [ - {"annotationDate": "2010-01-29T17:30:22Z", - "annotationType": "REVIEW", - "annotator": "Person: Mick Doe ()", - "comment": "Package level annotation"} - ]}], + { + "SPDXID": "SPDXRef-Package", + "annotations": [ + { + "annotationDate": "2010-01-29T17:30:22Z", + "annotationType": "REVIEW", + "annotator": "Person: Mick Doe ()", + "comment": "Package level annotation", + } + ], + } + ], "files": [ - {"SPDXID": "SPDXRef-File", - "annotations": [ - {"annotationDate": "2010-01-29T18:30:22Z", - "annotationType": "OTHER", - "annotator": "Person: Jane Doe ()", - "comment": "File level annotation"} - ]} + { + "SPDXID": "SPDXRef-File", + "annotations": [ + { + "annotationDate": "2010-01-29T18:30:22Z", + "annotationType": "OTHER", + "annotator": "Person: Jane Doe ()", + "comment": "File level annotation", + } + ], + } ], "snippets": [ - {"SPDXID": "SPDXRef-Snippet", - "annotations": [ - {"annotationDate": "2022-01-29T18:30:32Z", - "annotationType": "REVIEW", - "annotator": "Person: Jonas Rie (jonas@example.com)", - "comment": "Snippet level annotation"} - ]}], - "revieweds": - [{ - "reviewDate": "2010-01-29T18:30:22Z", - "reviewer": "Person: Jane Doe ()", - "comment": "Review annotation" - }] + { + "SPDXID": "SPDXRef-Snippet", + "annotations": [ + { + "annotationDate": "2022-01-29T18:30:32Z", + "annotationType": "REVIEW", + "annotator": "Person: Jonas Rie (jonas@example.com)", + "comment": "Snippet level annotation", + } + ], + } + ], + "revieweds": [ + {"reviewDate": "2010-01-29T18:30:22Z", "reviewer": "Person: Jane Doe ()", "comment": "Review annotation"} + ], } annotations = annotation_parser.parse_all_annotations(input_doc_dict=doc_dict) @@ -79,34 +90,70 @@ def test_parse_all_annotations(): assert len(annotations) == 4 test_case = TestCase() test_case.maxDiff = None - test_case.assertCountEqual(annotations, [Annotation(spdx_id="SPDXRef-DOCUMENT", - annotation_type=AnnotationType.REVIEW, - annotator=Actor(actor_type=ActorType.PERSON, name="Jane Doe", - email=None), - annotation_date=datetime.datetime(2010, 1, 29, 18, 30, 22), - annotation_comment="Review annotation"), - Annotation(spdx_id="SPDXRef-Package", - annotation_type=AnnotationType.REVIEW, - annotator=Actor(actor_type=ActorType.PERSON, name="Mick Doe", - email=None), - annotation_date=datetime.datetime(2010, 1, 29, 17, 30, 22), - annotation_comment="Package level annotation"), - Annotation(spdx_id="SPDXRef-File", annotation_type=AnnotationType.OTHER, - annotator=Actor(actor_type=ActorType.PERSON, name="Jane Doe", - email=None), - annotation_date=datetime.datetime(2010, 1, 29, 18, 30, 22), - annotation_comment="File level annotation"), - Annotation(spdx_id="SPDXRef-Snippet", - annotation_type=AnnotationType.REVIEW, - annotator=Actor(actor_type=ActorType.PERSON, name="Jonas Rie", - email="jonas@example.com"), - annotation_date=datetime.datetime(2022, 1, 29, 18, 30, 32), - annotation_comment="Snippet level annotation")]) + test_case.assertCountEqual( + annotations, + [ + Annotation( + spdx_id="SPDXRef-DOCUMENT", + annotation_type=AnnotationType.REVIEW, + annotator=Actor(actor_type=ActorType.PERSON, name="Jane Doe", email=None), + annotation_date=datetime.datetime(2010, 1, 29, 18, 30, 22), + annotation_comment="Review annotation", + ), + Annotation( + spdx_id="SPDXRef-Package", + annotation_type=AnnotationType.REVIEW, + annotator=Actor(actor_type=ActorType.PERSON, name="Mick Doe", email=None), + annotation_date=datetime.datetime(2010, 1, 29, 17, 30, 22), + annotation_comment="Package level annotation", + ), + Annotation( + spdx_id="SPDXRef-File", + annotation_type=AnnotationType.OTHER, + annotator=Actor(actor_type=ActorType.PERSON, name="Jane Doe", email=None), + annotation_date=datetime.datetime(2010, 1, 29, 18, 30, 22), + annotation_comment="File level annotation", + ), + Annotation( + spdx_id="SPDXRef-Snippet", + annotation_type=AnnotationType.REVIEW, + annotator=Actor(actor_type=ActorType.PERSON, name="Jonas Rie", email="jonas@example.com"), + annotation_date=datetime.datetime(2022, 1, 29, 18, 30, 32), + annotation_comment="Snippet level annotation", + ), + ], + ) -@pytest.mark.parametrize("incomplete_annotation_dict,expected_message", [({"annotator": "Person: Jane Doe ()"}, [ - "Error while constructing Annotation: ['SetterError Annotation: type of " 'argument "spdx_id" must be str; got NoneType instead: None\', \'SetterError Annotation: type of argument "annotation_type" must be ' "spdx.model.annotation.AnnotationType; got NoneType instead: None', " '\'SetterError Annotation: type of argument "annotation_date" must be ' "datetime.datetime; got NoneType instead: None', 'SetterError Annotation: " 'type of argument "annotation_comment" must be str; got NoneType instead: ' "None']"]), - ({"annotationDate": "2010-01-29T18:30:22Z"}, ["Error while constructing Annotation: ['SetterError Annotation: type of " 'argument "spdx_id" must be str; got NoneType instead: None\', \'SetterError Annotation: type of argument "annotation_type" must be ' "spdx.model.annotation.AnnotationType; got NoneType instead: None', " '\'SetterError Annotation: type of argument "annotator" must be ' "spdx.model.actor.Actor; got NoneType instead: None', 'SetterError Annotation: " 'type of argument "annotation_comment" must be str; got NoneType instead: ' "None']"])]) +@pytest.mark.parametrize( + "incomplete_annotation_dict,expected_message", + [ + ( + {"annotator": "Person: Jane Doe ()"}, + [ + "Error while constructing Annotation: ['SetterError Annotation: type of " + 'argument "spdx_id" must be str; got NoneType instead: None\', \'SetterError Annotation: type of argument "annotation_type" must be ' + "spdx.model.annotation.AnnotationType; got NoneType instead: None', " + '\'SetterError Annotation: type of argument "annotation_date" must be ' + "datetime.datetime; got NoneType instead: None', 'SetterError Annotation: " + 'type of argument "annotation_comment" must be str; got NoneType instead: ' + "None']" + ], + ), + ( + {"annotationDate": "2010-01-29T18:30:22Z"}, + [ + "Error while constructing Annotation: ['SetterError Annotation: type of " + 'argument "spdx_id" must be str; got NoneType instead: None\', \'SetterError Annotation: type of argument "annotation_type" must be ' + "spdx.model.annotation.AnnotationType; got NoneType instead: None', " + '\'SetterError Annotation: type of argument "annotator" must be ' + "spdx.model.actor.Actor; got NoneType instead: None', 'SetterError Annotation: " + 'type of argument "annotation_comment" must be str; got NoneType instead: ' + "None']" + ], + ), + ], +) def test_parse_incomplete_annotation(incomplete_annotation_dict, expected_message): annotation_parser = AnnotationParser() diff --git a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py index a60249787..c2a51076d 100644 --- a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py @@ -19,10 +19,7 @@ def test_parse_checksum(): checksum_parser = ChecksumParser() - checksum_dict = { - "algorithm": "SHA1", - "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759" - } + checksum_dict = {"algorithm": "SHA1", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759"} checksum = checksum_parser.parse_checksum(checksum_dict) @@ -32,26 +29,26 @@ def test_parse_checksum(): def test_parse_invalid_checksum(): checksum_parser = ChecksumParser() - checksum_dict = { - "algorithm": "SHA", - "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759" - } + checksum_dict = {"algorithm": "SHA", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759"} with pytest.raises(SPDXParsingError) as err: checksum_parser.parse_checksum(checksum_dict) - TestCase().assertCountEqual(err.value.get_messages(), - ["Error while parsing Checksum: ['Invalid ChecksumAlgorithm: SHA']"]) + TestCase().assertCountEqual( + err.value.get_messages(), ["Error while parsing Checksum: ['Invalid ChecksumAlgorithm: SHA']"] + ) def test_parse_incomplete_checksum(): checksum_parser = ChecksumParser() - checksum_dict = { - "algorithm": "SHA1" - } + checksum_dict = {"algorithm": "SHA1"} with pytest.raises(SPDXParsingError) as err: checksum_parser.parse_checksum(checksum_dict) - TestCase().assertCountEqual(err.value.get_messages(), [ - "Error while constructing Checksum: ['SetterError Checksum: type of argument \"value\" must be str; got NoneType instead: None']"]) + TestCase().assertCountEqual( + err.value.get_messages(), + [ + "Error while constructing Checksum: ['SetterError Checksum: type of argument \"value\" must be str; got NoneType instead: None']" + ], + ) diff --git a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py index a45f204b6..2ed029280 100644 --- a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py @@ -29,20 +29,19 @@ def test_parse_creation_info(): "name": "Example Document", "dataLicense": "CC0-1.0", "documentNamespace": "namespace", - "externalDocumentRefs": [{ - "externalDocumentId": "DocumentRef-spdx-tool-1.2", - "checksum": { - "algorithm": "SHA1", - "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759" - }, - "spdxDocument": "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301" - }], + "externalDocumentRefs": [ + { + "externalDocumentId": "DocumentRef-spdx-tool-1.2", + "checksum": {"algorithm": "SHA1", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759"}, + "spdxDocument": "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301", + } + ], "creationInfo": { "created": "2010-01-29T18:30:22Z", "creators": ["Tool: LicenseFind-1.0", "Organization: ExampleCodeInspect ()", "Person: Jane Doe ()"], "licenseListVersion": "3.7", - "comment": "Some comment." - } + "comment": "Some comment.", + }, } creation_info = creation_info_parser.parse_creation_info(doc_dict) @@ -51,31 +50,48 @@ def test_parse_creation_info(): assert creation_info.name == "Example Document" assert creation_info.document_namespace == "namespace" assert creation_info.created == datetime(2010, 1, 29, 18, 30, 22) - TestCase().assertCountEqual(creation_info.creators, [Actor(ActorType.TOOL, "LicenseFind-1.0"), - Actor(ActorType.ORGANIZATION, "ExampleCodeInspect"), - Actor(ActorType.PERSON, "Jane Doe")]) + TestCase().assertCountEqual( + creation_info.creators, + [ + Actor(ActorType.TOOL, "LicenseFind-1.0"), + Actor(ActorType.ORGANIZATION, "ExampleCodeInspect"), + Actor(ActorType.PERSON, "Jane Doe"), + ], + ) assert creation_info.license_list_version == Version(3, 7) - assert creation_info.external_document_refs == [ExternalDocumentRef(document_ref_id="DocumentRef-spdx-tool-1.2", - checksum=Checksum( - algorithm=ChecksumAlgorithm.SHA1, - value="d6a770ba38583ed4bb4525bd96e50461655d2759"), - document_uri="http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301")] + assert creation_info.external_document_refs == [ + ExternalDocumentRef( + document_ref_id="DocumentRef-spdx-tool-1.2", + checksum=Checksum(algorithm=ChecksumAlgorithm.SHA1, value="d6a770ba38583ed4bb4525bd96e50461655d2759"), + document_uri="http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301", + ) + ] -@pytest.mark.parametrize("incomplete_dict,expected_message", - [({"spdxVersion": "2.3", "SPDXID": "SPDXRef-DOCUMENT", "name": "Example Document"}, - ["Error while parsing document Example Document: ['CreationInfo does not exist.']"]), - ({"creationInfo": {"created": "2019-02-01T11:30:40Z"}}, - ["Error while constructing CreationInfo: ['SetterError CreationInfo: type of " - 'argument "spdx_version" must be str; got NoneType instead: None\', ' - '\'SetterError CreationInfo: type of argument "spdx_id" must be str; got ' - "NoneType instead: None', 'SetterError CreationInfo: type of argument " - '"name" must be str; got NoneType instead: None\', \'SetterError ' - 'CreationInfo: type of argument "document_namespace" must be str; got ' - "NoneType instead: None', 'SetterError CreationInfo: type of argument " - '"creators" must be a list; got NoneType instead: None\', \'SetterError ' - 'CreationInfo: type of argument "data_license" must be str; got NoneType ' - "instead: None']"])]) +@pytest.mark.parametrize( + "incomplete_dict,expected_message", + [ + ( + {"spdxVersion": "2.3", "SPDXID": "SPDXRef-DOCUMENT", "name": "Example Document"}, + ["Error while parsing document Example Document: ['CreationInfo does not exist.']"], + ), + ( + {"creationInfo": {"created": "2019-02-01T11:30:40Z"}}, + [ + "Error while constructing CreationInfo: ['SetterError CreationInfo: type of " + 'argument "spdx_version" must be str; got NoneType instead: None\', ' + '\'SetterError CreationInfo: type of argument "spdx_id" must be str; got ' + "NoneType instead: None', 'SetterError CreationInfo: type of argument " + "\"name\" must be str; got NoneType instead: None', 'SetterError " + 'CreationInfo: type of argument "document_namespace" must be str; got ' + "NoneType instead: None', 'SetterError CreationInfo: type of argument " + "\"creators\" must be a list; got NoneType instead: None', 'SetterError " + 'CreationInfo: type of argument "data_license" must be str; got NoneType ' + "instead: None']" + ], + ), + ], +) def test_parse_incomplete_document_info(incomplete_dict, expected_message): creation_info_parser = CreationInfoParser() @@ -95,11 +111,17 @@ def test_parse_invalid_creation_info(): "created": "2010-01-29T18:30:22Z", "creators": ["Tool: LicenseFind-1.0", "Organization: ExampleCodeInspect ()", "Person: Jane Doe ()"], }, - "dataLicense": None + "dataLicense": None, } with pytest.raises(SPDXParsingError) as err: creation_info_parser.parse_creation_info(doc_dict) - TestCase().assertCountEqual(err.value.get_messages(), [ - "Error while constructing CreationInfo: ['SetterError CreationInfo: type of " 'argument "document_namespace" must be str; got NoneType instead: None\', \'SetterError CreationInfo: type of argument "data_license" must be str; got ' "NoneType instead: None']"]) + TestCase().assertCountEqual( + err.value.get_messages(), + [ + "Error while constructing CreationInfo: ['SetterError CreationInfo: type of " + 'argument "document_namespace" must be str; got NoneType instead: None\', \'SetterError CreationInfo: type of argument "data_license" must be str; got ' + "NoneType instead: None']" + ], + ) diff --git a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py index bea9d74a7..66babca5d 100644 --- a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py +++ b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py @@ -30,8 +30,7 @@ def test_json_str_to_enum(): assert enum_name == "BLAKE2B_256" -@pytest.mark.parametrize("invalid_json_str,expected_message", - [(5, ["Type for enum must be str not int"])]) +@pytest.mark.parametrize("invalid_json_str,expected_message", [(5, ["Type for enum must be str not int"])]) def test_invalid_json_str_to_enum(invalid_json_str, expected_message): with pytest.raises(SPDXParsingError) as err: json_str_to_enum_name(invalid_json_str) @@ -46,8 +45,9 @@ def test_parse_field_or_no_assertion(input_str, expected_type): assert type(resulting_value) == expected_type -@pytest.mark.parametrize("input_str,expected_type", - [("NOASSERTION", SpdxNoAssertion), ("NONE", SpdxNone), ("example string", str)]) +@pytest.mark.parametrize( + "input_str,expected_type", [("NOASSERTION", SpdxNoAssertion), ("NONE", SpdxNone), ("example string", str)] +) def test_parse_field_or_no_assertion_or_none(input_str, expected_type): resulting_value = parse_field_or_no_assertion_or_none(input_str, lambda x: x) diff --git a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py index d73ed5c0e..f8c64ea32 100644 --- a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py @@ -20,21 +20,23 @@ def test_parse_extracted_licensing_info(): extracted_licensing_info_parser = ExtractedLicensingInfoParser() extracted_licensing_infos_dict = { - "licenseId": "LicenseRef-Beerware-4.2", "comment": "The beerware license has a couple of other standard variants.", - "extractedText": "\"THE BEER-WARE LICENSE\" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "extractedText": '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp', "name": "Beer-Ware License (Version 42)", - "seeAlsos": ["http://people.freebsd.org/~phk/"] - + "seeAlsos": ["http://people.freebsd.org/~phk/"], } extracted_licensing_info = extracted_licensing_info_parser.parse_extracted_licensing_info( - extracted_licensing_infos_dict) + extracted_licensing_infos_dict + ) assert extracted_licensing_info.license_id == "LicenseRef-Beerware-4.2" assert extracted_licensing_info.comment == "The beerware license has a couple of other standard variants." - assert extracted_licensing_info.extracted_text == "\"THE BEER-WARE LICENSE\" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp" + assert ( + extracted_licensing_info.extracted_text + == '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp' + ) assert extracted_licensing_info.license_name == "Beer-Ware License (Version 42)" assert extracted_licensing_info.cross_references == ["http://people.freebsd.org/~phk/"] @@ -45,15 +47,19 @@ def test_parse_invalid_extracted_licensing_info(): extracted_licensing_infos_dict = { "licenseId": "LicenseRef-Beerware-4.2", "comment": 56, - "extractedText": "\"THE BEER-WARE LICENSE\" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "extractedText": '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp', "name": "Beer-Ware License (Version 42)", - "seeAlsos": ["http://people.freebsd.org/~phk/"] - + "seeAlsos": ["http://people.freebsd.org/~phk/"], } with pytest.raises(SPDXParsingError) as err: extracted_licensing_info_parser.parse_extracted_licensing_info(extracted_licensing_infos_dict) - TestCase().assertCountEqual(err.value.get_messages(), [ - "Error while constructing ExtractedLicensingInfo: ['SetterError " 'ExtractedLicensingInfo: type of argument "comment" must be one of (str, ' "NoneType); got int instead: 56']"]) - + TestCase().assertCountEqual( + err.value.get_messages(), + [ + "Error while constructing ExtractedLicensingInfo: ['SetterError " + 'ExtractedLicensingInfo: type of argument "comment" must be one of (str, ' + "NoneType); got int instead: 56']" + ], + ) diff --git a/tests/spdx/parser/jsonlikedict/test_file_parser.py b/tests/spdx/parser/jsonlikedict/test_file_parser.py index 5987b66e2..ddea8cfe7 100644 --- a/tests/spdx/parser/jsonlikedict/test_file_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_file_parser.py @@ -26,90 +26,111 @@ def test_parse_file(): file_dict = { "SPDXID": "SPDXRef-File", "attributionTexts": ["Some attribution text."], - "checksums": [{ - "algorithm": "SHA1", - "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2758" - }, { - "algorithm": "MD5", - "checksumValue": "624c1abb3664f4b35547e7c73864ad24" - }], + "checksums": [ + {"algorithm": "SHA1", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2758"}, + {"algorithm": "MD5", "checksumValue": "624c1abb3664f4b35547e7c73864ad24"}, + ], "comment": "The concluded license was taken from the package level that the file was included in.\nThis information was found in the COPYING.txt file in the xyz directory.", "copyrightText": "Copyright 2008-2010 John Smith", - "fileContributors": ["The Regents of the University of California", - "Modified by Paul Mundt lethal@linux-sh.org", "IBM Corporation"], + "fileContributors": [ + "The Regents of the University of California", + "Modified by Paul Mundt lethal@linux-sh.org", + "IBM Corporation", + ], "fileName": "./package/foo.c", "fileTypes": ["SOURCE"], "licenseComments": "The concluded license was taken from the package level that the file was included in.", "licenseConcluded": "(LGPL-2.0-only OR LicenseRef-2)", "licenseInfoInFiles": ["GPL-2.0-only", "LicenseRef-2", "NOASSERTION"], - "noticeText": "Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: \nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + "noticeText": 'Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: \nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.', } file = file_parser.parse_file(file_dict) assert file.name == "./package/foo.c" assert file.spdx_id == "SPDXRef-File" - TestCase().assertCountEqual(file.checksums, - [Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), - Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24")]) - assert file.comment == "The concluded license was taken from the package level that the file was included in.\nThis information was found in the COPYING.txt file in the xyz directory." + TestCase().assertCountEqual( + file.checksums, + [ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), + Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), + ], + ) + assert ( + file.comment + == "The concluded license was taken from the package level that the file was included in.\nThis information was found in the COPYING.txt file in the xyz directory." + ) assert file.copyright_text == "Copyright 2008-2010 John Smith" assert file.file_types == [FileType.SOURCE] - TestCase().assertCountEqual(file.contributors, ["The Regents of the University of California", - "Modified by Paul Mundt lethal@linux-sh.org", "IBM Corporation"]) + TestCase().assertCountEqual( + file.contributors, + [ + "The Regents of the University of California", + "Modified by Paul Mundt lethal@linux-sh.org", + "IBM Corporation", + ], + ) assert file.license_concluded == Licensing().parse("(LGPL-2.0-only OR LicenseRef-2)") - TestCase().assertCountEqual(file.license_info_in_file, - [Licensing().parse("GPL-2.0-only"), Licensing().parse("LicenseRef-2"), - SpdxNoAssertion()]) - assert file.license_comment == "The concluded license was taken from the package level that the file was included in." + TestCase().assertCountEqual( + file.license_info_in_file, + [Licensing().parse("GPL-2.0-only"), Licensing().parse("LicenseRef-2"), SpdxNoAssertion()], + ) + assert ( + file.license_comment == "The concluded license was taken from the package level that the file was included in." + ) assert file.attribution_texts == ["Some attribution text."] def test_parse_incomplete_file(): file_parser = FileParser() - file_dict = { - "SPDXID": "SPDXRef-File", - "fileName": "Incomplete File" - } + file_dict = {"SPDXID": "SPDXRef-File", "fileName": "Incomplete File"} with pytest.raises(SPDXParsingError) as err: file_parser.parse_file(file_dict) - TestCase().assertCountEqual(err.value.get_messages(), - ["Error while constructing File: ['SetterError File: type of argument " - '"checksums" must be a list; got NoneType instead: None\']']) + TestCase().assertCountEqual( + err.value.get_messages(), + [ + "Error while constructing File: ['SetterError File: type of argument " + '"checksums" must be a list; got NoneType instead: None\']' + ], + ) def test_parse_invalid_files(): file_parser = FileParser() - files = [{"SPDXID": "SPDXRef-File", - "fileName": "Incomplete File"}, - {"SPDXID": "SPDXRef-File", - "attributionTexts": ["Some attribution text."], - "checksums": [{ - "algorithm": "SHA1", - "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2758" - }, { - "algorithm": "MD5", - "checksumValue": "624c1abb3664f4b35547e7c73864ad24" - }]}, - {"SPDXID": "SPDXRef-File", - "attributionTexts": ["Some attribution text."], - "checksums": [{ - "algorithm": "SHA1", - "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2758" - }, { - "algorithm": "MD", - "checksumValue": "624c1abb3664f4b35547e7c73864ad24" - }]}, - ] + files = [ + {"SPDXID": "SPDXRef-File", "fileName": "Incomplete File"}, + { + "SPDXID": "SPDXRef-File", + "attributionTexts": ["Some attribution text."], + "checksums": [ + {"algorithm": "SHA1", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2758"}, + {"algorithm": "MD5", "checksumValue": "624c1abb3664f4b35547e7c73864ad24"}, + ], + }, + { + "SPDXID": "SPDXRef-File", + "attributionTexts": ["Some attribution text."], + "checksums": [ + {"algorithm": "SHA1", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2758"}, + {"algorithm": "MD", "checksumValue": "624c1abb3664f4b35547e7c73864ad24"}, + ], + }, + ] with pytest.raises(SPDXParsingError) as err: parse_list_of_elements(files, file_parser.parse_file) - TestCase().assertCountEqual(err.value.get_messages(), [ - "Error while constructing File: ['SetterError File: type of argument " '"checksums" must be a list; got NoneType instead: None\']', - 'Error while constructing File: [\'SetterError File: type of argument "name" ' "must be str; got NoneType instead: None']", - 'Error while parsing File: ["Error while parsing Checksum: [\'Invalid ChecksumAlgorithm: MD\']"]']) + TestCase().assertCountEqual( + err.value.get_messages(), + [ + "Error while constructing File: ['SetterError File: type of argument " + '"checksums" must be a list; got NoneType instead: None\']', + 'Error while constructing File: [\'SetterError File: type of argument "name" ' + "must be str; got NoneType instead: None']", + "Error while parsing File: [\"Error while parsing Checksum: ['Invalid ChecksumAlgorithm: MD']\"]", + ], + ) def test_parse_file_types(): @@ -128,5 +149,6 @@ def test_parse_invalid_file_types(): with pytest.raises(SPDXParsingError) as err: file_parser.parse_file_types(file_types_list) - TestCase().assertCountEqual(err.value.get_messages(), - ["Error while parsing FileType: ['Invalid FileType: APPLICAON']"]) + TestCase().assertCountEqual( + err.value.get_messages(), ["Error while parsing FileType: ['Invalid FileType: APPLICAON']"] + ) diff --git a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py index b6d45e486..8157afcdf 100644 --- a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py @@ -19,11 +19,15 @@ from spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser -@pytest.mark.parametrize("license_expression_str, expected_license", - [("First License", get_spdx_licensing().parse("First License")), - ("Second License", get_spdx_licensing().parse("Second License")), - ("NOASSERTION", SpdxNoAssertion()), - ("NONE", SpdxNone())]) +@pytest.mark.parametrize( + "license_expression_str, expected_license", + [ + ("First License", get_spdx_licensing().parse("First License")), + ("Second License", get_spdx_licensing().parse("Second License")), + ("NOASSERTION", SpdxNoAssertion()), + ("NONE", SpdxNone()), + ], +) def test_parse_license_expression(license_expression_str, expected_license): license_expression_parser = LicenseExpressionParser() license_expression = license_expression_parser.parse_license_expression(license_expression_str) @@ -31,10 +35,12 @@ def test_parse_license_expression(license_expression_str, expected_license): assert license_expression == expected_license -@pytest.mark.parametrize("invalid_license_expression,expected_message", - [(56, - ["Error parsing LicenseExpression: expression must be a string and not: : 56"]), - ]) +@pytest.mark.parametrize( + "invalid_license_expression,expected_message", + [ + (56, ["Error parsing LicenseExpression: expression must be a string and not: : 56"]), + ], +) def test_parse_invalid_license_expression(invalid_license_expression, expected_message): license_expression_parser = LicenseExpressionParser() diff --git a/tests/spdx/parser/jsonlikedict/test_package_parser.py b/tests/spdx/parser/jsonlikedict/test_package_parser.py index 367f3b795..6890b807f 100644 --- a/tests/spdx/parser/jsonlikedict/test_package_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_package_parser.py @@ -29,35 +29,39 @@ def test_parse_package(): package_dict = { "SPDXID": "SPDXRef-Package", "attributionTexts": [ - "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually."], + "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually." + ], "builtDate": "2011-01-29T18:30:22Z", - "checksums": [{ - "algorithm": "MD5", - "checksumValue": "624c1abb3664f4b35547e7c73864ad24" - }, { - "algorithm": "SHA1", - "checksumValue": "85ed0817af83a24ad8da68c2b5094de69833983c" - }, { - "algorithm": "SHA256", - "checksumValue": "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd" - }, { - "algorithm": "BLAKE2b-384", - "checksumValue": "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706" - }], + "checksums": [ + {"algorithm": "MD5", "checksumValue": "624c1abb3664f4b35547e7c73864ad24"}, + {"algorithm": "SHA1", "checksumValue": "85ed0817af83a24ad8da68c2b5094de69833983c"}, + { + "algorithm": "SHA256", + "checksumValue": "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd", + }, + { + "algorithm": "BLAKE2b-384", + "checksumValue": "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706", + }, + ], "comment": "This is a comment.", "copyrightText": "Copyright 2008-2010 John Smith", "description": "The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems.", "downloadLocation": "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", - "externalRefs": [{ - "referenceCategory": "SECURITY", - "referenceLocator": "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*", - "referenceType": "cpe23Type" - }, { - "comment": "This is the external ref for Acme", - "referenceCategory": "OTHER", - "referenceLocator": "acmecorp/acmenator/4.1.3-alpha", - "referenceType": "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge" - }], + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type", + }, + { + "comment": "This is the external ref for Acme", + "referenceCategory": "OTHER", + "referenceLocator": "acmecorp/acmenator/4.1.3-alpha", + "referenceType": "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301" + "#LocationRef-acmeforge", + }, + ], "filesAnalyzed": True, "homepage": "http://ftp.gnu.org/gnu/glibc", "licenseComments": "The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change.", @@ -69,7 +73,7 @@ def test_parse_package(): "packageFileName": "glibc-2.11.1.tar.gz", "packageVerificationCode": { "packageVerificationCodeExcludedFiles": ["./package.spdx"], - "packageVerificationCodeValue": "d6a770ba38583ed4bb4525bd96e50461655d2758" + "packageVerificationCodeValue": "d6a770ba38583ed4bb4525bd96e50461655d2758", }, "primaryPackagePurpose": "SOURCE", "releaseDate": "2012-01-29T18:30:22Z", @@ -77,7 +81,7 @@ def test_parse_package(): "summary": "GNU C library.", "supplier": "Person: Jane Doe (jane.doe@example.com)", "validUntilDate": "2014-01-29T18:30:22Z", - "versionInfo": "2.11.1" + "versionInfo": "2.11.1", } package = package_parser.parse_package(package_dict) @@ -90,49 +94,92 @@ def test_parse_package(): assert package.supplier == Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com") assert package.originator == Actor(ActorType.ORGANIZATION, "ExampleCodeInspect", "contact@example.com") assert package.files_analyzed == True - assert package.verification_code == PackageVerificationCode(value="d6a770ba38583ed4bb4525bd96e50461655d2758", - excluded_files=["./package.spdx"]) + assert package.verification_code == PackageVerificationCode( + value="d6a770ba38583ed4bb4525bd96e50461655d2758", excluded_files=["./package.spdx"] + ) assert len(package.checksums) == 4 - TestCase().assertCountEqual(package.checksums, [Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), - Checksum(ChecksumAlgorithm.SHA1, - "85ed0817af83a24ad8da68c2b5094de69833983c"), - Checksum(ChecksumAlgorithm.SHA256, - "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd"), - Checksum(ChecksumAlgorithm.BLAKE2B_384, - "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706")]) + TestCase().assertCountEqual( + package.checksums, + [ + Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), + Checksum(ChecksumAlgorithm.SHA1, "85ed0817af83a24ad8da68c2b5094de69833983c"), + Checksum(ChecksumAlgorithm.SHA256, "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd"), + Checksum( + ChecksumAlgorithm.BLAKE2B_384, + "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706", + ), + ], + ) assert package.homepage == "http://ftp.gnu.org/gnu/glibc" assert package.source_info == "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git." assert package.license_concluded == Licensing().parse("(LGPL-2.0-only OR LicenseRef-3)") - TestCase().assertCountEqual(package.license_info_from_files, - [Licensing().parse("GPL-2.0-only"), Licensing().parse("LicenseRef-2"), - Licensing().parse("LicenseRef-1"), SpdxNoAssertion()]) + TestCase().assertCountEqual( + package.license_info_from_files, + [ + Licensing().parse("GPL-2.0-only"), + Licensing().parse("LicenseRef-2"), + Licensing().parse("LicenseRef-1"), + SpdxNoAssertion(), + ], + ) assert package.license_declared == Licensing().parse("(LGPL-2.0-only AND LicenseRef-3)") - assert package.license_comment == "The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change." + assert ( + package.license_comment + == "The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change." + ) assert package.copyright_text == "Copyright 2008-2010 John Smith" assert package.summary == "GNU C library." - assert package.description == "The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems." + assert ( + package.description + == "The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems." + ) assert package.comment == "This is a comment." assert len(package.external_references) == 2 - TestCase().assertCountEqual(package.external_references, [ExternalPackageRef(ExternalPackageRefCategory.SECURITY, - "cpe23Type", - "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*"), - ExternalPackageRef(ExternalPackageRefCategory.OTHER, - "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge", - locator="acmecorp/acmenator/4.1.3-alpha", - comment="This is the external ref for Acme")]) + TestCase().assertCountEqual( + package.external_references, + [ + ExternalPackageRef( + ExternalPackageRefCategory.SECURITY, + "cpe23Type", + "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*", + ), + ExternalPackageRef( + ExternalPackageRefCategory.OTHER, + "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge", + locator="acmecorp/acmenator/4.1.3-alpha", + comment="This is the external ref for Acme", + ), + ], + ) assert package.attribution_texts == [ - "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually."] + "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually." + ] assert package.primary_package_purpose == PackagePurpose.SOURCE assert package.release_date == datetime(2012, 1, 29, 18, 30, 22) assert package.built_date == datetime(2011, 1, 29, 18, 30, 22) assert package.valid_until_date == datetime(2014, 1, 29, 18, 30, 22) -@pytest.mark.parametrize("incomplete_package_dict,expected_message", [({"SPDXID": "SPDXRef-Package"}, [ - "Error while constructing Package: ['SetterError Package: type of " 'argument "name" must be str; got NoneType instead: None\', \'SetterError Package: type of argument "download_location" must be one of (str, spdx.model.spdx_no_assertion.SpdxNoAssertion, spdx.model.spdx_none.SpdxNone); ' "got NoneType instead: None']"]), - ({"SPDXID": "SPDXRef-Package", "name": 5, - "downloadLocation": "NONE"}, [ - "Error while constructing Package: ['SetterError Package: type of argument " '"name" must be str; got int instead: 5\']'])]) +@pytest.mark.parametrize( + "incomplete_package_dict,expected_message", + [ + ( + {"SPDXID": "SPDXRef-Package"}, + [ + "Error while constructing Package: ['SetterError Package: type of " + 'argument "name" must be str; got NoneType instead: None\', \'SetterError Package: type of argument "download_location" must be one of (str, spdx.model.spdx_no_assertion.SpdxNoAssertion, spdx.model.spdx_none.SpdxNone); ' + "got NoneType instead: None']" + ], + ), + ( + {"SPDXID": "SPDXRef-Package", "name": 5, "downloadLocation": "NONE"}, + [ + "Error while constructing Package: ['SetterError Package: type of argument " + '"name" must be str; got int instead: 5\']' + ], + ), + ], +) def test_parse_incomplete_package(incomplete_package_dict, expected_message): package_parser = PackageParser() @@ -148,59 +195,62 @@ def test_parse_invalid_package(): "SPDXID": "SPDXRef-Package", "name": "Example Package", "downloadLocation": "NONE", - "checksums": - [{"algorithm": "SHA", - "value": "1234"}] + "checksums": [{"algorithm": "SHA", "value": "1234"}], } with pytest.raises(SPDXParsingError) as err: package_parser.parse_package(package_dict) - TestCase().assertCountEqual(err.value.get_messages(), [ - 'Error while parsing Package: ["Error while parsing Checksum: [\'Invalid ChecksumAlgorithm: SHA\']"]']) + TestCase().assertCountEqual( + err.value.get_messages(), + ["Error while parsing Package: [\"Error while parsing Checksum: ['Invalid ChecksumAlgorithm: SHA']\"]"], + ) def test_parse_packages(): package_parser = PackageParser() - packages_list = [{ - "SPDXID": "SPDXRef-Package", - "name": "Example Package", - "downloadLocation": "NONE", - "checksums": - [{"algorithm": "SHA", - "value": "1234"}] - }, { - "SPDXID": "SPDXRef-Package", - "name": 5, - "downloadLocation": "NONE" - }, + packages_list = [ { "SPDXID": "SPDXRef-Package", "name": "Example Package", - "downloadLocation": "NONE"} + "downloadLocation": "NONE", + "checksums": [{"algorithm": "SHA", "value": "1234"}], + }, + {"SPDXID": "SPDXRef-Package", "name": 5, "downloadLocation": "NONE"}, + {"SPDXID": "SPDXRef-Package", "name": "Example Package", "downloadLocation": "NONE"}, ] with pytest.raises(SPDXParsingError) as err: parse_list_of_elements(packages_list, package_parser.parse_package) - TestCase().assertCountEqual(err.value.get_messages(), - ['Error while parsing Package: ["Error while parsing Checksum: ' - '[\'Invalid ChecksumAlgorithm: SHA\']"]', - "Error while constructing Package: ['SetterError Package: type of argument " - '"name" must be str; got int instead: 5\']']) + TestCase().assertCountEqual( + err.value.get_messages(), + [ + 'Error while parsing Package: ["Error while parsing Checksum: ' "['Invalid ChecksumAlgorithm: SHA']\"]", + "Error while constructing Package: ['SetterError Package: type of argument " + '"name" must be str; got int instead: 5\']', + ], + ) def test_parse_external_ref(): package_parser = PackageParser() - external_ref = { - "referenceType": "fix" - } + external_ref = {"referenceType": "fix"} with pytest.raises(SPDXParsingError) as err: package_parser.parse_external_ref(external_ref) - TestCase().assertCountEqual(err.value.get_messages(), [ - "Error while constructing ExternalPackageRef: ['SetterError " 'ExternalPackageRef: type of argument "category" must be ' "spdx.model.package.ExternalPackageRefCategory; got NoneType instead: None', " '\'SetterError ExternalPackageRef: type of argument "locator" must be str; ' "got NoneType instead: None']"]) + TestCase().assertCountEqual( + err.value.get_messages(), + [ + "Error while constructing ExternalPackageRef: ['SetterError " + 'ExternalPackageRef: type of argument "category" must be ' + "spdx.model.package.ExternalPackageRefCategory; got NoneType instead: None', " + '\'SetterError ExternalPackageRef: type of argument "locator" must be str; ' + "got NoneType instead: None']" + ], + ) + def test_parse_invalid_external_package_ref_category(): package_parser = PackageParser() diff --git a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py index 3bf8fae2a..01f67833a 100644 --- a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py @@ -25,7 +25,7 @@ def test_parse_relationship(): "spdxElementId": "SPDXRef-DOCUMENT", "relationshipType": "CONTAINS", "relatedSpdxElement": "NOASSERTION", - "comment": "Comment." + "comment": "Comment.", } relationship = relationship_parser.parse_relationship(relationship_dict) @@ -41,14 +41,20 @@ def test_parse_incomplete_relationship(): relationship_dict = { "spdxElementId": "SPDXRef-DOCUMENT", "relatedSpdxElement": "SPDXRef-Package", - "comment": "Comment." + "comment": "Comment.", } with pytest.raises(SPDXParsingError) as err: relationship_parser.parse_relationship(relationship_dict) - TestCase().assertCountEqual(err.value.get_messages(), [ - "Error while constructing Relationship: ['SetterError Relationship: type of " 'argument "relationship_type" must be ' "spdx.model.relationship.RelationshipType; got NoneType instead: None']"]) + TestCase().assertCountEqual( + err.value.get_messages(), + [ + "Error while constructing Relationship: ['SetterError Relationship: type of " + 'argument "relationship_type" must be ' + "spdx.model.relationship.RelationshipType; got NoneType instead: None']" + ], + ) def test_parse_relationship_type(): @@ -64,49 +70,87 @@ def test_parse_document_describes(): document_dict = { "SPDXID": "SPDXRef-DOCUMENT", - "documentDescribes": ["SPDXRef-Package", "SPDXRef-File", "SPDXRef-Snippet"] + "documentDescribes": ["SPDXRef-Package", "SPDXRef-File", "SPDXRef-Snippet"], } - relationships = relationship_parser.parse_document_describes(doc_spdx_id="SPDXRef-DOCUMENT", - described_spdx_ids=document_dict.get( - "documentDescribes"), - existing_relationships=[]) + relationships = relationship_parser.parse_document_describes( + doc_spdx_id="SPDXRef-DOCUMENT", + described_spdx_ids=document_dict.get("documentDescribes"), + existing_relationships=[], + ) assert len(relationships) == 3 - TestCase().assertCountEqual(relationships, - [Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package"), - Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-File"), - Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Snippet")]) - - -@pytest.mark.parametrize("document_describes,relationships,parsed_relationships", - [(["SPDXRef-Package", "SPDXRef-File"], [ - {"spdxElementId": "SPDXRef-DOCUMENT", "relatedSpdxElement": "SPDXRef-Package", - "relationshipType": "DESCRIBES", "comment": "This relationship has a comment."}, - {"spdxElementId": "SPDXRef-File", "relatedSpdxElement": "SPDXRef-DOCUMENT", - "relationshipType": "DESCRIBED_BY", "comment": "This relationship has a comment."}], [ - Relationship(related_spdx_element_id="SPDXRef-Package", - relationship_type=RelationshipType.DESCRIBES, - spdx_element_id="SPDXRef-DOCUMENT", - comment="This relationship has a comment."), - Relationship(related_spdx_element_id="SPDXRef-DOCUMENT", - relationship_type=RelationshipType.DESCRIBED_BY, - spdx_element_id="SPDXRef-File", - comment="This relationship has a comment.")]), - (["SPDXRef-Package", "SPDXRef-File", "SPDXRef-Package"], [], [ - Relationship(related_spdx_element_id="SPDXRef-Package", - relationship_type=RelationshipType.DESCRIBES, - spdx_element_id="SPDXRef-DOCUMENT"), - Relationship(related_spdx_element_id="SPDXRef-File", - relationship_type=RelationshipType.DESCRIBES, - spdx_element_id="SPDXRef-DOCUMENT")])]) -def test_parse_document_describes_without_duplicating_relationships(document_describes, relationships, - parsed_relationships): + TestCase().assertCountEqual( + relationships, + [ + Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package"), + Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-File"), + Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Snippet"), + ], + ) + + +@pytest.mark.parametrize( + "document_describes,relationships,parsed_relationships", + [ + ( + ["SPDXRef-Package", "SPDXRef-File"], + [ + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relatedSpdxElement": "SPDXRef-Package", + "relationshipType": "DESCRIBES", + "comment": "This relationship has a comment.", + }, + { + "spdxElementId": "SPDXRef-File", + "relatedSpdxElement": "SPDXRef-DOCUMENT", + "relationshipType": "DESCRIBED_BY", + "comment": "This relationship has a comment.", + }, + ], + [ + Relationship( + related_spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.DESCRIBES, + spdx_element_id="SPDXRef-DOCUMENT", + comment="This relationship has a comment.", + ), + Relationship( + related_spdx_element_id="SPDXRef-DOCUMENT", + relationship_type=RelationshipType.DESCRIBED_BY, + spdx_element_id="SPDXRef-File", + comment="This relationship has a comment.", + ), + ], + ), + ( + ["SPDXRef-Package", "SPDXRef-File", "SPDXRef-Package"], + [], + [ + Relationship( + related_spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.DESCRIBES, + spdx_element_id="SPDXRef-DOCUMENT", + ), + Relationship( + related_spdx_element_id="SPDXRef-File", + relationship_type=RelationshipType.DESCRIBES, + spdx_element_id="SPDXRef-DOCUMENT", + ), + ], + ), + ], +) +def test_parse_document_describes_without_duplicating_relationships( + document_describes, relationships, parsed_relationships +): relationship_parser = RelationshipParser() document_dict = { "SPDXID": "SPDXRef-DOCUMENT", "documentDescribes": document_describes, - "relationships": relationships} + "relationships": relationships, + } relationships = relationship_parser.parse_all_relationships(document_dict) @@ -116,52 +160,72 @@ def test_parse_document_describes_without_duplicating_relationships(document_des def test_parse_has_files(): relationship_parser = RelationshipParser() - document_dict = { - "packages": - [{ - "SPDXID": "SPDXRef-Package", - "hasFiles": ["SPDXRef-File1", "SPDXRef-File2"] - }] - } + document_dict = {"packages": [{"SPDXID": "SPDXRef-Package", "hasFiles": ["SPDXRef-File1", "SPDXRef-File2"]}]} relationships = relationship_parser.parse_has_files(document_dict.get("packages"), existing_relationships=[]) assert len(relationships) == 2 - TestCase().assertCountEqual(relationships, [ - Relationship(spdx_element_id="SPDXRef-Package", relationship_type=RelationshipType.CONTAINS, - related_spdx_element_id="SPDXRef-File1"), - Relationship(spdx_element_id="SPDXRef-Package", relationship_type=RelationshipType.CONTAINS, - related_spdx_element_id="SPDXRef-File2")]) - - -@pytest.mark.parametrize("has_files,existing_relationships,contains_relationships", - [(["SPDXRef-File1", "SPDXRef-File2"], [ - Relationship(spdx_element_id="SPDXRef-Package", - relationship_type=RelationshipType.CONTAINS, - related_spdx_element_id="SPDXRef-File1", - comment="This relationship has a comment."), - Relationship(spdx_element_id="SPDXRef-File2", - relationship_type=RelationshipType.CONTAINED_BY, - related_spdx_element_id="SPDXRef-Package")], []), - (["SPDXRef-File1", "SPDXRef-File2", "SPDXRef-File1"], [], [ - Relationship(spdx_element_id="SPDXRef-Package", - relationship_type=RelationshipType.CONTAINS, - related_spdx_element_id="SPDXRef-File1"), - Relationship(spdx_element_id="SPDXRef-Package", - relationship_type=RelationshipType.CONTAINS, - related_spdx_element_id="SPDXRef-File2")])]) -def test_parse_has_files_without_duplicating_relationships(has_files, existing_relationships, - contains_relationships): + TestCase().assertCountEqual( + relationships, + [ + Relationship( + spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id="SPDXRef-File1", + ), + Relationship( + spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id="SPDXRef-File2", + ), + ], + ) + + +@pytest.mark.parametrize( + "has_files,existing_relationships,contains_relationships", + [ + ( + ["SPDXRef-File1", "SPDXRef-File2"], + [ + Relationship( + spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id="SPDXRef-File1", + comment="This relationship has a comment.", + ), + Relationship( + spdx_element_id="SPDXRef-File2", + relationship_type=RelationshipType.CONTAINED_BY, + related_spdx_element_id="SPDXRef-Package", + ), + ], + [], + ), + ( + ["SPDXRef-File1", "SPDXRef-File2", "SPDXRef-File1"], + [], + [ + Relationship( + spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id="SPDXRef-File1", + ), + Relationship( + spdx_element_id="SPDXRef-Package", + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id="SPDXRef-File2", + ), + ], + ), + ], +) +def test_parse_has_files_without_duplicating_relationships(has_files, existing_relationships, contains_relationships): relationship_parser = RelationshipParser() - document_dict = { - "packages": - [{ - "SPDXID": "SPDXRef-Package", - "hasFiles": has_files - }] - } - relationships = relationship_parser.parse_has_files(document_dict.get("packages"), - existing_relationships=existing_relationships) + document_dict = {"packages": [{"SPDXID": "SPDXRef-Package", "hasFiles": has_files}]} + relationships = relationship_parser.parse_has_files( + document_dict.get("packages"), existing_relationships=existing_relationships + ) assert len(relationships) == len(contains_relationships) TestCase().assertCountEqual(relationships, contains_relationships) diff --git a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py index 14882aa2b..3a78d4e86 100644 --- a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py @@ -29,35 +29,32 @@ def test_parse_snippet(): "licenseConcluded": "GPL-2.0-only", "licenseInfoInSnippets": ["GPL-2.0-only", "NOASSERTION"], "name": "from linux kernel", - "ranges": [{ - "endPointer": { - "offset": 420, - "reference": "SPDXRef-DoapSource" + "ranges": [ + { + "endPointer": {"offset": 420, "reference": "SPDXRef-DoapSource"}, + "startPointer": {"offset": 310, "reference": "SPDXRef-DoapSource"}, }, - "startPointer": { - "offset": 310, - "reference": "SPDXRef-DoapSource" - } - }, { - "endPointer": { - "lineNumber": 23, - "reference": "SPDXRef-DoapSource" + { + "endPointer": {"lineNumber": 23, "reference": "SPDXRef-DoapSource"}, + "startPointer": {"lineNumber": 5, "reference": "SPDXRef-DoapSource"}, }, - "startPointer": { - "lineNumber": 5, - "reference": "SPDXRef-DoapSource" - } - }], + ], "snippetFromFile": "SPDXRef-DoapSource", - "attributionTexts": ["Some example attibution text."] + "attributionTexts": ["Some example attibution text."], } snippet = snippet_parser.parse_snippet(snippet_dict) assert snippet.spdx_id == "SPDXRef-Snippet" assert snippet.name == "from linux kernel" - assert snippet.comment == "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0." + assert ( + snippet.comment + == "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0." + ) assert snippet.copyright_text == "Copyright 2008-2010 John Smith" - assert snippet.license_comment == "The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz." + assert ( + snippet.license_comment + == "The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz." + ) assert snippet.byte_range == (310, 420) assert snippet.line_range == (5, 23) assert snippet.file_spdx_id == "SPDXRef-DoapSource" @@ -68,17 +65,19 @@ def test_parse_snippet(): def test_parse_incomplete_snippet(): snippet_parser = SnippetParser() - incomplete_snippet_dict = { - "SPDXID": "SPDXRef-Snippet", - "file_spdx_id": "SPDXRef-File" - } + incomplete_snippet_dict = {"SPDXID": "SPDXRef-Snippet", "file_spdx_id": "SPDXRef-File"} with pytest.raises(SPDXParsingError) as err: snippet_parser.parse_snippet(incomplete_snippet_dict) - TestCase().assertCountEqual(err.value.get_messages(), [ - "Error while constructing Snippet: ['SetterError Snippet: type of argument " '"file_spdx_id" must be str; got NoneType instead: None\', \'SetterError Snippet: type of argument "byte_range" must be a tuple; got NoneType ' - "instead: None']"]) + TestCase().assertCountEqual( + err.value.get_messages(), + [ + "Error while constructing Snippet: ['SetterError Snippet: type of argument " + '"file_spdx_id" must be str; got NoneType instead: None\', \'SetterError Snippet: type of argument "byte_range" must be a tuple; got NoneType ' + "instead: None']" + ], + ) def test_parse_snippet_with_invalid_snippet_range(): @@ -88,25 +87,24 @@ def test_parse_snippet_with_invalid_snippet_range(): "file_spdx_id": "SPDXRef-File", "ranges": [ { - "endPointer": { - "offset": 23, - "reference": "SPDXRef-DoapSource" - }, - "startPointer": { - "offset": "310s", - "reference": "SPDXRef-DoapSource" - } - }] + "endPointer": {"offset": 23, "reference": "SPDXRef-DoapSource"}, + "startPointer": {"offset": "310s", "reference": "SPDXRef-DoapSource"}, + } + ], } with pytest.raises(SPDXParsingError) as err: snippet_parser.parse_snippet(snippet_with_invalid_ranges_list) - TestCase().assertCountEqual(err.value.get_messages(), - ["Error while constructing Snippet: ['SetterError Snippet: type of argument " - '"file_spdx_id" must be str; got NoneType instead: None\', \'SetterError ' - 'Snippet: type of argument "byte_range"[0] must be int; got str instead: ' - "(\\'310s\\', 23)']"]) + TestCase().assertCountEqual( + err.value.get_messages(), + [ + "Error while constructing Snippet: ['SetterError Snippet: type of argument " + "\"file_spdx_id\" must be str; got NoneType instead: None', 'SetterError " + 'Snippet: type of argument "byte_range"[0] must be int; got str instead: ' + "(\\'310s\\', 23)']" + ], + ) def test_parse_invalid_snippet_range(): @@ -114,29 +112,21 @@ def test_parse_invalid_snippet_range(): ranges = [ { - "endPointer": { - "lineNumber": 23, - "reference": "SPDXRef-DoapSource" - }, - "startPointer": { - "offset": 310, - "reference": "SPDXRef-DoapSource" - } - }, { - "endPointer": { - "offset": 420, - "reference": "SPDXRef-DoapSource" - }, - "startPointer": { - "lineNumber": 5, - "reference": "SPDXRef-DoapSource" - } - } - + "endPointer": {"lineNumber": 23, "reference": "SPDXRef-DoapSource"}, + "startPointer": {"offset": 310, "reference": "SPDXRef-DoapSource"}, + }, + { + "endPointer": {"offset": 420, "reference": "SPDXRef-DoapSource"}, + "startPointer": {"lineNumber": 5, "reference": "SPDXRef-DoapSource"}, + }, ] with pytest.raises(SPDXParsingError) as err: snippet_parser.parse_ranges(ranges) - TestCase().assertCountEqual(err.value.get_messages(), [ - "Error while parsing snippet ranges: ['Type of startpointer is not the same as type of endpointer.', 'Type of startpointer is not the same as type of endpointer.']"]) + TestCase().assertCountEqual( + err.value.get_messages(), + [ + "Error while parsing snippet ranges: ['Type of startpointer is not the same as type of endpointer.', 'Type of startpointer is not the same as type of endpointer.']" + ], + ) diff --git a/tests/spdx/parser/rdf/test_checksum_parser.py b/tests/spdx/parser/rdf/test_checksum_parser.py index 4cadb17b3..2597fd83f 100644 --- a/tests/spdx/parser/rdf/test_checksum_parser.py +++ b/tests/spdx/parser/rdf/test_checksum_parser.py @@ -20,10 +20,10 @@ def test_parse_checksum(): - graph = Graph().parse(os.path.join(os.path.dirname(__file__), - "data/file_to_test_rdf_parser.rdf.xml")) - checksum_node = graph.value(subject=URIRef("https://some.namespace#DocumentRef-external"), - predicate=SPDX_NAMESPACE.checksum) + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + checksum_node = graph.value( + subject=URIRef("https://some.namespace#DocumentRef-external"), predicate=SPDX_NAMESPACE.checksum + ) checksum = parse_checksum(checksum_node, graph) @@ -31,40 +31,44 @@ def test_parse_checksum(): assert checksum.value == "71c4025dd9897b364f3ebbb42c484ff43d00791c" -@pytest.mark.parametrize("rdf_element,expected", [(SPDX_NAMESPACE.checksumAlgorithm_sha1, ChecksumAlgorithm.SHA1), - (SPDX_NAMESPACE.checksumAlgorithm_sha224, ChecksumAlgorithm.SHA224), - (SPDX_NAMESPACE.checksumAlgorithm_sha256, ChecksumAlgorithm.SHA256), - (SPDX_NAMESPACE.checksumAlgorithm_sha384, ChecksumAlgorithm.SHA384), - (SPDX_NAMESPACE.checksumAlgorithm_sha512, ChecksumAlgorithm.SHA512), - (SPDX_NAMESPACE.checksumAlgorithm_sha3_256, - ChecksumAlgorithm.SHA3_256), - (SPDX_NAMESPACE.checksumAlgorithm_sha3_384, - ChecksumAlgorithm.SHA3_384), - (SPDX_NAMESPACE.checksumAlgorithm_sha3_512, - ChecksumAlgorithm.SHA3_512), - (SPDX_NAMESPACE.checksumAlgorithm_blake2b256, - ChecksumAlgorithm.BLAKE2B_256), - (SPDX_NAMESPACE.checksumAlgorithm_blake2b384, - ChecksumAlgorithm.BLAKE2B_384), - (SPDX_NAMESPACE.checksumAlgorithm_blake2b512, - ChecksumAlgorithm.BLAKE2B_512), - (SPDX_NAMESPACE.checksumAlgorithm_blake3, ChecksumAlgorithm.BLAKE3), - (SPDX_NAMESPACE.checksumAlgorithm_md2, ChecksumAlgorithm.MD2), - (SPDX_NAMESPACE.checksumAlgorithm_md4, ChecksumAlgorithm.MD4), - (SPDX_NAMESPACE.checksumAlgorithm_md5, ChecksumAlgorithm.MD5), - (SPDX_NAMESPACE.checksumAlgorithm_md6, ChecksumAlgorithm.MD6), - (SPDX_NAMESPACE.checksumAlgorithm_adler32, ChecksumAlgorithm.ADLER32) - ]) +@pytest.mark.parametrize( + "rdf_element,expected", + [ + (SPDX_NAMESPACE.checksumAlgorithm_sha1, ChecksumAlgorithm.SHA1), + (SPDX_NAMESPACE.checksumAlgorithm_sha224, ChecksumAlgorithm.SHA224), + (SPDX_NAMESPACE.checksumAlgorithm_sha256, ChecksumAlgorithm.SHA256), + (SPDX_NAMESPACE.checksumAlgorithm_sha384, ChecksumAlgorithm.SHA384), + (SPDX_NAMESPACE.checksumAlgorithm_sha512, ChecksumAlgorithm.SHA512), + (SPDX_NAMESPACE.checksumAlgorithm_sha3_256, ChecksumAlgorithm.SHA3_256), + (SPDX_NAMESPACE.checksumAlgorithm_sha3_384, ChecksumAlgorithm.SHA3_384), + (SPDX_NAMESPACE.checksumAlgorithm_sha3_512, ChecksumAlgorithm.SHA3_512), + (SPDX_NAMESPACE.checksumAlgorithm_blake2b256, ChecksumAlgorithm.BLAKE2B_256), + (SPDX_NAMESPACE.checksumAlgorithm_blake2b384, ChecksumAlgorithm.BLAKE2B_384), + (SPDX_NAMESPACE.checksumAlgorithm_blake2b512, ChecksumAlgorithm.BLAKE2B_512), + (SPDX_NAMESPACE.checksumAlgorithm_blake3, ChecksumAlgorithm.BLAKE3), + (SPDX_NAMESPACE.checksumAlgorithm_md2, ChecksumAlgorithm.MD2), + (SPDX_NAMESPACE.checksumAlgorithm_md4, ChecksumAlgorithm.MD4), + (SPDX_NAMESPACE.checksumAlgorithm_md5, ChecksumAlgorithm.MD5), + (SPDX_NAMESPACE.checksumAlgorithm_md6, ChecksumAlgorithm.MD6), + (SPDX_NAMESPACE.checksumAlgorithm_adler32, ChecksumAlgorithm.ADLER32), + ], +) def test_convert_rdf_to_algorithm(rdf_element, expected): algorithm = convert_rdf_to_algorithm(rdf_element) assert algorithm == expected -@pytest.mark.parametrize("invalid_rdf_element", - [SPDX_NAMESPACE.checksumAlgorithm_blake2b_512, SPDX_NAMESPACE.checksumAlgorithm_BLAKE2b_512, - SPDX_NAMESPACE.checksumAlgorithm_sha3512, SPDX_NAMESPACE.checksumAlgorithm_sha513, - SPDX_NAMESPACE.checksumalgorithm_blake2b_512]) +@pytest.mark.parametrize( + "invalid_rdf_element", + [ + SPDX_NAMESPACE.checksumAlgorithm_blake2b_512, + SPDX_NAMESPACE.checksumAlgorithm_BLAKE2b_512, + SPDX_NAMESPACE.checksumAlgorithm_sha3512, + SPDX_NAMESPACE.checksumAlgorithm_sha513, + SPDX_NAMESPACE.checksumalgorithm_blake2b_512, + ], +) def test_convert_invalid_rdf_to_algorithm(invalid_rdf_element): with pytest.raises(SPDXParsingError): convert_rdf_to_algorithm(invalid_rdf_element) diff --git a/tests/spdx/parser/rdf/test_creation_info_parser.py b/tests/spdx/parser/rdf/test_creation_info_parser.py index 0580a3802..ba5cd19c2 100644 --- a/tests/spdx/parser/rdf/test_creation_info_parser.py +++ b/tests/spdx/parser/rdf/test_creation_info_parser.py @@ -52,16 +52,27 @@ def test_parse_namespace_and_spdx_id(): assert spdx_id == "spdxID" -@pytest.mark.parametrize("triples,error_message", - [([(URIRef("docNamespace"), RDF.type, SPDX_NAMESPACE.SpdxDocument)], - r"No '#' found in the URI of SpdxDocument"), - ([(URIRef(""), RDF.type, URIRef(""))], r"No SpdxDocument found, can't parse rdf file."), - ([(URIRef("#SPDXRef-DOCUMENT"), RDF.type, SPDX_NAMESPACE.SpdxDocument)], - "No namespace found"), - ([(URIRef("docNamespace1"), RDF.type, SPDX_NAMESPACE.SpdxDocument), - (URIRef("docNamespace2"), RDF.type, SPDX_NAMESPACE.SpdxDocument)], - "Multiple SpdxDocuments found")]) -def test_parse_namespace_and_spdx_id_with_system_exit(triples: List[Tuple[Node, Node, Node]], error_message: str, caplog): +@pytest.mark.parametrize( + "triples,error_message", + [ + ( + [(URIRef("docNamespace"), RDF.type, SPDX_NAMESPACE.SpdxDocument)], + r"No '#' found in the URI of SpdxDocument", + ), + ([(URIRef(""), RDF.type, URIRef(""))], r"No SpdxDocument found, can't parse rdf file."), + ([(URIRef("#SPDXRef-DOCUMENT"), RDF.type, SPDX_NAMESPACE.SpdxDocument)], "No namespace found"), + ( + [ + (URIRef("docNamespace1"), RDF.type, SPDX_NAMESPACE.SpdxDocument), + (URIRef("docNamespace2"), RDF.type, SPDX_NAMESPACE.SpdxDocument), + ], + "Multiple SpdxDocuments found", + ), + ], +) +def test_parse_namespace_and_spdx_id_with_system_exit( + triples: List[Tuple[Node, Node, Node]], error_message: str, caplog +): graph = Graph() for triple in triples: graph = graph.add(triple) @@ -75,12 +86,14 @@ def test_parse_namespace_and_spdx_id_with_system_exit(triples: List[Tuple[Node, def test_parse_external_document_refs(): graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) doc_namespace = "https://some.namespace" - external_doc_ref_node = graph.value(subject=URIRef(f"{doc_namespace}#SPDXRef-DOCUMENT"), - predicate=SPDX_NAMESPACE.externalDocumentRef) + external_doc_ref_node = graph.value( + subject=URIRef(f"{doc_namespace}#SPDXRef-DOCUMENT"), predicate=SPDX_NAMESPACE.externalDocumentRef + ) external_document_ref = parse_external_document_refs(external_doc_ref_node, graph, doc_namespace) assert external_document_ref.document_ref_id == "DocumentRef-external" - assert external_document_ref.checksum == Checksum(ChecksumAlgorithm.SHA1, - "71c4025dd9897b364f3ebbb42c484ff43d00791c") + assert external_document_ref.checksum == Checksum( + ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c" + ) assert external_document_ref.document_uri == "https://namespace.com" diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py index f6142e3ba..33d168b4b 100644 --- a/tests/spdx/parser/rdf/test_file_parser.py +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -36,9 +36,10 @@ def test_parse_file(): assert file.copyright_text == "copyrightText" assert file.contributors == ["fileContributor"] assert file.license_concluded == get_spdx_licensing().parse("MIT AND GPL-2.0") - TestCase().assertCountEqual(file.license_info_in_file, - [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), - SpdxNoAssertion()]) + TestCase().assertCountEqual( + file.license_info_in_file, + [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()], + ) assert file.license_comment == "licenseComment" assert file.notice == "fileNotice" assert file.attribution_texts == ["fileAttributionText"] diff --git a/tests/spdx/parser/rdf/test_graph_parsing_function.py b/tests/spdx/parser/rdf/test_graph_parsing_function.py index 48240aad0..5a1118c2a 100644 --- a/tests/spdx/parser/rdf/test_graph_parsing_function.py +++ b/tests/spdx/parser/rdf/test_graph_parsing_function.py @@ -14,13 +14,20 @@ from spdx.parser.rdf.graph_parsing_functions import parse_spdx_id, remove_prefix -@pytest.mark.parametrize("resource,doc_namespace,ext_namespace_mapping,expected", - [(URIRef("docNamespace#SPDXRef-Test"), "docNamespace", ("", Namespace("")), "SPDXRef-Test"), - (URIRef("docNamespaceSPDXRef-Test"), "docNamespace", ("", Namespace("")), - "docNamespaceSPDXRef-Test"), - (URIRef("differentNamespace#SPDXRef-Test"), "docNamespace", - ("extDoc", Namespace("differentNamespace#")), "extDoc:SPDXRef-Test"), - (None, "", ("", Namespace("")), None)]) +@pytest.mark.parametrize( + "resource,doc_namespace,ext_namespace_mapping,expected", + [ + (URIRef("docNamespace#SPDXRef-Test"), "docNamespace", ("", Namespace("")), "SPDXRef-Test"), + (URIRef("docNamespaceSPDXRef-Test"), "docNamespace", ("", Namespace("")), "docNamespaceSPDXRef-Test"), + ( + URIRef("differentNamespace#SPDXRef-Test"), + "docNamespace", + ("extDoc", Namespace("differentNamespace#")), + "extDoc:SPDXRef-Test", + ), + (None, "", ("", Namespace("")), None), + ], +) def test_parse_spdx_id(resource, doc_namespace, ext_namespace_mapping, expected): graph = Graph() graph.bind(*ext_namespace_mapping) @@ -29,8 +36,9 @@ def test_parse_spdx_id(resource, doc_namespace, ext_namespace_mapping, expected) assert spdx_id == expected -@pytest.mark.parametrize("string,prefix,expected", [("prefixString", "prefix", "String"), - ("prefixString", "refix", "prefixString")]) +@pytest.mark.parametrize( + "string,prefix,expected", [("prefixString", "prefix", "String"), ("prefixString", "refix", "prefixString")] +) def test_remove_prefix(string, prefix, expected): shorten_string = remove_prefix(string, prefix) diff --git a/tests/spdx/parser/rdf/test_license_expression_parser.py b/tests/spdx/parser/rdf/test_license_expression_parser.py index 012e8854e..3a529e768 100644 --- a/tests/spdx/parser/rdf/test_license_expression_parser.py +++ b/tests/spdx/parser/rdf/test_license_expression_parser.py @@ -31,17 +31,25 @@ def test_license_expression_parser(): def test_license_expression_parser_with_coupled_licenses(): doc = rdf_parser.parse_from_file( - os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXRdfExample-v2.3.spdx.rdf.xml")) + os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXRdfExample-v2.3.spdx.rdf.xml") + ) packages_by_spdx_id = {package.spdx_id: package for package in doc.packages} files_by_spdx_id = {file.spdx_id: file for file in doc.files} assert packages_by_spdx_id["SPDXRef-Package"].license_declared == get_spdx_licensing().parse( - "LGPL-2.0-only AND LicenseRef-3") + "LGPL-2.0-only AND LicenseRef-3" + ) assert packages_by_spdx_id["SPDXRef-Package"].license_concluded == get_spdx_licensing().parse( - "LGPL-2.0-only OR LicenseRef-3") - TestCase().assertCountEqual(packages_by_spdx_id["SPDXRef-Package"].license_info_from_files, - [get_spdx_licensing().parse("GPL-2.0"), get_spdx_licensing().parse("LicenseRef-1"), - get_spdx_licensing().parse("LicenseRef-2")]) + "LGPL-2.0-only OR LicenseRef-3" + ) + TestCase().assertCountEqual( + packages_by_spdx_id["SPDXRef-Package"].license_info_from_files, + [ + get_spdx_licensing().parse("GPL-2.0"), + get_spdx_licensing().parse("LicenseRef-1"), + get_spdx_licensing().parse("LicenseRef-2"), + ], + ) assert files_by_spdx_id["SPDXRef-JenaLib"].license_concluded == get_spdx_licensing().parse("LicenseRef-1") diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index 1b87e8f7f..ff4974286 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -42,13 +42,15 @@ def test_package_parser(): assert package.source_info == "sourceInfo" assert package.license_concluded == get_spdx_licensing().parse("MIT AND GPL-2.0") assert package.license_declared == get_spdx_licensing().parse("MIT AND GPL-2.0") - TestCase().assertCountEqual(package.license_info_from_files, - [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), - SpdxNoAssertion()]) + TestCase().assertCountEqual( + package.license_info_from_files, + [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()], + ) assert package.license_comment == "packageLicenseComment" assert package.copyright_text == "packageCopyrightText" - assert package.verification_code == PackageVerificationCode(value="85ed0817af83a24ad8da68c2b5094de69833983c", - excluded_files=["./exclude.py"]) + assert package.verification_code == PackageVerificationCode( + value="85ed0817af83a24ad8da68c2b5094de69833983c", excluded_files=["./exclude.py"] + ) assert len(package.external_references) == 1 assert package.summary == "packageSummary" assert package.description == "packageDescription" @@ -59,11 +61,25 @@ def test_package_parser(): assert package.originator == Actor(ActorType.PERSON, "originatorName", "some@mail.com") -@pytest.mark.parametrize("download_location,category,locator,type,comment", - [("https://download.com", ExternalPackageRefCategory.PACKAGE_MANAGER, - "org.apache.tomcat:tomcat:9.0.0.M4", "maven-central", "externalPackageRefComment"), - ("http://differentdownload.com", ExternalPackageRefCategory.OTHER, - "acmecorp/acmenator/4.1.3-alpha", "LocationRef-acmeforge","This is the external ref for Acme")]) +@pytest.mark.parametrize( + "download_location,category,locator,type,comment", + [ + ( + "https://download.com", + ExternalPackageRefCategory.PACKAGE_MANAGER, + "org.apache.tomcat:tomcat:9.0.0.M4", + "maven-central", + "externalPackageRefComment", + ), + ( + "http://differentdownload.com", + ExternalPackageRefCategory.OTHER, + "acmecorp/acmenator/4.1.3-alpha", + "LocationRef-acmeforge", + "This is the external ref for Acme", + ), + ], +) def test_external_package_ref_parser(download_location, category, locator, type, comment): graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) doc_namespace = "https://some.namespace" diff --git a/tests/spdx/parser/rdf/test_rdf_parser.py b/tests/spdx/parser/rdf/test_rdf_parser.py index 769e5c8e2..650346d4d 100644 --- a/tests/spdx/parser/rdf/test_rdf_parser.py +++ b/tests/spdx/parser/rdf/test_rdf_parser.py @@ -18,13 +18,14 @@ def test_rdf_parser_file_not_found(): with pytest.raises(FileNotFoundError, match="No such file or directory") as err: - wrong_file_path = os.path.join(os.path.dirname(__file__), 'hnjfkjsedhnflsiafg.json') + wrong_file_path = os.path.join(os.path.dirname(__file__), "hnjfkjsedhnflsiafg.json") rdf_parser.parse_from_file(wrong_file_path) def test_rdf_parser_with_2_3_example(): doc = rdf_parser.parse_from_file( - os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXRdfExample-v2.3.spdx.rdf.xml")) + os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXRdfExample-v2.3.spdx.rdf.xml") + ) assert type(doc) == Document assert len(doc.snippets) == 1 diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index a301a28d3..d04d50e6c 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -33,9 +33,10 @@ def test_parse_snippet(): assert snippet.byte_range == (1, 2) assert snippet.line_range == (3, 4) assert snippet.license_concluded == get_spdx_licensing().parse("MIT AND GPL-2.0") - TestCase().assertCountEqual(snippet.license_info_in_snippet, - [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), - SpdxNoAssertion()]) + TestCase().assertCountEqual( + snippet.license_info_in_snippet, + [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()], + ) assert snippet.license_comment == "snippetLicenseComment" assert snippet.copyright_text == "licenseCopyrightText" assert snippet.comment == "snippetComment" @@ -43,16 +44,23 @@ def test_parse_snippet(): assert snippet.attribution_texts == ["snippetAttributionText"] -@pytest.mark.parametrize("predicate_value_class_member", - [([(POINTER_NAMESPACE.startPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, - POINTER_NAMESPACE.offset), - (POINTER_NAMESPACE.endPointer, 2, POINTER_NAMESPACE.ByteOffsetPointer, - POINTER_NAMESPACE.offset)]), - ([(POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, - POINTER_NAMESPACE.lineNumber), - (POINTER_NAMESPACE.endPointer, 200, POINTER_NAMESPACE.LineCharPointer, - POINTER_NAMESPACE.lineNumber)]) - ]) +@pytest.mark.parametrize( + "predicate_value_class_member", + [ + ( + [ + (POINTER_NAMESPACE.startPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + (POINTER_NAMESPACE.endPointer, 2, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + ] + ), + ( + [ + (POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), + (POINTER_NAMESPACE.endPointer, 200, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), + ] + ), + ], +) def test_parse_ranges(predicate_value_class_member): graph = Graph() pointer_class = predicate_value_class_member[0][2] @@ -66,16 +74,23 @@ def test_parse_ranges(predicate_value_class_member): assert range_dict[pointer_class.fragment][1] == predicate_value_class_member[1][1] -@pytest.mark.parametrize("predicate_value_class_member", - [([(POINTER_NAMESPACE.startPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, - POINTER_NAMESPACE.lineNumber), - (POINTER_NAMESPACE.endPointer, 2, POINTER_NAMESPACE.ByteOffsetPointer, - POINTER_NAMESPACE.lineNumber)]), - ([(POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, - POINTER_NAMESPACE.offset), - (POINTER_NAMESPACE.endPointer, 200, POINTER_NAMESPACE.LineCharPointer, - POINTER_NAMESPACE.offset)]) - ]) +@pytest.mark.parametrize( + "predicate_value_class_member", + [ + ( + [ + (POINTER_NAMESPACE.startPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.lineNumber), + (POINTER_NAMESPACE.endPointer, 2, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.lineNumber), + ] + ), + ( + [ + (POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.offset), + (POINTER_NAMESPACE.endPointer, 200, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.offset), + ] + ), + ], +) def test_parse_ranges_wrong_pair_of_pointer_classes(predicate_value_class_member): graph = Graph() pointer_class = predicate_value_class_member[0][2] @@ -91,22 +106,42 @@ def test_parse_ranges_wrong_pair_of_pointer_classes(predicate_value_class_member @pytest.mark.parametrize( "predicate_value_class_member,expected_message", - [([(POINTER_NAMESPACE.endPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), - (POINTER_NAMESPACE.endPointer, 2, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset)], - "Couldn't find pointer of type startPointer."), - ([(POINTER_NAMESPACE.startPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset)], - "Couldn't find pointer of type endPointer."), - ([(POINTER_NAMESPACE.startPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), - (POINTER_NAMESPACE.endPointer, 2, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), - (POINTER_NAMESPACE.endPointer, 3, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset)], - "Multiple values for endPointer."), - ([(POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), - (POINTER_NAMESPACE.startPointer, 200, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber)], - "Multiple values for startPointer"), - ([(POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), - (POINTER_NAMESPACE.endPointer, 200, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset)], - f"Types of startPointer and endPointer don't match") - ]) + [ + ( + [ + (POINTER_NAMESPACE.endPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + (POINTER_NAMESPACE.endPointer, 2, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + ], + "Couldn't find pointer of type startPointer.", + ), + ( + [(POINTER_NAMESPACE.startPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset)], + "Couldn't find pointer of type endPointer.", + ), + ( + [ + (POINTER_NAMESPACE.startPointer, 1, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + (POINTER_NAMESPACE.endPointer, 2, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + (POINTER_NAMESPACE.endPointer, 3, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + ], + "Multiple values for endPointer.", + ), + ( + [ + (POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), + (POINTER_NAMESPACE.startPointer, 200, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), + ], + "Multiple values for startPointer", + ), + ( + [ + (POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), + (POINTER_NAMESPACE.endPointer, 200, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + ], + f"Types of startPointer and endPointer don't match", + ), + ], +) def test_parse_ranges_error(predicate_value_class_member, expected_message): graph = Graph() @@ -119,7 +154,7 @@ def test_parse_ranges_error(predicate_value_class_member, expected_message): def add_range_to_graph_helper(graph, predicate_value_class_member): start_end_pointer = BNode() graph.add((start_end_pointer, RDF.type, POINTER_NAMESPACE.StartEndPointer)) - for (predicate, value, pointer_class, pointer_member) in predicate_value_class_member: + for predicate, value, pointer_class, pointer_member in predicate_value_class_member: pointer_node = BNode() graph.add((pointer_node, RDF.type, pointer_class)) graph.add((start_end_pointer, predicate, pointer_node)) diff --git a/tests/spdx/parser/tagvalue/test_annotation_parser.py b/tests/spdx/parser/tagvalue/test_annotation_parser.py index 65e9fa1d1..8dd8cb2ec 100644 --- a/tests/spdx/parser/tagvalue/test_annotation_parser.py +++ b/tests/spdx/parser/tagvalue/test_annotation_parser.py @@ -20,13 +20,15 @@ def test_parse_annotation(): parser = Parser() - annotation_str = "\n".join([ - "Annotator: Person: Jane Doe()", - "AnnotationDate: 2010-01-29T18:30:22Z", - "AnnotationComment: Document level annotation", - "AnnotationType: OTHER", - "SPDXREF: SPDXRef-DOCUMENT" - ]) + annotation_str = "\n".join( + [ + "Annotator: Person: Jane Doe()", + "AnnotationDate: 2010-01-29T18:30:22Z", + "AnnotationComment: Document level annotation", + "AnnotationType: OTHER", + "SPDXREF: SPDXRef-DOCUMENT", + ] + ) document = parser.parse("\n".join([DOCUMENT_STR, annotation_str])) assert document is not None assert len(document.annotations) == 1 @@ -38,22 +40,36 @@ def test_parse_annotation(): assert annotation.spdx_id == "SPDXRef-DOCUMENT" -@pytest.mark.parametrize("annotation_str, expected_message", [ - ("Annotator: Person: Jane Doe()", r"__init__() missing 4 " - "required positional arguments: 'spdx_id', 'annotation_type', " - "'annotation_date', and 'annotation_comment'"), - ("Annotator: Person: Jane Doe()\nAnnotationType: SOURCE\nAnnotationDate: 201001-2912:23", - "Error while parsing Annotation: ['Invalid AnnotationType: SOURCE. Line: 2', " - "'Error while parsing AnnotationDate: Token did not match specified grammar " - "rule. Line: 3']"), - ("Annotator: Jane Doe()\nAnnotationDate: 201001-29T18:30:22Z\n" - "AnnotationComment: Document level annotation\nAnnotationType: OTHER\nSPDXREF: SPDXRef-DOCUMENT", - "Error while parsing Annotation: ['Error while parsing Annotator: Token did " - "not match specified grammar rule. Line: 1', 'Error while parsing " - "AnnotationDate: Token did not match specified grammar rule. Line: 2']"), - ("Annotator: Person: ()", "Error while parsing Annotation: [['No name for Person provided: Person: ().']]"), - ("AnnotationType: REVIEW", "Element Annotation is not the current element in scope, probably the " - "expected tag to start the element (Annotator) is missing. Line: 1")]) +@pytest.mark.parametrize( + "annotation_str, expected_message", + [ + ( + "Annotator: Person: Jane Doe()", + r"__init__() missing 4 " + "required positional arguments: 'spdx_id', 'annotation_type', " + "'annotation_date', and 'annotation_comment'", + ), + ( + "Annotator: Person: Jane Doe()\nAnnotationType: SOURCE\nAnnotationDate: 201001-2912:23", + "Error while parsing Annotation: ['Invalid AnnotationType: SOURCE. Line: 2', " + "'Error while parsing AnnotationDate: Token did not match specified grammar " + "rule. Line: 3']", + ), + ( + "Annotator: Jane Doe()\nAnnotationDate: 201001-29T18:30:22Z\n" + "AnnotationComment: Document level annotation\nAnnotationType: OTHER\nSPDXREF: SPDXRef-DOCUMENT", + "Error while parsing Annotation: ['Error while parsing Annotator: Token did " + "not match specified grammar rule. Line: 1', 'Error while parsing " + "AnnotationDate: Token did not match specified grammar rule. Line: 2']", + ), + ("Annotator: Person: ()", "Error while parsing Annotation: [['No name for Person provided: Person: ().']]"), + ( + "AnnotationType: REVIEW", + "Element Annotation is not the current element in scope, probably the " + "expected tag to start the element (Annotator) is missing. Line: 1", + ), + ], +) def test_parse_invalid_annotation(annotation_str, expected_message): parser = Parser() with pytest.raises(SPDXParsingError) as err: diff --git a/tests/spdx/parser/tagvalue/test_creation_info_parser.py b/tests/spdx/parser/tagvalue/test_creation_info_parser.py index 98971e24c..da98350b9 100644 --- a/tests/spdx/parser/tagvalue/test_creation_info_parser.py +++ b/tests/spdx/parser/tagvalue/test_creation_info_parser.py @@ -20,20 +20,22 @@ from spdx.parser.error import SPDXParsingError from spdx.parser.tagvalue.parser import Parser -DOCUMENT_STR = "\n".join([ - "SPDXVersion: SPDX-2.3", - "DataLicense: CC0-1.0", - "DocumentName: Sample_Document-V2.3", - "SPDXID: SPDXRef-DOCUMENT", - "DocumentComment: Sample Comment", - "DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", - "ExternalDocumentRef: DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", - "Creator: Person: Bob (bob@example.com)", - "Creator: Organization: Acme.", - "Created: 2010-02-03T00:00:00Z", - "CreatorComment: Sample Comment \nwith multiple \nlines.", - "LicenseListVersion: 3.17" -]) +DOCUMENT_STR = "\n".join( + [ + "SPDXVersion: SPDX-2.3", + "DataLicense: CC0-1.0", + "DocumentName: Sample_Document-V2.3", + "SPDXID: SPDXRef-DOCUMENT", + "DocumentComment: Sample Comment", + "DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", + "ExternalDocumentRef: DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "Creator: Person: Bob (bob@example.com)", + "Creator: Organization: Acme.", + "Created: 2010-02-03T00:00:00Z", + "CreatorComment: Sample Comment \nwith multiple \nlines.", + "LicenseListVersion: 3.17", + ] +) def test_parse_creation_info(): @@ -47,44 +49,79 @@ def test_parse_creation_info(): assert creation_info.name == "Sample_Document-V2.3" assert creation_info.spdx_id == "SPDXRef-DOCUMENT" assert creation_info.document_comment == "Sample Comment" - assert creation_info.document_namespace == "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301" - TestCase().assertCountEqual(creation_info.creators, - [Actor(ActorType.PERSON, "Bob", "bob@example.com"), - Actor(ActorType.ORGANIZATION, "Acme.")]) + assert ( + creation_info.document_namespace + == "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301" + ) + TestCase().assertCountEqual( + creation_info.creators, + [Actor(ActorType.PERSON, "Bob", "bob@example.com"), Actor(ActorType.ORGANIZATION, "Acme.")], + ) assert creation_info.creator_comment == "Sample Comment \nwith multiple \nlines." assert creation_info.created == datetime(2010, 2, 3) assert creation_info.license_list_version == Version(3, 17) - assert creation_info.external_document_refs == [ExternalDocumentRef("DocumentRef-spdx-tool-1.2", - "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301", - Checksum(ChecksumAlgorithm.SHA1, - "d6a770ba38583ed4bb4525bd96e50461655d2759"))] + assert creation_info.external_document_refs == [ + ExternalDocumentRef( + "DocumentRef-spdx-tool-1.2", + "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301", + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2759"), + ) + ] -@pytest.mark.parametrize("document_str, expected_message", - ([("\n".join( - ["SPDXVersion: SPDX-2.3", "DataLicense: CC0-1.0", "DocumentName: Sample_Document-V2.3", - "SPDXID: SPDXRef-DOCUMENT", "DocumentComment: Sample Comment", - "DocumentNamespace: Sample Comment", - "ExternalDocumentRef: DocumentRef-spdx-tool-1.2:htp://spdx.org:SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", - "Creator: Person Bob (bob@example.com)", "Creator: Organization: Acme [email]", - "Created: 2010-02-03T00:00:0Z", "CreatorComment: Sample Comment", - "LicenseListVersion: 7"]), - ("Error while parsing CreationInfo: ['Error while parsing DocumentNamespace: " - 'Token did not match specified grammar rule. Line: 6\', "Error while parsing ' - "ExternalDocumentRef: Couldn't split the first part of the value into " - 'document_ref_id and document_uri. Line: 7", \'Error while parsing Creator: ' - "Token did not match specified grammar rule. Line: 8', 'Error while parsing " - "Created: Token did not match specified grammar rule. Line: 10', '7 is not a " - "valid version string']")), - ("\n".join( - ["SPDXVersion: SPDX-2.3", "DataLicense: CC0-1.0", "DocumentName: Sample_Document-V2.3", - "SPDXID: SPDXRef-DOCUMENT"]), - r"__init__() missing 3 required positional arguments: 'document_namespace', 'creators', and 'created'"), - ("LicenseListVersion: 3.5\nLicenseListVersion: 3.7", - "Error while parsing CreationInfo: ['Multiple values for LicenseListVersion found. Line: 2']"), - ("ExternalDocumentRef: Document_ref document_uri SHA1: afded", - 'Error while parsing CreationInfo: ["Error while parsing ExternalDocumentRef: Couldn\'t match Checksum. Line: 1"]' - )])) +@pytest.mark.parametrize( + "document_str, expected_message", + ( + [ + ( + "\n".join( + [ + "SPDXVersion: SPDX-2.3", + "DataLicense: CC0-1.0", + "DocumentName: Sample_Document-V2.3", + "SPDXID: SPDXRef-DOCUMENT", + "DocumentComment: Sample Comment", + "DocumentNamespace: Sample Comment", + "ExternalDocumentRef: DocumentRef-spdx-tool-1.2:htp://spdx.org:SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "Creator: Person Bob (bob@example.com)", + "Creator: Organization: Acme [email]", + "Created: 2010-02-03T00:00:0Z", + "CreatorComment: Sample Comment", + "LicenseListVersion: 7", + ] + ), + ( + "Error while parsing CreationInfo: ['Error while parsing DocumentNamespace: " + "Token did not match specified grammar rule. Line: 6', \"Error while parsing " + "ExternalDocumentRef: Couldn't split the first part of the value into " + "document_ref_id and document_uri. Line: 7\", 'Error while parsing Creator: " + "Token did not match specified grammar rule. Line: 8', 'Error while parsing " + "Created: Token did not match specified grammar rule. Line: 10', '7 is not a " + "valid version string']" + ), + ), + ( + "\n".join( + [ + "SPDXVersion: SPDX-2.3", + "DataLicense: CC0-1.0", + "DocumentName: Sample_Document-V2.3", + "SPDXID: SPDXRef-DOCUMENT", + ] + ), + r"__init__() missing 3 required positional arguments: 'document_namespace', 'creators', and 'created'", + ), + ( + "LicenseListVersion: 3.5\nLicenseListVersion: 3.7", + "Error while parsing CreationInfo: ['Multiple values for LicenseListVersion found. Line: 2']", + ), + ( + "ExternalDocumentRef: Document_ref document_uri SHA1: afded", + 'Error while parsing CreationInfo: ["Error while parsing ExternalDocumentRef: Couldn\'t match Checksum. Line: 1"]', + ), + ] + ), +) def test_parse_invalid_creation_info(document_str, expected_message): parser = Parser() with pytest.raises(SPDXParsingError) as err: diff --git a/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py b/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py index f8e27ace1..4107cc78b 100644 --- a/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py @@ -19,48 +19,60 @@ def test_parse_extracted_licensing_info(): parser = Parser() - extracted_licensing_info_str = "\n".join([ - "LicenseID: LicenseRef-Beerware-4.2", - "ExtractedText: \"THE BEER-WARE LICENSE\" (Revision 42): phk@FreeBSD.ORG wrote this file. As long as you " - "retain this notice you can do whatever you want with this stuff. If we meet some day, and you think this " - "stuff is worth it, you can buy me a beer in return Poul-Henning Kamp" - "LicenseName: Beer-Ware License (Version 42)", - "LicenseCrossReference: http://people.freebsd.org/~phk/", - "LicenseCrossReference: http://another.cross.reference/", - "LicenseComment: The beerware license has a couple of other standard variants." - ]) + extracted_licensing_info_str = "\n".join( + [ + "LicenseID: LicenseRef-Beerware-4.2", + 'ExtractedText: "THE BEER-WARE LICENSE" (Revision 42): phk@FreeBSD.ORG wrote this file. As long as you ' + "retain this notice you can do whatever you want with this stuff. If we meet some day, and you think this " + "stuff is worth it, you can buy me a beer in return Poul-Henning Kamp" + "LicenseName: Beer-Ware License (Version 42)", + "LicenseCrossReference: http://people.freebsd.org/~phk/", + "LicenseCrossReference: http://another.cross.reference/", + "LicenseComment: The beerware license has a couple of other standard variants.", + ] + ) document = parser.parse("\n".join([DOCUMENT_STR, extracted_licensing_info_str])) assert document is not None assert len(document.extracted_licensing_info) == 1 extracted_licensing_info = document.extracted_licensing_info[0] assert extracted_licensing_info.license_id == "LicenseRef-Beerware-4.2" - assert extracted_licensing_info.extracted_text == "\"THE BEER-WARE LICENSE\" (Revision 42): phk@FreeBSD.ORG wrote this file. " \ - "As long as you retain this notice you can do whatever you want with this stuff. " \ - "If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp" + assert ( + extracted_licensing_info.extracted_text + == '"THE BEER-WARE LICENSE" (Revision 42): phk@FreeBSD.ORG wrote this file. ' + "As long as you retain this notice you can do whatever you want with this stuff. " + "If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp" + ) assert extracted_licensing_info.license_name == "Beer-Ware License (Version 42)" - TestCase().assertCountEqual(extracted_licensing_info.cross_references, - ["http://people.freebsd.org/~phk/", "http://another.cross.reference/"]) + TestCase().assertCountEqual( + extracted_licensing_info.cross_references, + ["http://people.freebsd.org/~phk/", "http://another.cross.reference/"], + ) assert extracted_licensing_info.comment == "The beerware license has a couple of other standard variants." def test_parse_invalid_extracted_licensing_info(): parser = Parser() - extracted_licensing_info_str = "\n".join([ - "ExtractedText: \"THE BEER-WARE LICENSE\" (Revision 42): phk@FreeBSD.ORG wrote this file. " - "As long as you retain this notice you can do whatever you want with this stuff. If we meet some day, and you " - "think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", - "LicenseName: Beer-Ware License (Version 42)", - "LicenseCrossReference: http://people.freebsd.org/~phk/", - "LicenseComment: The beerware license has a couple of other standard variants."]) + extracted_licensing_info_str = "\n".join( + [ + 'ExtractedText: "THE BEER-WARE LICENSE" (Revision 42): phk@FreeBSD.ORG wrote this file. ' + "As long as you retain this notice you can do whatever you want with this stuff. If we meet some day, and you " + "think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "LicenseName: Beer-Ware License (Version 42)", + "LicenseCrossReference: http://people.freebsd.org/~phk/", + "LicenseComment: The beerware license has a couple of other standard variants.", + ] + ) with pytest.raises(SPDXParsingError) as err: parser.parse(extracted_licensing_info_str) - assert err.value.get_messages() == ["Element ExtractedLicensingInfo is not the current element in scope, probably " - "the expected tag to start the element (LicenseID) is missing. Line: 1", - "Element ExtractedLicensingInfo is not the current element in scope, probably " - "the expected tag to start the element (LicenseID) is missing. Line: 2", - "Element ExtractedLicensingInfo is not the current element in scope, probably " - "the expected tag to start the element (LicenseID) is missing. Line: 3", - "Element ExtractedLicensingInfo is not the current element in scope, probably " - "the expected tag to start the element (LicenseID) is missing. Line: 4"] + assert err.value.get_messages() == [ + "Element ExtractedLicensingInfo is not the current element in scope, probably " + "the expected tag to start the element (LicenseID) is missing. Line: 1", + "Element ExtractedLicensingInfo is not the current element in scope, probably " + "the expected tag to start the element (LicenseID) is missing. Line: 2", + "Element ExtractedLicensingInfo is not the current element in scope, probably " + "the expected tag to start the element (LicenseID) is missing. Line: 3", + "Element ExtractedLicensingInfo is not the current element in scope, probably " + "the expected tag to start the element (LicenseID) is missing. Line: 4", + ] diff --git a/tests/spdx/parser/tagvalue/test_file_parser.py b/tests/spdx/parser/tagvalue/test_file_parser.py index 29399020f..95cb8e322 100644 --- a/tests/spdx/parser/tagvalue/test_file_parser.py +++ b/tests/spdx/parser/tagvalue/test_file_parser.py @@ -20,19 +20,21 @@ def test_parse_file(): parser = Parser() - file_str = "\n".join([ - "FileName: testfile.java", - "SPDXID: SPDXRef-File", - "FileType: SOURCE", - "FileType: TEXT", - "FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "LicenseConcluded: Apache-2.0", - "LicenseInfoInFile: Apache-2.0", - "LicenseInfoInFile: NOASSERTION", - "FileCopyrightText: Copyright 2014 Acme Inc.", - "FileComment: Very long file", - "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts." - ]) + file_str = "\n".join( + [ + "FileName: testfile.java", + "SPDXID: SPDXRef-File", + "FileType: SOURCE", + "FileType: TEXT", + "FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + "LicenseConcluded: Apache-2.0", + "LicenseInfoInFile: Apache-2.0", + "LicenseInfoInFile: NOASSERTION", + "FileCopyrightText: Copyright 2014 Acme Inc.", + "FileComment: Very long file", + "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts.", + ] + ) document = parser.parse("\n".join([DOCUMENT_STR, file_str])) assert document is not None assert len(document.files) == 1 @@ -42,30 +44,33 @@ def test_parse_file(): assert spdx_file.file_types == [FileType.SOURCE, FileType.TEXT] assert spdx_file.comment == "Very long file" assert spdx_file.attribution_texts == [ - "Acknowledgements that might be required to be communicated in some contexts."] - assert spdx_file.license_info_in_file == [get_spdx_licensing().parse("Apache-2.0"), - SpdxNoAssertion()] + "Acknowledgements that might be required to be communicated in some contexts." + ] + assert spdx_file.license_info_in_file == [get_spdx_licensing().parse("Apache-2.0"), SpdxNoAssertion()] assert spdx_file.license_concluded == get_spdx_licensing().parse("Apache-2.0") def test_parse_invalid_file(): parser = Parser() - file_str = "\n".join([ - "FileName: testfile.java", - "SPDXID: SPDXRef-File", - "FileType: SOUCE", - "FileType: TEXT", - "FileChecksum: SHA3: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "LicenseConcluded: Apache-2.0", - "LicenseInfoInFile: Apache-2.0", - "FileCopyrightText: Copyright 2014 Acme Inc.", - "FileComment: Very long file", - "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts." - ]) + file_str = "\n".join( + [ + "FileName: testfile.java", + "SPDXID: SPDXRef-File", + "FileType: SOUCE", + "FileType: TEXT", + "FileChecksum: SHA3: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + "LicenseConcluded: Apache-2.0", + "LicenseInfoInFile: Apache-2.0", + "FileCopyrightText: Copyright 2014 Acme Inc.", + "FileComment: Very long file", + "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts.", + ] + ) with pytest.raises(SPDXParsingError) as err: parser.parse(file_str) assert err.value.get_messages() == [ "Error while parsing File: ['Invalid FileType: SOUCE. Line 3', 'Error while " - "parsing FileChecksum: Token did not match specified grammar rule. Line: 5']"] + "parsing FileChecksum: Token did not match specified grammar rule. Line: 5']" + ] diff --git a/tests/spdx/parser/tagvalue/test_helper_methods.py b/tests/spdx/parser/tagvalue/test_helper_methods.py index 75e7f0742..6c0e7eb7a 100644 --- a/tests/spdx/parser/tagvalue/test_helper_methods.py +++ b/tests/spdx/parser/tagvalue/test_helper_methods.py @@ -14,58 +14,80 @@ from spdx.parser.tagvalue.helper_methods import parse_checksum -@pytest.mark.parametrize("checksum_str, algorithm, value", - [("SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", - ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2759"), - ("SHA224: 9c9f4e27d957a123cc32d86afe33ae53b1184192cccb23b0f257f588", - ChecksumAlgorithm.SHA224, - "9c9f4e27d957a123cc32d86afe33ae53b1184192cccb23b0f257f588"), - ("SHA256: fbea580d286bbbbb41314430d58ba887716a74d7134119c5307cdc9f0c7a4299", - ChecksumAlgorithm.SHA256, - "fbea580d286bbbbb41314430d58ba887716a74d7134119c5307cdc9f0c7a4299"), - ( - "SHA384: 73b4ad9a34e5f76cb2525ea6bb8b1dcf9ba79426b3295bd18bc6d148cba4fcc2ca3cf2630fd481b47caaac9127103933", - ChecksumAlgorithm.SHA384, - "73b4ad9a34e5f76cb2525ea6bb8b1dcf9ba79426b3295bd18bc6d148cba4fcc2ca3cf2630fd481b47caaac9127103933"), - ( - "SHA512: c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f15af43e7cb5547f1a464053", - ChecksumAlgorithm.SHA512, - "c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f15af43e7cb5547f1a464053"), - ("SHA3-256: 1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce", - ChecksumAlgorithm.SHA3_256, - "1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce"), ( - "SHA3-384: dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166", - ChecksumAlgorithm.SHA3_384, - "dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166"), - ( - "SHA3-512: 906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d111310266a5d46e2bc1ffbb36", - ChecksumAlgorithm.SHA3_512, - "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d111310266a5d46e2bc1ffbb36"), - ("BLAKE2b-256: a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7", - ChecksumAlgorithm.BLAKE2B_256, - "a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7"), ( - "BLAKE2B-384: 902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2", - ChecksumAlgorithm.BLAKE2B_384, - "902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2"), - ( - "BLAKE2B-512: 72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8c4af74dce531ca8ebd8824c", - ChecksumAlgorithm.BLAKE2B_512, - "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8c4af74dce531ca8ebd8824c"), - ( - "BLAKE3: a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed", - ChecksumAlgorithm.BLAKE3, - "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed"), - ("MD2: af1eec2a1b18886c3f3cc244349d91d8", ChecksumAlgorithm.MD2, - "af1eec2a1b18886c3f3cc244349d91d8"), - ("MD4: d4c41ce30a517d6ce9d79c8c17bb4b66", ChecksumAlgorithm.MD4, - "d4c41ce30a517d6ce9d79c8c17bb4b66"), - ("MD5: 0d7f61beb7018b3924c6b8f96549fa39", ChecksumAlgorithm.MD5, - "0d7f61beb7018b3924c6b8f96549fa39"), - ( - "MD6: af1eec2a1b18886c3f3cc244349d91d8d4c41ce30a517d6ce9d79c8c17bb4b660d7f61beb7018b3924c6b8f96549fa39", - ChecksumAlgorithm.MD6, - "af1eec2a1b18886c3f3cc244349d91d8d4c41ce30a517d6ce9d79c8c17bb4b660d7f61beb7018b3924c6b8f96549fa39"), - ("ADLER32: 02ec0130", ChecksumAlgorithm.ADLER32, "02ec0130")]) +@pytest.mark.parametrize( + "checksum_str, algorithm, value", + [ + ( + "SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + ChecksumAlgorithm.SHA1, + "d6a770ba38583ed4bb4525bd96e50461655d2759", + ), + ( + "SHA224: 9c9f4e27d957a123cc32d86afe33ae53b1184192cccb23b0f257f588", + ChecksumAlgorithm.SHA224, + "9c9f4e27d957a123cc32d86afe33ae53b1184192cccb23b0f257f588", + ), + ( + "SHA256: fbea580d286bbbbb41314430d58ba887716a74d7134119c5307cdc9f0c7a4299", + ChecksumAlgorithm.SHA256, + "fbea580d286bbbbb41314430d58ba887716a74d7134119c5307cdc9f0c7a4299", + ), + ( + "SHA384: 73b4ad9a34e5f76cb2525ea6bb8b1dcf9ba79426b3295bd18bc6d148cba4fcc2ca3cf2630fd481b47caaac9127103933", + ChecksumAlgorithm.SHA384, + "73b4ad9a34e5f76cb2525ea6bb8b1dcf9ba79426b3295bd18bc6d148cba4fcc2ca3cf2630fd481b47caaac9127103933", + ), + ( + "SHA512: c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f15af43e7cb5547f1a464053", + ChecksumAlgorithm.SHA512, + "c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f15af43e7cb5547f1a464053", + ), + ( + "SHA3-256: 1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce", + ChecksumAlgorithm.SHA3_256, + "1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce", + ), + ( + "SHA3-384: dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166", + ChecksumAlgorithm.SHA3_384, + "dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166", + ), + ( + "SHA3-512: 906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d111310266a5d46e2bc1ffbb36", + ChecksumAlgorithm.SHA3_512, + "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d111310266a5d46e2bc1ffbb36", + ), + ( + "BLAKE2b-256: a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7", + ChecksumAlgorithm.BLAKE2B_256, + "a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7", + ), + ( + "BLAKE2B-384: 902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2", + ChecksumAlgorithm.BLAKE2B_384, + "902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2", + ), + ( + "BLAKE2B-512: 72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8c4af74dce531ca8ebd8824c", + ChecksumAlgorithm.BLAKE2B_512, + "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8c4af74dce531ca8ebd8824c", + ), + ( + "BLAKE3: a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed", + ChecksumAlgorithm.BLAKE3, + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed", + ), + ("MD2: af1eec2a1b18886c3f3cc244349d91d8", ChecksumAlgorithm.MD2, "af1eec2a1b18886c3f3cc244349d91d8"), + ("MD4: d4c41ce30a517d6ce9d79c8c17bb4b66", ChecksumAlgorithm.MD4, "d4c41ce30a517d6ce9d79c8c17bb4b66"), + ("MD5: 0d7f61beb7018b3924c6b8f96549fa39", ChecksumAlgorithm.MD5, "0d7f61beb7018b3924c6b8f96549fa39"), + ( + "MD6: af1eec2a1b18886c3f3cc244349d91d8d4c41ce30a517d6ce9d79c8c17bb4b660d7f61beb7018b3924c6b8f96549fa39", + ChecksumAlgorithm.MD6, + "af1eec2a1b18886c3f3cc244349d91d8d4c41ce30a517d6ce9d79c8c17bb4b660d7f61beb7018b3924c6b8f96549fa39", + ), + ("ADLER32: 02ec0130", ChecksumAlgorithm.ADLER32, "02ec0130"), + ], +) def test_parse_checksum(checksum_str, algorithm, value): checksum = parse_checksum(checksum_str) diff --git a/tests/spdx/parser/tagvalue/test_package_parser.py b/tests/spdx/parser/tagvalue/test_package_parser.py index 39d6eeef3..f5c75d751 100644 --- a/tests/spdx/parser/tagvalue/test_package_parser.py +++ b/tests/spdx/parser/tagvalue/test_package_parser.py @@ -23,36 +23,38 @@ def test_parse_package(): parser = Parser() - package_str = "\n".join([ - "PackageName: Test", - "SPDXID: SPDXRef-Package", - "PackageVersion: 1:22.36.1-8+deb11u1", - "PackageDownloadLocation: http://example.com/test", - "FilesAnalyzed: True", - "PackageSummary: Test package", - "PackageSourceInfo: Version 1.0 of test", - "PackageFileName: test-1.0.zip", - "PackageSupplier: Organization:ACME", - "PackageOriginator: Organization:ACME", - "PackageChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "PackageVerificationCode: 4e3211c67a2d28fced849ee1bb76e7391b93feba (something.rdf, something.txt)", - "PackageDescription: A package.", - "PackageComment: Comment on the package.", - "PackageCopyrightText: Copyright 2014 Acme Inc.", - "PackageLicenseDeclared: Apache-2.0", - "PackageLicenseConcluded: (LicenseRef-2.0 and Apache-2.0)", - "PackageLicenseInfoFromFiles: Apache-1.0", - "PackageLicenseInfoFromFiles: Apache-2.0", - "PackageLicenseInfoFromFiles: NONE", - "PackageLicenseComments: License Comments", - "ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:", - "ExternalRefComment: Some comment about the package.", - "ExternalRef: OTHER LocationRef-acmeforge acmecorp/acmenator/4.1.3-alpha", - "PrimaryPackagePurpose: OPERATING-SYSTEM", - "BuiltDate: 2020-01-01T12:00:00Z", - "ReleaseDate: 2021-01-01T12:00:00Z", - "ValidUntilDate: 2022-01-01T12:00:00Z" - ]) + package_str = "\n".join( + [ + "PackageName: Test", + "SPDXID: SPDXRef-Package", + "PackageVersion: 1:22.36.1-8+deb11u1", + "PackageDownloadLocation: http://example.com/test", + "FilesAnalyzed: True", + "PackageSummary: Test package", + "PackageSourceInfo: Version 1.0 of test", + "PackageFileName: test-1.0.zip", + "PackageSupplier: Organization:ACME", + "PackageOriginator: Organization:ACME", + "PackageChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + "PackageVerificationCode: 4e3211c67a2d28fced849ee1bb76e7391b93feba (something.rdf, something.txt)", + "PackageDescription: A package.", + "PackageComment: Comment on the package.", + "PackageCopyrightText: Copyright 2014 Acme Inc.", + "PackageLicenseDeclared: Apache-2.0", + "PackageLicenseConcluded: (LicenseRef-2.0 and Apache-2.0)", + "PackageLicenseInfoFromFiles: Apache-1.0", + "PackageLicenseInfoFromFiles: Apache-2.0", + "PackageLicenseInfoFromFiles: NONE", + "PackageLicenseComments: License Comments", + "ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:", + "ExternalRefComment: Some comment about the package.", + "ExternalRef: OTHER LocationRef-acmeforge acmecorp/acmenator/4.1.3-alpha", + "PrimaryPackagePurpose: OPERATING-SYSTEM", + "BuiltDate: 2020-01-01T12:00:00Z", + "ReleaseDate: 2021-01-01T12:00:00Z", + "ValidUntilDate: 2022-01-01T12:00:00Z", + ] + ) document = parser.parse("\n".join([DOCUMENT_STR, package_str])) assert document is not None package = document.packages[0] @@ -60,50 +62,76 @@ def test_parse_package(): assert package.spdx_id == "SPDXRef-Package" assert package.version == "1:22.36.1-8+deb11u1" assert len(package.license_info_from_files) == 3 - TestCase().assertCountEqual(package.license_info_from_files, [get_spdx_licensing().parse("Apache-1.0"), - get_spdx_licensing().parse("Apache-2.0"), - SpdxNone()]) + TestCase().assertCountEqual( + package.license_info_from_files, + [get_spdx_licensing().parse("Apache-1.0"), get_spdx_licensing().parse("Apache-2.0"), SpdxNone()], + ) assert package.license_concluded == get_spdx_licensing().parse("LicenseRef-2.0 AND Apache-2.0") assert package.files_analyzed is True assert package.comment == "Comment on the package." assert len(package.external_references) == 2 - TestCase().assertCountEqual(package.external_references, - [ExternalPackageRef(ExternalPackageRefCategory.SECURITY, "cpe23Type", - "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:", - "Some comment about the package."), - ExternalPackageRef(ExternalPackageRefCategory.OTHER, "LocationRef-acmeforge", - "acmecorp/acmenator/4.1.3-alpha")]) + TestCase().assertCountEqual( + package.external_references, + [ + ExternalPackageRef( + ExternalPackageRefCategory.SECURITY, + "cpe23Type", + "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:", + "Some comment about the package.", + ), + ExternalPackageRef( + ExternalPackageRefCategory.OTHER, "LocationRef-acmeforge", "acmecorp/acmenator/4.1.3-alpha" + ), + ], + ) assert package.primary_package_purpose == PackagePurpose.OPERATING_SYSTEM assert package.built_date == datetime(2020, 1, 1, 12) assert package.release_date == datetime(2021, 1, 1, 12) assert package.valid_until_date == datetime(2022, 1, 1, 12) -@pytest.mark.parametrize("package_str, expected_message", - [("PackageDownloadLocation: SPDXRef-Package", - "Element Package is not the current element in scope, probably the expected " - "tag to start the element (PackageName) is missing. Line: 1"), - ("PackageName: TestPackage", - r"__init__() missing 2 required positional arguments: 'spdx_id' and 'download_location'"), - ("PackageName: TestPackage\nPackageCopyrightText:This is a copyright\n" - "PackageCopyrightText:MultipleCopyright", - "Error while parsing Package: ['Multiple values for PackageCopyrightText " - "found. Line: 3']"), - ("PackageName: TestPackage\nExternalRef: reference locator", - ('Error while parsing Package: ["Couldn\'t split PackageExternalRef in category, ' - 'reference_type and locator. Line: 2"]')), - ("PackageName: TestPackage\nExternalRef: category reference locator", - "Error while parsing Package: ['Invalid ExternalPackageRefCategory: " - "category. Line: 2']"), - ("SPDXID:SPDXRef-DOCUMENT\nPackageName: TestPackage\nSPDXID:SPDXRef-Package\n" - "PackageDownloadLocation: download.com\nPackageVerificationCode: category reference locator", - "Error while parsing Package: ['Error while parsing PackageVerificationCode: " - "Value did not match expected format. Line: 5']"), - ("PackageName: TestPackage\nBuiltDate: 2012\nValidUntilDate:202-11-02T00:00", - "Error while parsing Package: ['Error while parsing BuiltDate: Token did not " - "match specified grammar rule. Line: 2', 'Error while parsing " - "ValidUntilDate: Token did not match specified grammar rule. Line: 3']") - ]) +@pytest.mark.parametrize( + "package_str, expected_message", + [ + ( + "PackageDownloadLocation: SPDXRef-Package", + "Element Package is not the current element in scope, probably the expected " + "tag to start the element (PackageName) is missing. Line: 1", + ), + ( + "PackageName: TestPackage", + r"__init__() missing 2 required positional arguments: 'spdx_id' and 'download_location'", + ), + ( + "PackageName: TestPackage\nPackageCopyrightText:This is a copyright\n" + "PackageCopyrightText:MultipleCopyright", + "Error while parsing Package: ['Multiple values for PackageCopyrightText " "found. Line: 3']", + ), + ( + "PackageName: TestPackage\nExternalRef: reference locator", + ( + "Error while parsing Package: [\"Couldn't split PackageExternalRef in category, " + 'reference_type and locator. Line: 2"]' + ), + ), + ( + "PackageName: TestPackage\nExternalRef: category reference locator", + "Error while parsing Package: ['Invalid ExternalPackageRefCategory: " "category. Line: 2']", + ), + ( + "SPDXID:SPDXRef-DOCUMENT\nPackageName: TestPackage\nSPDXID:SPDXRef-Package\n" + "PackageDownloadLocation: download.com\nPackageVerificationCode: category reference locator", + "Error while parsing Package: ['Error while parsing PackageVerificationCode: " + "Value did not match expected format. Line: 5']", + ), + ( + "PackageName: TestPackage\nBuiltDate: 2012\nValidUntilDate:202-11-02T00:00", + "Error while parsing Package: ['Error while parsing BuiltDate: Token did not " + "match specified grammar rule. Line: 2', 'Error while parsing " + "ValidUntilDate: Token did not match specified grammar rule. Line: 3']", + ), + ], +) def test_parse_invalid_package(package_str, expected_message): parser = Parser() diff --git a/tests/spdx/parser/tagvalue/test_relationship_parser.py b/tests/spdx/parser/tagvalue/test_relationship_parser.py index 4c2d7b9a3..fc74b05b7 100644 --- a/tests/spdx/parser/tagvalue/test_relationship_parser.py +++ b/tests/spdx/parser/tagvalue/test_relationship_parser.py @@ -18,20 +18,31 @@ from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR -@pytest.mark.parametrize("relationship_str, expected_relationship", - [("\n".join(["Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-File", - "RelationshipComment: This is a comment."]), - Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, - "SPDXRef-File", "This is a comment.")), - ("Relationship: SPDXRef-DOCUMENT PATCH_FOR NOASSERTION", - Relationship("SPDXRef-DOCUMENT", RelationshipType.PATCH_FOR, - SpdxNoAssertion())), - ("Relationship: SPDXRef-CarolCompression DEPENDS_ON NONE", - Relationship("SPDXRef-CarolCompression", RelationshipType.DEPENDS_ON, SpdxNone())), - ("Relationship: DocumentRef-ExternalDocument:SPDXRef-Test DEPENDS_ON DocumentRef:AnotherRef", - Relationship("DocumentRef-ExternalDocument:SPDXRef-Test", RelationshipType.DEPENDS_ON, - "DocumentRef:AnotherRef")) - ]) +@pytest.mark.parametrize( + "relationship_str, expected_relationship", + [ + ( + "\n".join( + ["Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-File", "RelationshipComment: This is a comment."] + ), + Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-File", "This is a comment."), + ), + ( + "Relationship: SPDXRef-DOCUMENT PATCH_FOR NOASSERTION", + Relationship("SPDXRef-DOCUMENT", RelationshipType.PATCH_FOR, SpdxNoAssertion()), + ), + ( + "Relationship: SPDXRef-CarolCompression DEPENDS_ON NONE", + Relationship("SPDXRef-CarolCompression", RelationshipType.DEPENDS_ON, SpdxNone()), + ), + ( + "Relationship: DocumentRef-ExternalDocument:SPDXRef-Test DEPENDS_ON DocumentRef:AnotherRef", + Relationship( + "DocumentRef-ExternalDocument:SPDXRef-Test", RelationshipType.DEPENDS_ON, "DocumentRef:AnotherRef" + ), + ), + ], +) def test_parse_relationship(relationship_str, expected_relationship): parser = Parser() document = parser.parse("\n".join([DOCUMENT_STR, relationship_str])) @@ -41,12 +52,22 @@ def test_parse_relationship(relationship_str, expected_relationship): assert relationship == expected_relationship -@pytest.mark.parametrize("relationship_str, expected_message", - [("Relationship: spdx_id DESCRIBES", - ['Error while parsing Relationship: ["Relationship couldn\'t be split in ' - 'spdx_element_id, relationship_type and related_spdx_element. Line: 1"]']), - ("Relationship: spdx_id IS spdx_id", - ["Error while parsing Relationship: ['Invalid RelationshipType IS. Line: 1']"])]) +@pytest.mark.parametrize( + "relationship_str, expected_message", + [ + ( + "Relationship: spdx_id DESCRIBES", + [ + "Error while parsing Relationship: [\"Relationship couldn't be split in " + 'spdx_element_id, relationship_type and related_spdx_element. Line: 1"]' + ], + ), + ( + "Relationship: spdx_id IS spdx_id", + ["Error while parsing Relationship: ['Invalid RelationshipType IS. Line: 1']"], + ), + ], +) def test_parse_invalid_relationship(relationship_str, expected_message): parser = Parser() with pytest.raises(SPDXParsingError) as err: diff --git a/tests/spdx/parser/tagvalue/test_snippet_parser.py b/tests/spdx/parser/tagvalue/test_snippet_parser.py index 94c54c39f..4e563a581 100644 --- a/tests/spdx/parser/tagvalue/test_snippet_parser.py +++ b/tests/spdx/parser/tagvalue/test_snippet_parser.py @@ -21,20 +21,22 @@ def test_parse_snippet(): parser = Parser() - snippet_str = "\n".join([ - "SnippetSPDXID: SPDXRef-Snippet", - "SnippetLicenseComments: Some lic comment.", - "SnippetCopyrightText: Copyright 2008-2010 John Smith ", - "SnippetComment: Some snippet comment.", - "SnippetName: from linux kernel", - "SnippetFromFileSPDXID: SPDXRef-DoapSource", - "SnippetLicenseConcluded: Apache-2.0", - "LicenseInfoInSnippet: NOASSERTION", - "SnippetByteRange: 310:420", - "SnippetLineRange: 5:23", - "SnippetAttributionText: This is a text\nthat spans multiple lines.", - "SnippetAttributionText: This text spans one line but has trailing and leading whitespaces. " - ]) + snippet_str = "\n".join( + [ + "SnippetSPDXID: SPDXRef-Snippet", + "SnippetLicenseComments: Some lic comment.", + "SnippetCopyrightText: Copyright 2008-2010 John Smith ", + "SnippetComment: Some snippet comment.", + "SnippetName: from linux kernel", + "SnippetFromFileSPDXID: SPDXRef-DoapSource", + "SnippetLicenseConcluded: Apache-2.0", + "LicenseInfoInSnippet: NOASSERTION", + "SnippetByteRange: 310:420", + "SnippetLineRange: 5:23", + "SnippetAttributionText: This is a text\nthat spans multiple lines.", + "SnippetAttributionText: This text spans one line but has trailing and leading whitespaces. ", + ] + ) document = parser.parse("\n".join([DOCUMENT_STR, snippet_str])) assert document is not None @@ -53,22 +55,37 @@ def test_parse_snippet(): assert snippet.line_range[0] == 5 assert snippet.line_range[1] == 23 TestCase().assertCountEqual( - snippet.attribution_texts, ["This is a text\nthat spans multiple lines.", - "This text spans one line but has trailing and leading whitespaces."]) + snippet.attribution_texts, + [ + "This is a text\nthat spans multiple lines.", + "This text spans one line but has trailing and leading whitespaces.", + ], + ) -@pytest.mark.parametrize("snippet_str, expected_message", [ - ("SnippetName: TestSnippet", "Element Snippet is not the current element in scope, probably the expected " - "tag to start the element (SnippetSPDXID) is missing. Line: 1"), - ("SnippetSPDXID: SPDXDRef-Snippet\nSnippetByteRange: 1,4", - 'Error while parsing Snippet: ["Value for SnippetByteRange doesn\'t match ' - 'valid range pattern. Line: 2"]'), - ("SnippetSPDXID: SPDXDRef-Snippet\nSnippetByteRange: 1:4\nSnippetByteRange:10:23", - "Error while parsing Snippet: ['Multiple values for SnippetByteRange found. " - "Line: 3']"), - ("SnippetSPDXID: SPDXRef-Snippet", r"__init__() missing 2 required " - r"positional arguments: 'file_spdx_id' and 'byte_range'") -]) +@pytest.mark.parametrize( + "snippet_str, expected_message", + [ + ( + "SnippetName: TestSnippet", + "Element Snippet is not the current element in scope, probably the expected " + "tag to start the element (SnippetSPDXID) is missing. Line: 1", + ), + ( + "SnippetSPDXID: SPDXDRef-Snippet\nSnippetByteRange: 1,4", + "Error while parsing Snippet: [\"Value for SnippetByteRange doesn't match " + 'valid range pattern. Line: 2"]', + ), + ( + "SnippetSPDXID: SPDXDRef-Snippet\nSnippetByteRange: 1:4\nSnippetByteRange:10:23", + "Error while parsing Snippet: ['Multiple values for SnippetByteRange found. " "Line: 3']", + ), + ( + "SnippetSPDXID: SPDXRef-Snippet", + r"__init__() missing 2 required " r"positional arguments: 'file_spdx_id' and 'byte_range'", + ), + ], +) def test_parse_invalid_snippet(snippet_str, expected_message): parser = Parser() diff --git a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py index 5eab39bea..e9010eb70 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py @@ -28,14 +28,16 @@ def token_assert_helper(token, token_type, value, line_number): def test_tokenization_of_document(lexer): - document_str = "\n".join([ - "SPDXVersion: SPDX-2.1", - "DataLicense: CC0-1.0", - "DocumentName: Sample_Document-V2.1", - "SPDXID: SPDXRef-DOCUMENT", - "DocumentComment: Sample Comment", - "DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301" - ]) + document_str = "\n".join( + [ + "SPDXVersion: SPDX-2.1", + "DataLicense: CC0-1.0", + "DocumentName: Sample_Document-V2.1", + "SPDXID: SPDXRef-DOCUMENT", + "DocumentComment: Sample Comment", + "DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", + ] + ) lexer.input(document_str) token_assert_helper(lexer.token(), "DOC_VERSION", "SPDXVersion", 1) token_assert_helper(lexer.token(), "LINE", "SPDX-2.1", 1) @@ -48,38 +50,50 @@ def test_tokenization_of_document(lexer): token_assert_helper(lexer.token(), "DOC_COMMENT", "DocumentComment", 5) token_assert_helper(lexer.token(), "TEXT", "Sample Comment", 5) token_assert_helper(lexer.token(), "DOC_NAMESPACE", "DocumentNamespace", 6) - token_assert_helper(lexer.token(), "LINE", - "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", 6) + token_assert_helper( + lexer.token(), "LINE", "https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", 6 + ) def test_tokenization_of_external_document_references(lexer): - data = "\n".join([ - "ExternalDocumentRef:DocumentRef-spdx-tool-2.1 http://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", - "ExternalDocumentRef:DocumentRef-spdx-tool-2.1 ldap://[2001:db8::7]/c=GB?objectClass?one SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759"]) + data = "\n".join( + [ + "ExternalDocumentRef:DocumentRef-spdx-tool-2.1 http://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "ExternalDocumentRef:DocumentRef-spdx-tool-2.1 ldap://[2001:db8::7]/c=GB?objectClass?one SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + ] + ) lexer.input(data) token_assert_helper(lexer.token(), "EXT_DOC_REF", "ExternalDocumentRef", 1) - token_assert_helper(lexer.token(), "LINE", - "DocumentRef-spdx-tool-2.1 http://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", - 1) + token_assert_helper( + lexer.token(), + "LINE", + "DocumentRef-spdx-tool-2.1 http://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + 1, + ) token_assert_helper(lexer.token(), "EXT_DOC_REF", "ExternalDocumentRef", 2) - token_assert_helper(lexer.token(), "LINE", - "DocumentRef-spdx-tool-2.1 ldap://[2001:db8::7]/c=GB?objectClass?one SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", - 2) + token_assert_helper( + lexer.token(), + "LINE", + "DocumentRef-spdx-tool-2.1 ldap://[2001:db8::7]/c=GB?objectClass?one SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + 2, + ) def test_tokenization_of_file(lexer): - file_str = "\n".join([ - "FileName: testfile.java", - "SPDXID: SPDXRef-File", - "FileType: SOURCE", - "FileType: TEXT", - "FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "LicenseConcluded: Apache-2.0", - "LicenseInfoInFile: Apache-2.0", - "FileCopyrightText: Copyright 2014 Acme Inc.", - "FileComment: Very long file", - "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts." - ]) + file_str = "\n".join( + [ + "FileName: testfile.java", + "SPDXID: SPDXRef-File", + "FileType: SOURCE", + "FileType: TEXT", + "FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + "LicenseConcluded: Apache-2.0", + "LicenseInfoInFile: Apache-2.0", + "FileCopyrightText: Copyright 2014 Acme Inc.", + "FileComment: Very long file", + "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts.", + ] + ) lexer.input(file_str) token_assert_helper(lexer.token(), "FILE_NAME", "FileName", 1) @@ -101,18 +115,23 @@ def test_tokenization_of_file(lexer): token_assert_helper(lexer.token(), "FILE_COMMENT", "FileComment", 9) token_assert_helper(lexer.token(), "TEXT", "Very long file", 9) token_assert_helper(lexer.token(), "FILE_ATTRIBUTION_TEXT", "FileAttributionText", 10) - token_assert_helper(lexer.token(), "TEXT", - "Acknowledgements that might be required to be communicated in some contexts.", - 10) + token_assert_helper( + lexer.token(), + "TEXT", + "Acknowledgements that might be required to be communicated in some contexts.", + 10, + ) def test_tokenization_of_creation_info(lexer): - creation_str = "\n".join([ - "Creator: Person: Bob (bob@example.com)", - "Creator: Organization: Acme.", - "Created: 2010-02-03T00:00:00Z", - "CreatorComment: Sample Comment" - ]) + creation_str = "\n".join( + [ + "Creator: Person: Bob (bob@example.com)", + "Creator: Organization: Acme.", + "Created: 2010-02-03T00:00:00Z", + "CreatorComment: Sample Comment", + ] + ) lexer.input(creation_str) token_assert_helper(lexer.token(), "CREATOR", "Creator", 1) @@ -126,34 +145,36 @@ def test_tokenization_of_creation_info(lexer): def test_tokenization_of_package(lexer): - package_str = "\n".join([ - "PackageName: Test", - "SPDXID: SPDXRef-Package", - "PackageVersion: Version 0.9.2", - "PackageDownloadLocation: http://example.com/test", - "FilesAnalyzed: True", - "PackageSummary: Test package", - "PackageSourceInfo: Version 1.0 of test", - "PackageFileName: test-1.0.zip", - "PackageSupplier: Organization:ACME", - "PackageOriginator: Organization:ACME", - "PackageChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", - "PackageVerificationCode: 4e3211c67a2d28fced849ee1bb76e7391b93feba (something.rdf, something.txt)", - "PackageDescription: A package.", - "PackageComment: Comment on the package.", - "PackageCopyrightText: Copyright 2014 Acme Inc.", - "PackageLicenseDeclared: Apache-2.0", - "PackageLicenseConcluded: (LicenseRef-2.0 and Apache-2.0)", - "PackageLicenseInfoFromFiles: Apache-1.0", - "PackageLicenseInfoFromFiles: Apache-2.0", - "PackageLicenseComments: License Comments", - "ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:", - "ExternalRefComment: Some comment about the package.", - "PrimaryPackagePurpose: OPERATING-SYSTEM", - "BuiltDate: 2020-01-01T12:00:00Z", - "ReleaseDate: 2021-01-01T12:00:00Z", - "ValidUntilDate: 2022-01-01T12:00:00Z" - ]) + package_str = "\n".join( + [ + "PackageName: Test", + "SPDXID: SPDXRef-Package", + "PackageVersion: Version 0.9.2", + "PackageDownloadLocation: http://example.com/test", + "FilesAnalyzed: True", + "PackageSummary: Test package", + "PackageSourceInfo: Version 1.0 of test", + "PackageFileName: test-1.0.zip", + "PackageSupplier: Organization:ACME", + "PackageOriginator: Organization:ACME", + "PackageChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", + "PackageVerificationCode: 4e3211c67a2d28fced849ee1bb76e7391b93feba (something.rdf, something.txt)", + "PackageDescription: A package.", + "PackageComment: Comment on the package.", + "PackageCopyrightText: Copyright 2014 Acme Inc.", + "PackageLicenseDeclared: Apache-2.0", + "PackageLicenseConcluded: (LicenseRef-2.0 and Apache-2.0)", + "PackageLicenseInfoFromFiles: Apache-1.0", + "PackageLicenseInfoFromFiles: Apache-2.0", + "PackageLicenseComments: License Comments", + "ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:", + "ExternalRefComment: Some comment about the package.", + "PrimaryPackagePurpose: OPERATING-SYSTEM", + "BuiltDate: 2020-01-01T12:00:00Z", + "ReleaseDate: 2021-01-01T12:00:00Z", + "ValidUntilDate: 2022-01-01T12:00:00Z", + ] + ) lexer.input(package_str) token_assert_helper(lexer.token(), "PKG_NAME", "PackageName", 1) @@ -179,8 +200,9 @@ def test_tokenization_of_package(lexer): token_assert_helper(lexer.token(), "PKG_CHECKSUM", "PackageChecksum", 11) token_assert_helper(lexer.token(), "CHECKSUM", "SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12", 11) token_assert_helper(lexer.token(), "PKG_VERIFICATION_CODE", "PackageVerificationCode", 12) - token_assert_helper(lexer.token(), "LINE", - "4e3211c67a2d28fced849ee1bb76e7391b93feba (something.rdf, something.txt)", 12) + token_assert_helper( + lexer.token(), "LINE", "4e3211c67a2d28fced849ee1bb76e7391b93feba (something.rdf, something.txt)", 12 + ) token_assert_helper(lexer.token(), "PKG_DESCRIPTION", "PackageDescription", 13) token_assert_helper(lexer.token(), "TEXT", "A package.", 13) token_assert_helper(lexer.token(), "PKG_COMMENT", "PackageComment", 14) @@ -198,8 +220,9 @@ def test_tokenization_of_package(lexer): token_assert_helper(lexer.token(), "PKG_LICENSE_COMMENT", "PackageLicenseComments", 20) token_assert_helper(lexer.token(), "TEXT", "License Comments", 20) token_assert_helper(lexer.token(), "PKG_EXTERNAL_REF", "ExternalRef", 21) - token_assert_helper(lexer.token(), "LINE", - "SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:", 21) + token_assert_helper( + lexer.token(), "LINE", "SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:", 21 + ) token_assert_helper(lexer.token(), "PKG_EXTERNAL_REF_COMMENT", "ExternalRefComment", 22) token_assert_helper(lexer.token(), "TEXT", "Some comment about the package.", 22) token_assert_helper(lexer.token(), "PRIMARY_PACKAGE_PURPOSE", "PrimaryPackagePurpose", 23) @@ -220,18 +243,20 @@ def test_tokenization_of_unknown_tag(lexer): def test_tokenization_of_snippet(lexer): - snippet_str = "\n".join([ - "SnippetSPDXID: SPDXRef-Snippet", - "SnippetLicenseComments: Some lic comment.", - "SnippetCopyrightText: Copyright 2008-2010 John Smith ", - "SnippetComment: Some snippet comment.", - "SnippetName: from linux kernel", - "SnippetFromFileSPDXID: SPDXRef-DoapSource", - "SnippetLicenseConcluded: Apache-2.0", - "LicenseInfoInSnippet: Apache-2.0", - "SnippetByteRange: 310:420", - "SnippetLineRange: 5:23", - ]) + snippet_str = "\n".join( + [ + "SnippetSPDXID: SPDXRef-Snippet", + "SnippetLicenseComments: Some lic comment.", + "SnippetCopyrightText: Copyright 2008-2010 John Smith ", + "SnippetComment: Some snippet comment.", + "SnippetName: from linux kernel", + "SnippetFromFileSPDXID: SPDXRef-DoapSource", + "SnippetLicenseConcluded: Apache-2.0", + "LicenseInfoInSnippet: Apache-2.0", + "SnippetByteRange: 310:420", + "SnippetLineRange: 5:23", + ] + ) lexer.input(snippet_str) token_assert_helper(lexer.token(), "SNIPPET_SPDX_ID", "SnippetSPDXID", 1) token_assert_helper(lexer.token(), "LINE", "SPDXRef-Snippet", 1) @@ -245,8 +270,7 @@ def test_tokenization_of_snippet(lexer): token_assert_helper(lexer.token(), "LINE", "from linux kernel", 5) token_assert_helper(lexer.token(), "SNIPPET_FILE_SPDXID", "SnippetFromFileSPDXID", 6) token_assert_helper(lexer.token(), "LINE", "SPDXRef-DoapSource", 6) - token_assert_helper(lexer.token(), "SNIPPET_LICENSE_CONCLUDED", - "SnippetLicenseConcluded", 7) + token_assert_helper(lexer.token(), "SNIPPET_LICENSE_CONCLUDED", "SnippetLicenseConcluded", 7) token_assert_helper(lexer.token(), "LINE", "Apache-2.0", 7) token_assert_helper(lexer.token(), "SNIPPET_LICENSE_INFO", "LicenseInfoInSnippet", 8) token_assert_helper(lexer.token(), "LINE", "Apache-2.0", 8) @@ -257,13 +281,15 @@ def test_tokenization_of_snippet(lexer): def test_tokenization_of_annotation(lexer): - annotation_str = "\n".join([ - "Annotator: Person: Jane Doe()", - "AnnotationDate: 2010-01-29T18:30:22Z", - "AnnotationComment: Document level annotation", - "AnnotationType: OTHER", - "SPDXREF: SPDXRef-DOCUMENT" - ]) + annotation_str = "\n".join( + [ + "Annotator: Person: Jane Doe()", + "AnnotationDate: 2010-01-29T18:30:22Z", + "AnnotationComment: Document level annotation", + "AnnotationType: OTHER", + "SPDXREF: SPDXRef-DOCUMENT", + ] + ) lexer.input(annotation_str) token_assert_helper(lexer.token(), "ANNOTATOR", "Annotator", 1) @@ -279,9 +305,13 @@ def test_tokenization_of_annotation(lexer): def test_tokenization_of_relationship(lexer): - relationship_str = "\n".join(["Relationship: SPDXRef-DOCUMENT DESCRIBES NONE", - "RelationshipComment: This is a comment.", - "Relationship: DocumentRef-extern:SPDXRef-Package DESCRIBES NONE"]) + relationship_str = "\n".join( + [ + "Relationship: SPDXRef-DOCUMENT DESCRIBES NONE", + "RelationshipComment: This is a comment.", + "Relationship: DocumentRef-extern:SPDXRef-Package DESCRIBES NONE", + ] + ) lexer.input(relationship_str) token_assert_helper(lexer.token(), "RELATIONSHIP", "Relationship", 1) diff --git a/tests/spdx/parser/tagvalue/test_tag_value_parser.py b/tests/spdx/parser/tagvalue/test_tag_value_parser.py index 192502033..1cd0183e0 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_parser.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_parser.py @@ -47,36 +47,53 @@ def test_tag_value_parser(): def test_building_contains_relationship(): parser = Parser() document_str = "\n".join( - [DOCUMENT_STR, "FileName: File without package", "SPDXID: SPDXRef-File", - "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", - "PackageName: Package with two files", "SPDXID: SPDXRef-Package-with-two-files", - "PackageDownloadLocation: https://download.com", - "FileName: File in package", "SPDXID: SPDXRef-File-in-Package", - "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", - "FileName: Second file in package", "SPDXID: SPDXRef-Second-File-in-Package", - "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", - "PackageName: Second package with file", "SPDXID: SPDXRef-Package-with-one-file", - "PackageDownloadLocation: https://download.com", - "FileName: File in package", "SPDXID: SPDXRef-File-in-different-Package", - "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", - ]) + [ + DOCUMENT_STR, + "FileName: File without package", + "SPDXID: SPDXRef-File", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "PackageName: Package with two files", + "SPDXID: SPDXRef-Package-with-two-files", + "PackageDownloadLocation: https://download.com", + "FileName: File in package", + "SPDXID: SPDXRef-File-in-Package", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "FileName: Second file in package", + "SPDXID: SPDXRef-Second-File-in-Package", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "PackageName: Second package with file", + "SPDXID: SPDXRef-Package-with-one-file", + "PackageDownloadLocation: https://download.com", + "FileName: File in package", + "SPDXID: SPDXRef-File-in-different-Package", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + ] + ) document = parser.parse(document_str) assert document.relationships == [ Relationship("SPDXRef-Package-with-two-files", RelationshipType.CONTAINS, "SPDXRef-File-in-Package"), Relationship("SPDXRef-Package-with-two-files", RelationshipType.CONTAINS, "SPDXRef-Second-File-in-Package"), - Relationship("SPDXRef-Package-with-one-file", RelationshipType.CONTAINS, "SPDXRef-File-in-different-Package")] + Relationship("SPDXRef-Package-with-one-file", RelationshipType.CONTAINS, "SPDXRef-File-in-different-Package"), + ] def test_document_with_mixed_values(): parser = Parser() document_str = "\n".join( - ["SPDXID:SPDXRef-DOCUMENT", "FileName: File without package", "SPDXID: SPDXRef-File", - "PackageDownloadLocation: https://download.com", - "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759"]) + [ + "SPDXID:SPDXRef-DOCUMENT", + "FileName: File without package", + "SPDXID: SPDXRef-File", + "PackageDownloadLocation: https://download.com", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + ] + ) with pytest.raises(SPDXParsingError) as err: parser.parse(document_str) - assert err.value.get_messages() == ["Element Package is not the current element in scope, probably the expected " - "tag to start the element (PackageName) is missing. Line: 4"] + assert err.value.get_messages() == [ + "Element Package is not the current element in scope, probably the expected " + "tag to start the element (PackageName) is missing. Line: 4" + ] diff --git a/tests/spdx/test_actor_parser.py b/tests/spdx/test_actor_parser.py index cdaf6ef16..dfd43a172 100644 --- a/tests/spdx/test_actor_parser.py +++ b/tests/spdx/test_actor_parser.py @@ -17,12 +17,20 @@ from spdx.parser.error import SPDXParsingError -@pytest.mark.parametrize("actor_string,expected_type,expected_name,expected_mail", [ - ("Person: Jane Doe (jane.doe@example.com)", ActorType.PERSON, "Jane Doe", "jane.doe@example.com"), - ("Organization: Example organization (organization@example.com)", ActorType.ORGANIZATION, "Example organization", - "organization@example.com"), - ("Organization: Example organization ( )", ActorType.ORGANIZATION, "Example organization", None), - ("Tool: Example tool ", ActorType.TOOL, "Example tool", None)]) +@pytest.mark.parametrize( + "actor_string,expected_type,expected_name,expected_mail", + [ + ("Person: Jane Doe (jane.doe@example.com)", ActorType.PERSON, "Jane Doe", "jane.doe@example.com"), + ( + "Organization: Example organization (organization@example.com)", + ActorType.ORGANIZATION, + "Example organization", + "organization@example.com", + ), + ("Organization: Example organization ( )", ActorType.ORGANIZATION, "Example organization", None), + ("Tool: Example tool ", ActorType.TOOL, "Example tool", None), + ], +) def test_parse_actor(actor_string, expected_type, expected_name, expected_mail): actor_parser = ActorParser() @@ -33,12 +41,16 @@ def test_parse_actor(actor_string, expected_type, expected_name, expected_mail): assert actor.email == expected_mail -@pytest.mark.parametrize("actor_string,expected_message", [ - ("Perso: Jane Doe (jane.doe@example.com)", - ["Actor Perso: Jane Doe (jane.doe@example.com) doesn't match any of person, organization or tool."]), - ("Toole Example Tool ()", - ["Actor Toole Example Tool () doesn't match any of person, organization or tool."]) -]) +@pytest.mark.parametrize( + "actor_string,expected_message", + [ + ( + "Perso: Jane Doe (jane.doe@example.com)", + ["Actor Perso: Jane Doe (jane.doe@example.com) doesn't match any of person, organization or tool."], + ), + ("Toole Example Tool ()", ["Actor Toole Example Tool () doesn't match any of person, organization or tool."]), + ], +) def test_parse_invalid_actor(actor_string, expected_message): actor_parser = ActorParser() actor_string = actor_string diff --git a/tests/spdx/test_casing_tools.py b/tests/spdx/test_casing_tools.py index 572feb7b4..354cb7657 100644 --- a/tests/spdx/test_casing_tools.py +++ b/tests/spdx/test_casing_tools.py @@ -20,9 +20,10 @@ def test_snake_case_to_camel_case(snake_case_str, camel_case_str): assert camel_case == camel_case_str -@pytest.mark.parametrize("camel_case_str,snake_case_str", - [("camelCase", "camel_case"), ("camelCaseMore", "camel_case_more"), - ("CamelCase", "camel_case")]) +@pytest.mark.parametrize( + "camel_case_str,snake_case_str", + [("camelCase", "camel_case"), ("camelCaseMore", "camel_case_more"), ("CamelCase", "camel_case")], +) def test_camel_case_to_snake_case(camel_case_str, snake_case_str): snake_case = camel_case_to_snake_case(camel_case_str) diff --git a/tests/spdx/test_datetime_conversions.py b/tests/spdx/test_datetime_conversions.py index 265054c0b..b396edf13 100644 --- a/tests/spdx/test_datetime_conversions.py +++ b/tests/spdx/test_datetime_conversions.py @@ -27,9 +27,13 @@ def test_datetime_from_str(): assert date == datetime(2010, 3, 4, 5, 45, 11) -@pytest.mark.parametrize("invalid_date_str, error_type, expected_message", - [(5, TypeError, "Could not convert str to datetime, invalid type: int"), - ("2010-02-03", ValueError, "time data '2010-02-03' does not match format '%Y-%m-%dT%H:%M:%SZ'")]) +@pytest.mark.parametrize( + "invalid_date_str, error_type, expected_message", + [ + (5, TypeError, "Could not convert str to datetime, invalid type: int"), + ("2010-02-03", ValueError, "time data '2010-02-03' does not match format '%Y-%m-%dT%H:%M:%SZ'"), + ], +) def test_datetime_from_str_error(invalid_date_str, error_type, expected_message): with pytest.raises(error_type, match=expected_message): datetime_from_str(invalid_date_str) diff --git a/tests/spdx/validation/test_actor_validator.py b/tests/spdx/validation/test_actor_validator.py index 7203977aa..19a99b8c7 100644 --- a/tests/spdx/validation/test_actor_validator.py +++ b/tests/spdx/validation/test_actor_validator.py @@ -26,16 +26,22 @@ def test_valid_actor_person(): assert validation_messages == [] -@pytest.mark.parametrize("actor, expected_message", - [(actor_fixture(actor_type=ActorType.TOOL, email="mail@mail.com"), - "email must be None if actor_type is TOOL, but is: mail@mail.com"), - ]) +@pytest.mark.parametrize( + "actor, expected_message", + [ + ( + actor_fixture(actor_type=ActorType.TOOL, email="mail@mail.com"), + "email must be None if actor_type is TOOL, but is: mail@mail.com", + ), + ], +) def test_invalid_actor(actor, expected_message): parent_id = "SPDXRef-DOCUMENT" validation_messages: List[ValidationMessage] = validate_actor(actor, parent_id) - expected = ValidationMessage(expected_message, - ValidationContext(parent_id=parent_id, element_type=SpdxElementType.ACTOR, - full_element=actor)) + expected = ValidationMessage( + expected_message, + ValidationContext(parent_id=parent_id, element_type=SpdxElementType.ACTOR, full_element=actor), + ) assert validation_messages == [expected] diff --git a/tests/spdx/validation/test_annotation_validator.py b/tests/spdx/validation/test_annotation_validator.py index 3a0e0d937..aba5995d5 100644 --- a/tests/spdx/validation/test_annotation_validator.py +++ b/tests/spdx/validation/test_annotation_validator.py @@ -26,17 +26,23 @@ def test_valid_annotation(): assert validation_messages == [] -@pytest.mark.parametrize("annotation_id, file_id, expected_message", - [("SPDXRef-File", "SPDXRef-hiddenFile", - 'did not find the referenced spdx_id "SPDXRef-File" in the SPDX document') - ]) +@pytest.mark.parametrize( + "annotation_id, file_id, expected_message", + [ + ( + "SPDXRef-File", + "SPDXRef-hiddenFile", + 'did not find the referenced spdx_id "SPDXRef-File" in the SPDX document', + ) + ], +) def test_invalid_annotation(annotation_id, file_id, expected_message): annotation: Annotation = annotation_fixture(spdx_id=annotation_id) document: Document = document_fixture(files=[file_fixture(spdx_id=file_id)]) validation_messages: List[ValidationMessage] = validate_annotation(annotation, document) - expected = ValidationMessage(expected_message, - ValidationContext(element_type=SpdxElementType.ANNOTATION, - full_element=annotation)) + expected = ValidationMessage( + expected_message, ValidationContext(element_type=SpdxElementType.ANNOTATION, full_element=annotation) + ) assert validation_messages == [expected] diff --git a/tests/spdx/validation/test_checksum_validator.py b/tests/spdx/validation/test_checksum_validator.py index 42f6dc74e..12c89bccf 100644 --- a/tests/spdx/validation/test_checksum_validator.py +++ b/tests/spdx/validation/test_checksum_validator.py @@ -19,110 +19,179 @@ from tests.spdx.fixtures import checksum_fixture -@pytest.mark.parametrize("checksum", - [checksum_fixture(), - Checksum(ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), - Checksum(ChecksumAlgorithm.SHA224, - "9c9f4e27d957a123cc32d86afe33ae53b1184192cccb23b0f257f588"), - Checksum(ChecksumAlgorithm.SHA256, - "fbea580d286bbbbb41314430d58ba887716a74d7134119c5307cdc9f0c7a4299"), - Checksum(ChecksumAlgorithm.SHA384, - "73b4ad9a34e5f76cb2525ea6bb8b1dcf9ba79426b3295bd18bc6d148cba4fcc2ca3cf2630fd481b47caaac9127103933"), - Checksum(ChecksumAlgorithm.SHA512, - "c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f15af43e7cb5547f1a464053"), - Checksum(ChecksumAlgorithm.SHA3_256, - "1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce"), - Checksum(ChecksumAlgorithm.SHA3_384, - "dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166"), - Checksum(ChecksumAlgorithm.SHA3_512, - "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d111310266a5d46e2bc1ffbb36"), - Checksum(ChecksumAlgorithm.BLAKE2B_256, - "a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7"), - Checksum(ChecksumAlgorithm.BLAKE2B_384, - "902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2"), - Checksum(ChecksumAlgorithm.BLAKE2B_512, - "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8c4af74dce531ca8ebd8824c"), - Checksum(ChecksumAlgorithm.BLAKE3, - "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed"), - Checksum(ChecksumAlgorithm.MD2, "af1eec2a1b18886c3f3cc244349d91d8"), - Checksum(ChecksumAlgorithm.MD4, "d4c41ce30a517d6ce9d79c8c17bb4b66"), - Checksum(ChecksumAlgorithm.MD5, "0d7f61beb7018b3924c6b8f96549fa39"), - Checksum(ChecksumAlgorithm.MD6, - "af1eec2a1b18886c3f3cc244349d91d8d4c41ce30a517d6ce9d79c8c17bb4b660d7f61beb7018b3924c6b8f96549fa39"), - Checksum(ChecksumAlgorithm.ADLER32, "02ec0130")]) +@pytest.mark.parametrize( + "checksum", + [ + checksum_fixture(), + Checksum(ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), + Checksum(ChecksumAlgorithm.SHA224, "9c9f4e27d957a123cc32d86afe33ae53b1184192cccb23b0f257f588"), + Checksum(ChecksumAlgorithm.SHA256, "fbea580d286bbbbb41314430d58ba887716a74d7134119c5307cdc9f0c7a4299"), + Checksum( + ChecksumAlgorithm.SHA384, + "73b4ad9a34e5f76cb2525ea6bb8b1dcf9ba79426b3295bd18bc6d148cba4fcc2ca3cf2630fd481b47caaac9127103933", + ), + Checksum( + ChecksumAlgorithm.SHA512, + "c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f15af43e7cb5547f1a464053", + ), + Checksum(ChecksumAlgorithm.SHA3_256, "1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce"), + Checksum( + ChecksumAlgorithm.SHA3_384, + "dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166", + ), + Checksum( + ChecksumAlgorithm.SHA3_512, + "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d111310266a5d46e2bc1ffbb36", + ), + Checksum(ChecksumAlgorithm.BLAKE2B_256, "a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7"), + Checksum( + ChecksumAlgorithm.BLAKE2B_384, + "902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2", + ), + Checksum( + ChecksumAlgorithm.BLAKE2B_512, + "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8c4af74dce531ca8ebd8824c", + ), + Checksum( + ChecksumAlgorithm.BLAKE3, + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed", + ), + Checksum(ChecksumAlgorithm.MD2, "af1eec2a1b18886c3f3cc244349d91d8"), + Checksum(ChecksumAlgorithm.MD4, "d4c41ce30a517d6ce9d79c8c17bb4b66"), + Checksum(ChecksumAlgorithm.MD5, "0d7f61beb7018b3924c6b8f96549fa39"), + Checksum( + ChecksumAlgorithm.MD6, + "af1eec2a1b18886c3f3cc244349d91d8d4c41ce30a517d6ce9d79c8c17bb4b660d7f61beb7018b3924c6b8f96549fa39", + ), + Checksum(ChecksumAlgorithm.ADLER32, "02ec0130"), + ], +) def test_valid_checksum(checksum): validation_messages: List[ValidationMessage] = validate_checksum(checksum, "parent_id", "SPDX-2.3") assert validation_messages == [] -@pytest.mark.parametrize("checksum, expected_message", - [(Checksum(ChecksumAlgorithm.SHA1, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA1 must consist of 40 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.SHA224, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA224 must consist of 56 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.SHA256, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA256 must consist of 64 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.SHA384, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA384 must consist of 96 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.SHA512, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA512 must consist of 128 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.SHA3_256, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA3_256 must consist of 64 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.SHA3_384, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA3_384 must consist of 96 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.SHA3_512, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA3_512 must consist of 128 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.BLAKE2B_256, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.BLAKE2B_256 must consist of 64 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.BLAKE2B_384, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.BLAKE2B_384 must consist of 96 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.BLAKE2B_512, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.BLAKE2B_512 must consist of 128 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.BLAKE3, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.BLAKE3 must consist of at least 256 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.MD2, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), - "value of ChecksumAlgorithm.MD2 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364f3ebbb42c484ff43d00791c (length: 40 digits)"), - (Checksum(ChecksumAlgorithm.MD4, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), - "value of ChecksumAlgorithm.MD4 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364f3ebbb42c484ff43d00791c (length: 40 digits)"), - (Checksum(ChecksumAlgorithm.MD5, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), - "value of ChecksumAlgorithm.MD5 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364f3ebbb42c484ff43d00791c (length: 40 digits)"), - (Checksum(ChecksumAlgorithm.MD6, - "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed5"), - "value of ChecksumAlgorithm.MD6 must consist of between 0 and 512 lowercase hexadecimal digits, but is: a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed5 (length: 513 digits)"), - (Checksum(ChecksumAlgorithm.ADLER32, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.ADLER32 must consist of 8 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)"), - (Checksum(ChecksumAlgorithm.SHA1, "CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4"), - "value of ChecksumAlgorithm.SHA1 must consist of 40 lowercase hexadecimal digits, but is: CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4 (length: 40 digits)"), - ]) +@pytest.mark.parametrize( + "checksum, expected_message", + [ + ( + Checksum(ChecksumAlgorithm.SHA1, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA1 must consist of 40 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA224, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA224 must consist of 56 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA256, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA256 must consist of 64 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA384, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA384 must consist of 96 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA512, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA512 must consist of 128 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA3_256, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA3_256 must consist of 64 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA3_384, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA3_384 must consist of 96 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA3_512, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.SHA3_512 must consist of 128 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.BLAKE2B_256, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.BLAKE2B_256 must consist of 64 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.BLAKE2B_384, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.BLAKE2B_384 must consist of 96 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.BLAKE2B_512, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.BLAKE2B_512 must consist of 128 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.BLAKE3, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.BLAKE3 must consist of at least 256 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.MD2, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), + "value of ChecksumAlgorithm.MD2 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364f3ebbb42c484ff43d00791c (length: 40 digits)", + ), + ( + Checksum(ChecksumAlgorithm.MD4, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), + "value of ChecksumAlgorithm.MD4 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364f3ebbb42c484ff43d00791c (length: 40 digits)", + ), + ( + Checksum(ChecksumAlgorithm.MD5, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), + "value of ChecksumAlgorithm.MD5 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364f3ebbb42c484ff43d00791c (length: 40 digits)", + ), + ( + Checksum( + ChecksumAlgorithm.MD6, + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed5", + ), + "value of ChecksumAlgorithm.MD6 must consist of between 0 and 512 lowercase hexadecimal digits, but is: a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed5 (length: 513 digits)", + ), + ( + Checksum(ChecksumAlgorithm.ADLER32, "af1eec2a1b18886c3f3cc244349d91d8"), + "value of ChecksumAlgorithm.ADLER32 must consist of 8 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + ), + ( + Checksum(ChecksumAlgorithm.SHA1, "CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4"), + "value of ChecksumAlgorithm.SHA1 must consist of 40 lowercase hexadecimal digits, but is: CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4 (length: 40 digits)", + ), + ], +) def test_invalid_checksum(checksum, expected_message): parent_id = "parent_id" validation_messages: List[ValidationMessage] = validate_checksum(checksum, parent_id, "SPDX-2.3") - expected = ValidationMessage(expected_message, - ValidationContext(parent_id=parent_id, element_type=SpdxElementType.CHECKSUM, - full_element=checksum)) + expected = ValidationMessage( + expected_message, + ValidationContext(parent_id=parent_id, element_type=SpdxElementType.CHECKSUM, full_element=checksum), + ) assert validation_messages == [expected] -@pytest.mark.parametrize("checksum", - [Checksum(ChecksumAlgorithm.SHA3_256, - "1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce"), - Checksum(ChecksumAlgorithm.SHA3_384, - "dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166"), - Checksum(ChecksumAlgorithm.SHA3_512, - "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d111310266a5d46e2bc1ffbb36"), - Checksum(ChecksumAlgorithm.BLAKE2B_256, - "a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7"), - Checksum(ChecksumAlgorithm.BLAKE2B_384, - "902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2"), - Checksum(ChecksumAlgorithm.BLAKE2B_512, - "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8c4af74dce531ca8ebd8824c"), - Checksum(ChecksumAlgorithm.BLAKE3, - "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed"), - Checksum(ChecksumAlgorithm.ADLER32, "02ec0130") - ]) +@pytest.mark.parametrize( + "checksum", + [ + Checksum(ChecksumAlgorithm.SHA3_256, "1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce"), + Checksum( + ChecksumAlgorithm.SHA3_384, + "dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166", + ), + Checksum( + ChecksumAlgorithm.SHA3_512, + "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d111310266a5d46e2bc1ffbb36", + ), + Checksum(ChecksumAlgorithm.BLAKE2B_256, "a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7"), + Checksum( + ChecksumAlgorithm.BLAKE2B_384, + "902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2", + ), + Checksum( + ChecksumAlgorithm.BLAKE2B_512, + "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8c4af74dce531ca8ebd8824c", + ), + Checksum( + ChecksumAlgorithm.BLAKE3, + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed", + ), + Checksum(ChecksumAlgorithm.ADLER32, "02ec0130"), + ], +) def test_v2_3only_checksums(checksum): parent_id = "parent_id" validation_messages: List[ValidationMessage] = validate_checksum(checksum, parent_id, "SPDX-2.2") diff --git a/tests/spdx/validation/test_creation_info_validator.py b/tests/spdx/validation/test_creation_info_validator.py index d502aa1a0..79274c906 100644 --- a/tests/spdx/validation/test_creation_info_validator.py +++ b/tests/spdx/validation/test_creation_info_validator.py @@ -25,15 +25,22 @@ def test_valid_creation_info(): assert validation_messages == [] -@pytest.mark.parametrize \ - ("creation_info_input, spdx_id, expected_message", - [(creation_info_fixture(spdx_id="SPDXRef-doc"), "SPDXRef-doc", - 'spdx_id must be "SPDXRef-DOCUMENT", but is: SPDXRef-doc'), - (creation_info_fixture(data_license="MIT"), "SPDXRef-DOCUMENT", - 'data_license must be "CC0-1.0", but is: MIT'), - (creation_info_fixture(document_namespace="some_namespace"), "SPDXRef-DOCUMENT", - "document_namespace must be a valid URI specified in RFC-3986 and must contain no fragment (#), but is: some_namespace"), - ]) +@pytest.mark.parametrize( + "creation_info_input, spdx_id, expected_message", + [ + ( + creation_info_fixture(spdx_id="SPDXRef-doc"), + "SPDXRef-doc", + 'spdx_id must be "SPDXRef-DOCUMENT", but is: SPDXRef-doc', + ), + (creation_info_fixture(data_license="MIT"), "SPDXRef-DOCUMENT", 'data_license must be "CC0-1.0", but is: MIT'), + ( + creation_info_fixture(document_namespace="some_namespace"), + "SPDXRef-DOCUMENT", + "document_namespace must be a valid URI specified in RFC-3986 and must contain no fragment (#), but is: some_namespace", + ), + ], +) def test_invalid_creation_info(creation_info_input, expected_message, spdx_id): validation_messages: List[ValidationMessage] = validate_creation_info(creation_info_input, "SPDX-2.3") diff --git a/tests/spdx/validation/test_document_validator.py b/tests/spdx/validation/test_document_validator.py index 8cf9fe043..c5cc55c64 100644 --- a/tests/spdx/validation/test_document_validator.py +++ b/tests/spdx/validation/test_document_validator.py @@ -27,22 +27,43 @@ def test_valid_document(): assert validation_messages == [] -@pytest.mark.parametrize("creation_info, version_input, expected_message", - [(creation_info_fixture(spdx_version="SPDX-2.3"), "SPDX-2.3", None), - (creation_info_fixture(spdx_version="SPDX-2.3"), None, None), - (creation_info_fixture(spdx_version="SPDX-2.3"), "SPDX-2.2", - "provided SPDX version SPDX-2.2 does not match the document's SPDX version SPDX-2.3"), - (creation_info_fixture(spdx_version="SPDX-2.3"), "SPDX2.3", - "provided SPDX version SPDX2.3 does not match the document's SPDX version SPDX-2.3"), - (creation_info_fixture(spdx_version="SPDX2.3"), "SPDX-2.3", - 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: SPDX2.3'), - (creation_info_fixture(spdx_version="SPDX2.3"), None, - 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: SPDX2.3'), - (creation_info_fixture(spdx_version="SPDX2.3"), "SPDX2.3", - 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: SPDX2.3'), - (creation_info_fixture(spdx_version="SPDX-2.1"), "SPDX-2.1", - 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: SPDX-2.1'), - ]) +@pytest.mark.parametrize( + "creation_info, version_input, expected_message", + [ + (creation_info_fixture(spdx_version="SPDX-2.3"), "SPDX-2.3", None), + (creation_info_fixture(spdx_version="SPDX-2.3"), None, None), + ( + creation_info_fixture(spdx_version="SPDX-2.3"), + "SPDX-2.2", + "provided SPDX version SPDX-2.2 does not match the document's SPDX version SPDX-2.3", + ), + ( + creation_info_fixture(spdx_version="SPDX-2.3"), + "SPDX2.3", + "provided SPDX version SPDX2.3 does not match the document's SPDX version SPDX-2.3", + ), + ( + creation_info_fixture(spdx_version="SPDX2.3"), + "SPDX-2.3", + 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: SPDX2.3', + ), + ( + creation_info_fixture(spdx_version="SPDX2.3"), + None, + 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: SPDX2.3', + ), + ( + creation_info_fixture(spdx_version="SPDX2.3"), + "SPDX2.3", + 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: SPDX2.3', + ), + ( + creation_info_fixture(spdx_version="SPDX-2.1"), + "SPDX-2.1", + 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: SPDX-2.1', + ), + ], +) def test_spdx_version_handling(creation_info: CreationInfo, version_input: str, expected_message: Optional[str]): document: Document = document_fixture(creation_info=creation_info) validation_messages: List[ValidationMessage] = validate_full_spdx_document(document, version_input) @@ -52,16 +73,25 @@ def test_spdx_version_handling(creation_info: CreationInfo, version_input: str, if expected_message: expected.append(ValidationMessage(expected_message, context)) - expected.append(ValidationMessage("There are issues concerning the SPDX version of the document. " - "As subsequent validation relies on the correct version, " - "the validation process has been cancelled.", context)) + expected.append( + ValidationMessage( + "There are issues concerning the SPDX version of the document. " + "As subsequent validation relies on the correct version, " + "the validation process has been cancelled.", + context, + ) + ) assert validation_messages == expected -@pytest.mark.parametrize("relationships", - [[Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-File")], - [Relationship("SPDXRef-File", RelationshipType.DESCRIBED_BY, "SPDXRef-DOCUMENT")]]) +@pytest.mark.parametrize( + "relationships", + [ + [Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-File")], + [Relationship("SPDXRef-File", RelationshipType.DESCRIBED_BY, "SPDXRef-DOCUMENT")], + ], +) def test_document_describes_at_least_one_element(relationships): document = document_fixture(relationships=relationships) validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) @@ -71,26 +101,36 @@ def test_document_describes_at_least_one_element(relationships): def test_document_does_not_describe_an_element(): document = document_fixture( - relationships=[Relationship("SPDXRef-Package", RelationshipType.DESCRIBES, "SPDXRef-File")]) + relationships=[Relationship("SPDXRef-Package", RelationshipType.DESCRIBES, "SPDXRef-File")] + ) validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) - assert validation_messages == [ValidationMessage( - 'there must be at least one relationship "SPDXRef-DOCUMENT DESCRIBES ..." or "... DESCRIBED_BY SPDXRef-DOCUMENT"', - ValidationContext(spdx_id="SPDXRef-DOCUMENT", element_type=SpdxElementType.DOCUMENT) - )] + assert validation_messages == [ + ValidationMessage( + 'there must be at least one relationship "SPDXRef-DOCUMENT DESCRIBES ..." or "... DESCRIBED_BY SPDXRef-DOCUMENT"', + ValidationContext(spdx_id="SPDXRef-DOCUMENT", element_type=SpdxElementType.DOCUMENT), + ) + ] def test_duplicated_spdx_ids(): document = document_fixture( - files=[file_fixture(spdx_id="SPDXRef-File"), file_fixture(spdx_id="SPDXRef-2"), - file_fixture(spdx_id="SPDXRef-3")], + files=[ + file_fixture(spdx_id="SPDXRef-File"), + file_fixture(spdx_id="SPDXRef-2"), + file_fixture(spdx_id="SPDXRef-3"), + ], packages=[package_fixture(spdx_id="SPDXRef-2"), package_fixture(spdx_id="SPDXRef-DOCUMENT")], - snippets=[snippet_fixture(spdx_id="SPDXRef-2"), snippet_fixture(spdx_id="SPDXRef-3")]) + snippets=[snippet_fixture(spdx_id="SPDXRef-2"), snippet_fixture(spdx_id="SPDXRef-3")], + ) context = ValidationContext(spdx_id=document.creation_info.spdx_id, element_type=SpdxElementType.DOCUMENT) validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) - assert validation_messages == [ValidationMessage( - "every spdx_id must be unique within the document, but found the following duplicates: ['SPDXRef-2', 'SPDXRef-3', 'SPDXRef-DOCUMENT']", - context)] + assert validation_messages == [ + ValidationMessage( + "every spdx_id must be unique within the document, but found the following duplicates: ['SPDXRef-2', 'SPDXRef-3', 'SPDXRef-DOCUMENT']", + context, + ) + ] diff --git a/tests/spdx/validation/test_external_document_ref_validator.py b/tests/spdx/validation/test_external_document_ref_validator.py index a81bc7b9d..4ad65edf4 100644 --- a/tests/spdx/validation/test_external_document_ref_validator.py +++ b/tests/spdx/validation/test_external_document_ref_validator.py @@ -18,7 +18,8 @@ def test_valid_external_document_ref(): external_document_ref = external_document_ref_fixture() - validation_messages: List[ValidationMessage] = validate_external_document_ref(external_document_ref, "parent_id", - "SPDX-2.3") + validation_messages: List[ValidationMessage] = validate_external_document_ref( + external_document_ref, "parent_id", "SPDX-2.3" + ) assert validation_messages == [] diff --git a/tests/spdx/validation/test_external_package_ref_validator.py b/tests/spdx/validation/test_external_package_ref_validator.py index adcdebaab..8037141d1 100644 --- a/tests/spdx/validation/test_external_package_ref_validator.py +++ b/tests/spdx/validation/test_external_package_ref_validator.py @@ -29,164 +29,267 @@ from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage -@pytest.mark.parametrize("category, reference_type, locator", - [(ExternalPackageRefCategory.SECURITY, "cpe22Type", - "cpe:/o:canonical:ubuntu_linux:10.04:-:lts"), - (ExternalPackageRefCategory.SECURITY, "cpe23Type", - "cpe:2.3:o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*"), - (ExternalPackageRefCategory.SECURITY, "advisory", - "https://nvd.nist.gov/vuln/detail/CVE-2020-28498"), - (ExternalPackageRefCategory.SECURITY, "fix", - "https://github.com/indutny/elliptic/commit/441b7428"), - (ExternalPackageRefCategory.SECURITY, "url", - "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/secp256k1_twist_attacks.md"), - (ExternalPackageRefCategory.SECURITY, "swid", "swid:2df9de35-0aff-4a86-ace6-f7dddd1ade4c"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "maven-central", - "org.apache.tomcat:tomcat:9.0.0.M4"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "npm", "http-server@0.3.0"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "nuget", "Microsoft.AspNet.MVC/5.0.0"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "bower", "modernizr#2.6.2"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", - "pkg:docker/debian@sha256:2f04d3d33b6027bb74ecc81397abe780649ec89f1a2af18d7022737d0482cefe"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", - "pkg:bitbucket/birkenfeld/pygments-main@244fd47e07d1014f0aed9c"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", - "pkg:deb/debian/curl@7.50.3-1?arch=i386&distro=jessie"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", - "pkg:docker/customer/dockerimage@sha256:244fd47e07d1004f0aed9c?repository_url=gcr.io"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", - "pkg:gem/jruby-launcher@1.1.2?platform=java"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:gem/ruby-advisory-db-check@0.12.4"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", - "pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", - "pkg:golang/google.golang.org/genproto#googleapis/api/annotations"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", - "pkg:maven/org.apache.xmlgraphics/batik-anim@1.9.1?repository_url=repo.spring.io%2Frelease"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:npm/%40angular/animation@12.3.1"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", - "pkg:nuget/EnterpriseLibrary.Common@6.0.1304"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", - "pkg:rpm/fedora/curl@7.50.3-1.fc25?arch=i386&distro=fedora-25"), - (ExternalPackageRefCategory.PERSISTENT_ID, "swh", - "swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2"), - (ExternalPackageRefCategory.PERSISTENT_ID, "swh", - "swh:1:dir:d198bc9d7a6bcf6db04f476d29314f157507d505"), - (ExternalPackageRefCategory.PERSISTENT_ID, "swh", - "swh:1:rev:309cf2674ee7a0749978cf8265ab91a60aea0f7d"), - (ExternalPackageRefCategory.PERSISTENT_ID, "swh", - "swh:1:rel:22ece559cc7cc2364edc5e5593d63ae8bd229f9f"), - (ExternalPackageRefCategory.PERSISTENT_ID, "swh", - "swh:1:snp:c7c108084bc0bf3d81436bf980b46e98bd338453"), - (ExternalPackageRefCategory.PERSISTENT_ID, "gitoid", - "gitoid:blob:sha1:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64"), - (ExternalPackageRefCategory.PERSISTENT_ID, "gitoid", - "gitoid:blob:sha256:3557f7eb43c621c71483743d4b37059bb80933e7f71277c0c3b3846159d1f61c"), - (ExternalPackageRefCategory.OTHER, "some idstring", "#//string-withOUT!Spaces\\?") - ]) +@pytest.mark.parametrize( + "category, reference_type, locator", + [ + (ExternalPackageRefCategory.SECURITY, "cpe22Type", "cpe:/o:canonical:ubuntu_linux:10.04:-:lts"), + (ExternalPackageRefCategory.SECURITY, "cpe23Type", "cpe:2.3:o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*"), + (ExternalPackageRefCategory.SECURITY, "advisory", "https://nvd.nist.gov/vuln/detail/CVE-2020-28498"), + (ExternalPackageRefCategory.SECURITY, "fix", "https://github.com/indutny/elliptic/commit/441b7428"), + ( + ExternalPackageRefCategory.SECURITY, + "url", + "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/secp256k1_twist_attacks.md", + ), + (ExternalPackageRefCategory.SECURITY, "swid", "swid:2df9de35-0aff-4a86-ace6-f7dddd1ade4c"), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "maven-central", "org.apache.tomcat:tomcat:9.0.0.M4"), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "npm", "http-server@0.3.0"), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "nuget", "Microsoft.AspNet.MVC/5.0.0"), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "bower", "modernizr#2.6.2"), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:docker/debian@sha256:2f04d3d33b6027bb74ecc81397abe780649ec89f1a2af18d7022737d0482cefe", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:bitbucket/birkenfeld/pygments-main@244fd47e07d1014f0aed9c", + ), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:deb/debian/curl@7.50.3-1?arch=i386&distro=jessie"), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:docker/customer/dockerimage@sha256:244fd47e07d1004f0aed9c?repository_url=gcr.io", + ), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:gem/jruby-launcher@1.1.2?platform=java"), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:gem/ruby-advisory-db-check@0.12.4"), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:github/package-url/purl-spec@244fd47e07d1004f0aed9c", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:golang/google.golang.org/genproto#googleapis/api/annotations", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:maven/org.apache.xmlgraphics/batik-anim@1.9.1?repository_url=repo.spring.io%2Frelease", + ), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:npm/%40angular/animation@12.3.1"), + (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:nuget/EnterpriseLibrary.Common@6.0.1304"), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:rpm/fedora/curl@7.50.3-1.fc25?arch=i386&distro=fedora-25", + ), + (ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh:1:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2"), + (ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh:1:dir:d198bc9d7a6bcf6db04f476d29314f157507d505"), + (ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh:1:rev:309cf2674ee7a0749978cf8265ab91a60aea0f7d"), + (ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh:1:rel:22ece559cc7cc2364edc5e5593d63ae8bd229f9f"), + (ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh:1:snp:c7c108084bc0bf3d81436bf980b46e98bd338453"), + ( + ExternalPackageRefCategory.PERSISTENT_ID, + "gitoid", + "gitoid:blob:sha1:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64", + ), + ( + ExternalPackageRefCategory.PERSISTENT_ID, + "gitoid", + "gitoid:blob:sha256:3557f7eb43c621c71483743d4b37059bb80933e7f71277c0c3b3846159d1f61c", + ), + (ExternalPackageRefCategory.OTHER, "some idstring", "#//string-withOUT!Spaces\\?"), + ], +) def test_valid_external_package_ref(category, reference_type, locator): external_package_ref = ExternalPackageRef(category, reference_type, locator, "externalPackageRef comment") - validation_messages: List[ValidationMessage] = validate_external_package_ref(external_package_ref, "parent_id", - "SPDX-2.3") + validation_messages: List[ValidationMessage] = validate_external_package_ref( + external_package_ref, "parent_id", "SPDX-2.3" + ) assert validation_messages == [] -@pytest.mark.parametrize("category, reference_type, locator, expected_message", - [( - ExternalPackageRefCategory.SECURITY, "cpe22Typo", - "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", - "externalPackageRef type in category SECURITY must be one of ['cpe22Type', 'cpe23Type', 'advisory', 'fix', 'url', 'swid'], but is: cpe22Typo"), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "nugat", - "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", - "externalPackageRef type in category PACKAGE_MANAGER must be one of ['maven-central', 'npm', 'nuget', 'bower', 'purl'], but is: nugat"), - (ExternalPackageRefCategory.PERSISTENT_ID, "git-oid", - "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", - "externalPackageRef type in category PERSISTENT_ID must be one of ['swh', 'gitoid'], but is: git-oid") - ]) +@pytest.mark.parametrize( + "category, reference_type, locator, expected_message", + [ + ( + ExternalPackageRefCategory.SECURITY, + "cpe22Typo", + "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", + "externalPackageRef type in category SECURITY must be one of ['cpe22Type', 'cpe23Type', 'advisory', 'fix', 'url', 'swid'], but is: cpe22Typo", + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "nugat", + "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", + "externalPackageRef type in category PACKAGE_MANAGER must be one of ['maven-central', 'npm', 'nuget', 'bower', 'purl'], but is: nugat", + ), + ( + ExternalPackageRefCategory.PERSISTENT_ID, + "git-oid", + "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", + "externalPackageRef type in category PERSISTENT_ID must be one of ['swh', 'gitoid'], but is: git-oid", + ), + ], +) def test_invalid_external_package_ref_types(category, reference_type, locator, expected_message): external_package_ref = ExternalPackageRef(category, reference_type, locator, "externalPackageRef comment") parent_id = "SPDXRef-Package" - validation_messages: List[ValidationMessage] = validate_external_package_ref(external_package_ref, parent_id, - "SPDX-2.3") + validation_messages: List[ValidationMessage] = validate_external_package_ref( + external_package_ref, parent_id, "SPDX-2.3" + ) - expected = ValidationMessage(expected_message, - ValidationContext(parent_id=parent_id, - element_type=SpdxElementType.EXTERNAL_PACKAGE_REF, - full_element=external_package_ref)) + expected = ValidationMessage( + expected_message, + ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.EXTERNAL_PACKAGE_REF, full_element=external_package_ref + ), + ) assert validation_messages == [expected] -@pytest.mark.parametrize("category, reference_type, locator, expected_message", - [(ExternalPackageRefCategory.SECURITY, "cpe22Type", "cpe:o:canonical:ubuntu_linux:10.04:-:lts", - f'externalPackageRef locator of type "cpe22Type" must conform with the regex {CPE22TYPE_REGEX}, but is: cpe:o:canonical:ubuntu_linux:10.04:-:lts'), - (ExternalPackageRefCategory.SECURITY, "cpe23Type", - "cpe:2.3:/o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*", - f'externalPackageRef locator of type "cpe23Type" must conform with the regex {CPE23TYPE_REGEX}, but is: cpe:2.3:/o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*'), - (ExternalPackageRefCategory.SECURITY, "advisory", "http://locatorurl", - f'externalPackageRef locator of type "advisory" must be a valid URL, but is: http://locatorurl'), - (ExternalPackageRefCategory.SECURITY, "fix", "http://fixurl", - f'externalPackageRef locator of type "fix" must be a valid URL, but is: http://fixurl'), - (ExternalPackageRefCategory.SECURITY, "url", "http://url", - f'externalPackageRef locator of type "url" must be a valid URL, but is: http://url'), - (ExternalPackageRefCategory.SECURITY, "swid", "2df9de35-0aff-4a86-ace6-f7dddd1ade4c", - f'externalPackageRef locator of type "swid" must be a valid URI with scheme swid, but is: 2df9de35-0aff-4a86-ace6-f7dddd1ade4c'), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "maven-central", - "org.apache.tomcat:tomcat:tomcat:9.0.0.M4", - f'externalPackageRef locator of type "maven-central" must conform with the regex {MAVEN_CENTRAL_REGEX}, but is: org.apache.tomcat:tomcat:tomcat:9.0.0.M4'), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "npm", "http-server:0.3.0", - f'externalPackageRef locator of type "npm" must conform with the regex {NPM_REGEX}, but is: http-server:0.3.0'), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "nuget", "Microsoft.AspNet.MVC@5.0.0", - f'externalPackageRef locator of type "nuget" must conform with the regex {NUGET_REGEX}, but is: Microsoft.AspNet.MVC@5.0.0'), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "bower", "modernizr:2.6.2", - f'externalPackageRef locator of type "bower" must conform with the regex {BOWER_REGEX}, but is: modernizr:2.6.2'), - (ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:npm@12.3.1", - f'externalPackageRef locator of type "purl" must conform with the regex {PURL_REGEX}, but is: pkg:npm@12.3.1'), - (ExternalPackageRefCategory.PERSISTENT_ID, "swh", - "swh:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2", - f'externalPackageRef locator of type "swh" must conform with the regex {SWH_REGEX}, but is: swh:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2'), - (ExternalPackageRefCategory.PERSISTENT_ID, "gitoid", - "gitoid:blob:sha1:3557f7eb43c621c71483743d4b37059bb80933e7f71277c0c3b3846159d1f61c", - f'externalPackageRef locator of type "gitoid" must conform with the regex {GITOID_REGEX}, but is: gitoid:blob:sha1:3557f7eb43c621c71483743d4b37059bb80933e7f71277c0c3b3846159d1f61c'), - (ExternalPackageRefCategory.PERSISTENT_ID, "gitoid", - "gitoid:blob:sha256:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64", - f'externalPackageRef locator of type "gitoid" must conform with the regex {GITOID_REGEX}, but is: gitoid:blob:sha256:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64'), - (ExternalPackageRefCategory.OTHER, "id string", "locator string", - "externalPackageRef locator in category OTHER must contain no spaces, but is: locator string"), - ]) +@pytest.mark.parametrize( + "category, reference_type, locator, expected_message", + [ + ( + ExternalPackageRefCategory.SECURITY, + "cpe22Type", + "cpe:o:canonical:ubuntu_linux:10.04:-:lts", + f'externalPackageRef locator of type "cpe22Type" must conform with the regex {CPE22TYPE_REGEX}, but is: cpe:o:canonical:ubuntu_linux:10.04:-:lts', + ), + ( + ExternalPackageRefCategory.SECURITY, + "cpe23Type", + "cpe:2.3:/o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*", + f'externalPackageRef locator of type "cpe23Type" must conform with the regex {CPE23TYPE_REGEX}, but is: cpe:2.3:/o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*', + ), + ( + ExternalPackageRefCategory.SECURITY, + "advisory", + "http://locatorurl", + f'externalPackageRef locator of type "advisory" must be a valid URL, but is: http://locatorurl', + ), + ( + ExternalPackageRefCategory.SECURITY, + "fix", + "http://fixurl", + f'externalPackageRef locator of type "fix" must be a valid URL, but is: http://fixurl', + ), + ( + ExternalPackageRefCategory.SECURITY, + "url", + "http://url", + f'externalPackageRef locator of type "url" must be a valid URL, but is: http://url', + ), + ( + ExternalPackageRefCategory.SECURITY, + "swid", + "2df9de35-0aff-4a86-ace6-f7dddd1ade4c", + f'externalPackageRef locator of type "swid" must be a valid URI with scheme swid, but is: 2df9de35-0aff-4a86-ace6-f7dddd1ade4c', + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "maven-central", + "org.apache.tomcat:tomcat:tomcat:9.0.0.M4", + f'externalPackageRef locator of type "maven-central" must conform with the regex {MAVEN_CENTRAL_REGEX}, but is: org.apache.tomcat:tomcat:tomcat:9.0.0.M4', + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "npm", + "http-server:0.3.0", + f'externalPackageRef locator of type "npm" must conform with the regex {NPM_REGEX}, but is: http-server:0.3.0', + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "nuget", + "Microsoft.AspNet.MVC@5.0.0", + f'externalPackageRef locator of type "nuget" must conform with the regex {NUGET_REGEX}, but is: Microsoft.AspNet.MVC@5.0.0', + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "bower", + "modernizr:2.6.2", + f'externalPackageRef locator of type "bower" must conform with the regex {BOWER_REGEX}, but is: modernizr:2.6.2', + ), + ( + ExternalPackageRefCategory.PACKAGE_MANAGER, + "purl", + "pkg:npm@12.3.1", + f'externalPackageRef locator of type "purl" must conform with the regex {PURL_REGEX}, but is: pkg:npm@12.3.1', + ), + ( + ExternalPackageRefCategory.PERSISTENT_ID, + "swh", + "swh:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2", + f'externalPackageRef locator of type "swh" must conform with the regex {SWH_REGEX}, but is: swh:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2', + ), + ( + ExternalPackageRefCategory.PERSISTENT_ID, + "gitoid", + "gitoid:blob:sha1:3557f7eb43c621c71483743d4b37059bb80933e7f71277c0c3b3846159d1f61c", + f'externalPackageRef locator of type "gitoid" must conform with the regex {GITOID_REGEX}, but is: gitoid:blob:sha1:3557f7eb43c621c71483743d4b37059bb80933e7f71277c0c3b3846159d1f61c', + ), + ( + ExternalPackageRefCategory.PERSISTENT_ID, + "gitoid", + "gitoid:blob:sha256:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64", + f'externalPackageRef locator of type "gitoid" must conform with the regex {GITOID_REGEX}, but is: gitoid:blob:sha256:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64', + ), + ( + ExternalPackageRefCategory.OTHER, + "id string", + "locator string", + "externalPackageRef locator in category OTHER must contain no spaces, but is: locator string", + ), + ], +) def test_invalid_external_package_ref_locators(category, reference_type, locator, expected_message): external_package_ref = ExternalPackageRef(category, reference_type, locator, "externalPackageRef comment") parent_id = "SPDXRef-Package" - validation_messages: List[ValidationMessage] = validate_external_package_ref(external_package_ref, parent_id, - "SPDX-2.3") + validation_messages: List[ValidationMessage] = validate_external_package_ref( + external_package_ref, parent_id, "SPDX-2.3" + ) - expected = ValidationMessage(expected_message, - ValidationContext(parent_id=parent_id, - element_type=SpdxElementType.EXTERNAL_PACKAGE_REF, - full_element=external_package_ref)) + expected = ValidationMessage( + expected_message, + ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.EXTERNAL_PACKAGE_REF, full_element=external_package_ref + ), + ) assert validation_messages == [expected] -@pytest.mark.parametrize("category, reference_type, locator", - [(ExternalPackageRefCategory.SECURITY, "advisory", - "https://nvd.nist.gov/vuln/detail/CVE-2020-28498"), - (ExternalPackageRefCategory.SECURITY, "fix", - "https://github.com/indutny/elliptic/commit/441b7428"), - (ExternalPackageRefCategory.SECURITY, "url", - "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/secp256k1_twist_attacks.md"), - (ExternalPackageRefCategory.SECURITY, "swid", "swid:2df9de35-0aff-4a86-ace6-f7dddd1ade4c") - ]) +@pytest.mark.parametrize( + "category, reference_type, locator", + [ + (ExternalPackageRefCategory.SECURITY, "advisory", "https://nvd.nist.gov/vuln/detail/CVE-2020-28498"), + (ExternalPackageRefCategory.SECURITY, "fix", "https://github.com/indutny/elliptic/commit/441b7428"), + ( + ExternalPackageRefCategory.SECURITY, + "url", + "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/secp256k1_twist_attacks.md", + ), + (ExternalPackageRefCategory.SECURITY, "swid", "swid:2df9de35-0aff-4a86-ace6-f7dddd1ade4c"), + ], +) def test_v2_3only_external_package_ref_types(category, reference_type, locator): external_package_ref = ExternalPackageRef(category, reference_type, locator, "externalPackageRef comment") parent_id = "SPDXRef-Package" - validation_messages: List[ValidationMessage] = validate_external_package_ref(external_package_ref, parent_id, - "SPDX-2.2") + validation_messages: List[ValidationMessage] = validate_external_package_ref( + external_package_ref, parent_id, "SPDX-2.2" + ) - expected = ValidationMessage(f'externalPackageRef type "{reference_type}" is not supported in SPDX-2.2', - ValidationContext(parent_id=parent_id, - element_type=SpdxElementType.EXTERNAL_PACKAGE_REF, - full_element=external_package_ref)) + expected = ValidationMessage( + f'externalPackageRef type "{reference_type}" is not supported in SPDX-2.2', + ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.EXTERNAL_PACKAGE_REF, full_element=external_package_ref + ), + ) assert validation_messages == [expected] diff --git a/tests/spdx/validation/test_extracted_licensing_info_validator.py b/tests/spdx/validation/test_extracted_licensing_info_validator.py index 00b2b255e..ce82f0626 100644 --- a/tests/spdx/validation/test_extracted_licensing_info_validator.py +++ b/tests/spdx/validation/test_extracted_licensing_info_validator.py @@ -26,17 +26,27 @@ def test_valid_extracted_licensing_info(): # TODO: tests for licenses not on the SPDX License list (i.e. they must provide id, name and cross-references) -@pytest.mark.parametrize("extracted_licensing_info, expected_message", - [(extracted_licensing_info_fixture(extracted_text=None), - 'extracted_text must be provided if there is a license_id assigned'), - (extracted_licensing_info_fixture(cross_references=["invalid_url"]), - 'cross_reference must be a valid URL, but is: invalid_url') - ]) +@pytest.mark.parametrize( + "extracted_licensing_info, expected_message", + [ + ( + extracted_licensing_info_fixture(extracted_text=None), + "extracted_text must be provided if there is a license_id assigned", + ), + ( + extracted_licensing_info_fixture(cross_references=["invalid_url"]), + "cross_reference must be a valid URL, but is: invalid_url", + ), + ], +) def test_invalid_extracted_licensing_info(extracted_licensing_info, expected_message): validation_messages: List[ValidationMessage] = validate_extracted_licensing_info(extracted_licensing_info) - expected = ValidationMessage(expected_message, - ValidationContext(element_type=SpdxElementType.EXTRACTED_LICENSING_INFO, - full_element=extracted_licensing_info)) + expected = ValidationMessage( + expected_message, + ValidationContext( + element_type=SpdxElementType.EXTRACTED_LICENSING_INFO, full_element=extracted_licensing_info + ), + ) assert validation_messages == [expected] diff --git a/tests/spdx/validation/test_file_validator.py b/tests/spdx/validation/test_file_validator.py index e71423b15..5caedeee9 100644 --- a/tests/spdx/validation/test_file_validator.py +++ b/tests/spdx/validation/test_file_validator.py @@ -27,23 +27,35 @@ def test_valid_file(): assert validation_messages == [] -@pytest.mark.parametrize("file_input, spdx_id, expected_message", - [(file_fixture(name="/invalid/file/name"), file_fixture().spdx_id, - f'file name must not be an absolute path starting with "/", but is: /invalid/file/name'), - ( - file_fixture(checksums=[Checksum(ChecksumAlgorithm.MD2, "d4c41ce30a517d6ce9d79c8c17bb4b66")]), - file_fixture().spdx_id, - f'checksums must contain a SHA1 algorithm checksum, but only contains: []') - ]) +@pytest.mark.parametrize( + "file_input, spdx_id, expected_message", + [ + ( + file_fixture(name="/invalid/file/name"), + file_fixture().spdx_id, + f'file name must not be an absolute path starting with "/", but is: /invalid/file/name', + ), + ( + file_fixture(checksums=[Checksum(ChecksumAlgorithm.MD2, "d4c41ce30a517d6ce9d79c8c17bb4b66")]), + file_fixture().spdx_id, + f"checksums must contain a SHA1 algorithm checksum, but only contains: []", + ), + ], +) def test_invalid_file(file_input, spdx_id, expected_message): - validation_messages: List[ValidationMessage] = validate_file_within_document(file_input, "SPDX-2.3", - document_fixture()) - - expected = ValidationMessage(expected_message, - ValidationContext(spdx_id=spdx_id, - parent_id=document_fixture().creation_info.spdx_id, - element_type=SpdxElementType.FILE, - full_element=file_input)) + validation_messages: List[ValidationMessage] = validate_file_within_document( + file_input, "SPDX-2.3", document_fixture() + ) + + expected = ValidationMessage( + expected_message, + ValidationContext( + spdx_id=spdx_id, + parent_id=document_fixture().creation_info.spdx_id, + element_type=SpdxElementType.FILE, + full_element=file_input, + ), + ) assert validation_messages == [expected] diff --git a/tests/spdx/validation/test_license_expression_validator.py b/tests/spdx/validation/test_license_expression_validator.py index c0ca3d5c7..579f0f2c0 100644 --- a/tests/spdx/validation/test_license_expression_validator.py +++ b/tests/spdx/validation/test_license_expression_validator.py @@ -25,14 +25,20 @@ FIXTURE_LICENSE_ID = extracted_licensing_info_fixture().license_id -@pytest.mark.parametrize("expression_string", - ["MIT", FIXTURE_LICENSE_ID, - f"GPL-2.0-only with GPL-CC-1.0 and {FIXTURE_LICENSE_ID} with 389-exception or Beerware"]) +@pytest.mark.parametrize( + "expression_string", + [ + "MIT", + FIXTURE_LICENSE_ID, + f"GPL-2.0-only with GPL-CC-1.0 and {FIXTURE_LICENSE_ID} with 389-exception or Beerware", + ], +) def test_valid_license_expression(expression_string): document: Document = document_fixture() license_expression: LicenseExpression = get_spdx_licensing().parse(expression_string) - validation_messages: List[ValidationMessage] = validate_license_expression(license_expression, document, - parent_id="SPDXRef-File") + validation_messages: List[ValidationMessage] = validate_license_expression( + license_expression, document, parent_id="SPDXRef-File" + ) assert validation_messages == [] @@ -40,62 +46,88 @@ def test_valid_license_expression(expression_string): @pytest.mark.parametrize("expression", [SpdxNone(), SpdxNoAssertion()]) def test_none_and_no_assertion(expression): document: Document = document_fixture() - validation_messages: List[ValidationMessage] = validate_license_expression(expression, document, - parent_id="SPDXRef-File") + validation_messages: List[ValidationMessage] = validate_license_expression( + expression, document, parent_id="SPDXRef-File" + ) assert validation_messages == [] -@pytest.mark.parametrize("expression_list", - [[SpdxNone()], [SpdxNoAssertion()], - [get_spdx_licensing().parse("MIT and GPL-3.0-only"), - get_spdx_licensing().parse(FIXTURE_LICENSE_ID)], - [SpdxNone(), get_spdx_licensing().parse("MIT"), SpdxNoAssertion()] - ]) +@pytest.mark.parametrize( + "expression_list", + [ + [SpdxNone()], + [SpdxNoAssertion()], + [get_spdx_licensing().parse("MIT and GPL-3.0-only"), get_spdx_licensing().parse(FIXTURE_LICENSE_ID)], + [SpdxNone(), get_spdx_licensing().parse("MIT"), SpdxNoAssertion()], + ], +) def test_valid_license_expressions(expression_list): document: Document = document_fixture() - validation_messages: List[ValidationMessage] = validate_license_expressions(expression_list, document, - parent_id="SPDXRef-File") + validation_messages: List[ValidationMessage] = validate_license_expressions( + expression_list, document, parent_id="SPDXRef-File" + ) assert validation_messages == [] -@pytest.mark.parametrize("expression_string, unknown_symbols", - [(f"{FIXTURE_LICENSE_ID} or LicenseRef-22", ["LicenseRef-22"]), - ("nope with 389-exception and _.- or LicenseRef-10", ["nope", "_.-", "LicenseRef-10"]) - ]) +@pytest.mark.parametrize( + "expression_string, unknown_symbols", + [ + (f"{FIXTURE_LICENSE_ID} or LicenseRef-22", ["LicenseRef-22"]), + ("nope with 389-exception and _.- or LicenseRef-10", ["nope", "_.-", "LicenseRef-10"]), + ], +) def test_invalid_license_expression_with_unknown_symbols(expression_string, unknown_symbols): document: Document = document_fixture() license_expression: LicenseExpression = get_spdx_licensing().parse(expression_string) parent_id = "SPDXRef-File" - context = ValidationContext(parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, - full_element=license_expression) + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expression + ) validation_messages: List[ValidationMessage] = validate_license_expression(license_expression, document, parent_id) - expected_messages = [ValidationMessage( - f"Unrecognized license reference: {symbol}. license_expression must only use IDs from the license list or extracted licensing info, but is: {license_expression}", - context - ) for symbol in unknown_symbols] + expected_messages = [ + ValidationMessage( + f"Unrecognized license reference: {symbol}. license_expression must only use IDs from the license list or extracted licensing info, but is: {license_expression}", + context, + ) + for symbol in unknown_symbols + ] TestCase().assertCountEqual(validation_messages, expected_messages) -@pytest.mark.parametrize("expression_string, expected_message", - [("MIT with MIT", - 'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "MIT" at position: 9. for license_expression: MIT WITH MIT'), - (f"GPL-2.0-or-later and {FIXTURE_LICENSE_ID} with {FIXTURE_LICENSE_ID}", - f'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "{FIXTURE_LICENSE_ID}" at position: 39. for license_expression: GPL-2.0-or-later AND {FIXTURE_LICENSE_ID} WITH {FIXTURE_LICENSE_ID}'), - (f"GPL-2.0-or-later with MIT and {FIXTURE_LICENSE_ID} with GPL-2.0-or-later", - f'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "MIT" at position: 22. for license_expression: GPL-2.0-or-later WITH MIT AND {FIXTURE_LICENSE_ID} WITH GPL-2.0-or-later'), - ("389-exception with 389-exception", - 'A license exception symbol can only be used as an exception in a "WITH exception" statement. for token: "389-exception". for license_expression: 389-exception WITH 389-exception'), - ("389-exception with MIT", - 'A license exception symbol can only be used as an exception in a "WITH exception" statement. for token: "389-exception". for license_expression: 389-exception WITH MIT'), - ]) +@pytest.mark.parametrize( + "expression_string, expected_message", + [ + ( + "MIT with MIT", + 'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "MIT" at position: 9. for license_expression: MIT WITH MIT', + ), + ( + f"GPL-2.0-or-later and {FIXTURE_LICENSE_ID} with {FIXTURE_LICENSE_ID}", + f'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "{FIXTURE_LICENSE_ID}" at position: 39. for license_expression: GPL-2.0-or-later AND {FIXTURE_LICENSE_ID} WITH {FIXTURE_LICENSE_ID}', + ), + ( + f"GPL-2.0-or-later with MIT and {FIXTURE_LICENSE_ID} with GPL-2.0-or-later", + f'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "MIT" at position: 22. for license_expression: GPL-2.0-or-later WITH MIT AND {FIXTURE_LICENSE_ID} WITH GPL-2.0-or-later', + ), + ( + "389-exception with 389-exception", + 'A license exception symbol can only be used as an exception in a "WITH exception" statement. for token: "389-exception". for license_expression: 389-exception WITH 389-exception', + ), + ( + "389-exception with MIT", + 'A license exception symbol can only be used as an exception in a "WITH exception" statement. for token: "389-exception". for license_expression: 389-exception WITH MIT', + ), + ], +) def test_invalid_license_expression_with_invalid_exceptions(expression_string, expected_message): document: Document = document_fixture() license_expression: LicenseExpression = get_spdx_licensing().parse(expression_string) parent_id = "SPDXRef-File" - context = ValidationContext(parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, - full_element=license_expression) + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expression + ) validation_messages: List[ValidationMessage] = validate_license_expression(license_expression, document, parent_id) expected_messages = [ValidationMessage(expected_message, context)] diff --git a/tests/spdx/validation/test_package_validator.py b/tests/spdx/validation/test_package_validator.py index 565b01c57..58e021b4a 100644 --- a/tests/spdx/validation/test_package_validator.py +++ b/tests/spdx/validation/test_package_validator.py @@ -25,62 +25,92 @@ def test_valid_package(): package = package_fixture() - validation_messages: List[ValidationMessage] = validate_package_within_document(package, "SPDX-2.3", - document_fixture()) + validation_messages: List[ValidationMessage] = validate_package_within_document( + package, "SPDX-2.3", document_fixture() + ) assert validation_messages == [] -@pytest.mark.parametrize("package_input, expected_message", - [(package_fixture(files_analyzed=False, verification_code=package_verification_code_fixture(), - license_info_from_files=[]), - f'verification_code must be None if files_analyzed is False, but is: {package_verification_code_fixture()}'), - (package_fixture(files_analyzed=False, license_info_from_files=[SpdxNone()], - verification_code=None), - 'license_info_from_files must be None if files_analyzed is False, but is: [NONE]'), - (package_fixture(files_analyzed=False, license_info_from_files=[SpdxNoAssertion()], - verification_code=None), - 'license_info_from_files must be None if files_analyzed is False, but is: [NOASSERTION]'), - (package_fixture(files_analyzed=False, - license_info_from_files=[Licensing().parse("some_license")], - verification_code=None), - "license_info_from_files must be None if files_analyzed is False, but is: [LicenseSymbol('some_license', " - "is_exception=False)]") - ]) +@pytest.mark.parametrize( + "package_input, expected_message", + [ + ( + package_fixture( + files_analyzed=False, verification_code=package_verification_code_fixture(), license_info_from_files=[] + ), + f"verification_code must be None if files_analyzed is False, but is: {package_verification_code_fixture()}", + ), + ( + package_fixture(files_analyzed=False, license_info_from_files=[SpdxNone()], verification_code=None), + "license_info_from_files must be None if files_analyzed is False, but is: [NONE]", + ), + ( + package_fixture(files_analyzed=False, license_info_from_files=[SpdxNoAssertion()], verification_code=None), + "license_info_from_files must be None if files_analyzed is False, but is: [NOASSERTION]", + ), + ( + package_fixture( + files_analyzed=False, + license_info_from_files=[Licensing().parse("some_license")], + verification_code=None, + ), + "license_info_from_files must be None if files_analyzed is False, but is: [LicenseSymbol('some_license', " + "is_exception=False)]", + ), + ], +) def test_invalid_package(package_input, expected_message): - validation_messages: List[ValidationMessage] = validate_package_within_document(package_input, "SPDX-2.3", - document_fixture(relationships=[])) - - expected = ValidationMessage(expected_message, - ValidationContext(spdx_id=package_input.spdx_id, parent_id="SPDXRef-DOCUMENT", - element_type=SpdxElementType.PACKAGE, - full_element=package_input)) + validation_messages: List[ValidationMessage] = validate_package_within_document( + package_input, "SPDX-2.3", document_fixture(relationships=[]) + ) + + expected = ValidationMessage( + expected_message, + ValidationContext( + spdx_id=package_input.spdx_id, + parent_id="SPDXRef-DOCUMENT", + element_type=SpdxElementType.PACKAGE, + full_element=package_input, + ), + ) assert validation_messages == [expected] -@pytest.mark.parametrize("relationships", - [[Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File1")], - [Relationship("SPDXRef-Package", RelationshipType.CONTAINS, - "DocumentRef-external:SPDXRef-File")], - [Relationship("SPDXRef-File2", RelationshipType.CONTAINED_BY, "SPDXRef-Package")], - [Relationship("DocumentRef-external:SPDXRef-File", RelationshipType.CONTAINED_BY, - "SPDXRef-Package")], - [Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File2"), - Relationship("SPDXRef-File1", RelationshipType.CONTAINED_BY, "SPDXRef-Package")]]) +@pytest.mark.parametrize( + "relationships", + [ + [Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File1")], + [Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "DocumentRef-external:SPDXRef-File")], + [Relationship("SPDXRef-File2", RelationshipType.CONTAINED_BY, "SPDXRef-Package")], + [Relationship("DocumentRef-external:SPDXRef-File", RelationshipType.CONTAINED_BY, "SPDXRef-Package")], + [ + Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File2"), + Relationship("SPDXRef-File1", RelationshipType.CONTAINED_BY, "SPDXRef-Package"), + ], + ], +) def test_invalid_package_with_contains(relationships): - document = document_fixture(relationships=relationships, - files=[file_fixture(spdx_id="SPDXRef-File1"), file_fixture(spdx_id="SPDXRef-File2")]) + document = document_fixture( + relationships=relationships, + files=[file_fixture(spdx_id="SPDXRef-File1"), file_fixture(spdx_id="SPDXRef-File2")], + ) package = package_fixture(files_analyzed=False, verification_code=None, license_info_from_files=[]) - context = ValidationContext(spdx_id=package.spdx_id, parent_id=document.creation_info.spdx_id, - element_type=SpdxElementType.PACKAGE, - full_element=package) + context = ValidationContext( + spdx_id=package.spdx_id, + parent_id=document.creation_info.spdx_id, + element_type=SpdxElementType.PACKAGE, + full_element=package, + ) validation_messages: List[ValidationMessage] = validate_package_within_document(package, "SPDX-2.3", document) assert validation_messages == [ - ValidationMessage(f"package must contain no elements if files_analyzed is False, but found {relationships}", - context)] + ValidationMessage( + f"package must contain no elements if files_analyzed is False, but found {relationships}", context + ) + ] def test_v2_3only_fields(): @@ -95,8 +125,15 @@ def test_v2_3only_fields(): def test_v2_2mandatory_fields(): - package = package_fixture(license_concluded=None, license_declared=None, copyright_text=None, - primary_package_purpose=None, built_date=None, release_date=None, valid_until_date=None) + package = package_fixture( + license_concluded=None, + license_declared=None, + copyright_text=None, + primary_package_purpose=None, + built_date=None, + release_date=None, + valid_until_date=None, + ) assert validate_package(package, "SPDX-2.3") == [] diff --git a/tests/spdx/validation/test_package_verification_code_validator.py b/tests/spdx/validation/test_package_verification_code_validator.py index 16c1eea02..963eb29a8 100644 --- a/tests/spdx/validation/test_package_verification_code_validator.py +++ b/tests/spdx/validation/test_package_verification_code_validator.py @@ -23,19 +23,28 @@ def test_valid_package_verification_code(): assert validation_messages == [] -@pytest.mark.parametrize("code, expected_message", - [(PackageVerificationCode("71c4025dd9897b364f3ebbb42c484ff43d00791cab", []), - "value of verification_code must consist of 40 lowercase hexadecimal digits, but is: 71c4025dd9897b364f3ebbb42c484ff43d00791cab (length: 42 digits)"), - (PackageVerificationCode("CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4", []), - "value of verification_code must consist of 40 lowercase hexadecimal digits, but is: CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4 (length: 40 digits)"), - (PackageVerificationCode("71c4025dd9897b364f3ebbb42c484ff43d00791c", - ["/invalid/excluded/file"]), - 'file name must not be an absolute path starting with "/", but is: /invalid/excluded/file') - ]) +@pytest.mark.parametrize( + "code, expected_message", + [ + ( + PackageVerificationCode("71c4025dd9897b364f3ebbb42c484ff43d00791cab", []), + "value of verification_code must consist of 40 lowercase hexadecimal digits, but is: 71c4025dd9897b364f3ebbb42c484ff43d00791cab (length: 42 digits)", + ), + ( + PackageVerificationCode("CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4", []), + "value of verification_code must consist of 40 lowercase hexadecimal digits, but is: CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4 (length: 40 digits)", + ), + ( + PackageVerificationCode("71c4025dd9897b364f3ebbb42c484ff43d00791c", ["/invalid/excluded/file"]), + 'file name must not be an absolute path starting with "/", but is: /invalid/excluded/file', + ), + ], +) def test_invalid_package_verification_code(code, expected_message): parent_id = "SPDXRef-Package" - context = ValidationContext(parent_id=parent_id, element_type=SpdxElementType.PACKAGE_VERIFICATION_CODE, - full_element=code) + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.PACKAGE_VERIFICATION_CODE, full_element=code + ) validation_messages = validate_verification_code(code, parent_id) assert validation_messages == [ValidationMessage(expected_message, context)] diff --git a/tests/spdx/validation/test_relationship_validator.py b/tests/spdx/validation/test_relationship_validator.py index 464fe6e61..83e8bc1a6 100644 --- a/tests/spdx/validation/test_relationship_validator.py +++ b/tests/spdx/validation/test_relationship_validator.py @@ -22,46 +22,66 @@ from tests.spdx.fixtures import document_fixture, relationship_fixture -@pytest.mark.parametrize("related_spdx_element", - ["SPDXRef-Package", SpdxNoAssertion(), SpdxNone()]) +@pytest.mark.parametrize("related_spdx_element", ["SPDXRef-Package", SpdxNoAssertion(), SpdxNone()]) def test_valid_relationship(related_spdx_element): - relationship = Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, related_spdx_element, comment="comment") + relationship = Relationship( + "SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, related_spdx_element, comment="comment" + ) validation_messages: List[ValidationMessage] = validate_relationship(relationship, "SPDX-2.3", document_fixture()) assert validation_messages == [] -@pytest.mark.parametrize("spdx_element_id, related_spdx_element_id, expected_message", - [("SPDXRef-unknownFile", "SPDXRef-File", - 'did not find the referenced spdx_id "SPDXRef-unknownFile" in the SPDX document'), - ("SPDXRef-File", "SPDXRef-unknownFile", - 'did not find the referenced spdx_id "SPDXRef-unknownFile" in the SPDX document'), - ]) +@pytest.mark.parametrize( + "spdx_element_id, related_spdx_element_id, expected_message", + [ + ( + "SPDXRef-unknownFile", + "SPDXRef-File", + 'did not find the referenced spdx_id "SPDXRef-unknownFile" in the SPDX document', + ), + ( + "SPDXRef-File", + "SPDXRef-unknownFile", + 'did not find the referenced spdx_id "SPDXRef-unknownFile" in the SPDX document', + ), + ], +) def test_unknown_spdx_id(spdx_element_id, related_spdx_element_id, expected_message): - relationship: Relationship = relationship_fixture(spdx_element_id=spdx_element_id, - related_spdx_element_id=related_spdx_element_id) + relationship: Relationship = relationship_fixture( + spdx_element_id=spdx_element_id, related_spdx_element_id=related_spdx_element_id + ) validation_messages: List[ValidationMessage] = validate_relationship(relationship, "SPDX-2.3", document_fixture()) - expected = ValidationMessage(expected_message, - ValidationContext(element_type=SpdxElementType.RELATIONSHIP, - full_element=relationship)) + expected = ValidationMessage( + expected_message, ValidationContext(element_type=SpdxElementType.RELATIONSHIP, full_element=relationship) + ) assert validation_messages == [expected] -@pytest.mark.parametrize("relationship, expected_message", - [(Relationship("SPDXRef-DOCUMENT", RelationshipType.SPECIFICATION_FOR, "SPDXRef-Package"), - "RelationshipType.SPECIFICATION_FOR is not supported in SPDX-2.2"), - (Relationship("SPDXRef-DOCUMENT", RelationshipType.REQUIREMENT_DESCRIPTION_FOR, - "SPDXRef-Package"), - "RelationshipType.REQUIREMENT_DESCRIPTION_FOR is not supported in SPDX-2.2")]) +@pytest.mark.parametrize( + "relationship, expected_message", + [ + ( + Relationship("SPDXRef-DOCUMENT", RelationshipType.SPECIFICATION_FOR, "SPDXRef-Package"), + "RelationshipType.SPECIFICATION_FOR is not supported in SPDX-2.2", + ), + ( + Relationship("SPDXRef-DOCUMENT", RelationshipType.REQUIREMENT_DESCRIPTION_FOR, "SPDXRef-Package"), + "RelationshipType.REQUIREMENT_DESCRIPTION_FOR is not supported in SPDX-2.2", + ), + ], +) def test_v2_3_only_types(relationship, expected_message): document: Document = document_fixture() validation_message: List[ValidationMessage] = validate_relationship(relationship, "SPDX-2.2", document) - expected = [ValidationMessage(expected_message, - ValidationContext(element_type=SpdxElementType.RELATIONSHIP, - full_element=relationship))] + expected = [ + ValidationMessage( + expected_message, ValidationContext(element_type=SpdxElementType.RELATIONSHIP, full_element=relationship) + ) + ] assert validation_message == expected diff --git a/tests/spdx/validation/test_snippet_validator.py b/tests/spdx/validation/test_snippet_validator.py index 764c68abe..5c9881653 100644 --- a/tests/spdx/validation/test_snippet_validator.py +++ b/tests/spdx/validation/test_snippet_validator.py @@ -21,31 +21,48 @@ def test_valid_snippet(): snippet = snippet_fixture() - validation_messages: List[ValidationMessage] = validate_snippet_within_document(snippet, "SPDX-2.3", - document_fixture()) + validation_messages: List[ValidationMessage] = validate_snippet_within_document( + snippet, "SPDX-2.3", document_fixture() + ) assert validation_messages == [] -@pytest.mark.parametrize("snippet_input, expected_message", - [(snippet_fixture(byte_range=(-12, 45)), - "byte_range values must be greater than or equal to 1, but is: (-12, 45)"), - (snippet_fixture(byte_range=(45, 23)), - "the first value of byte_range must be less than or equal to the second, but is: (45, 23)"), - (snippet_fixture(line_range=(-12, 45)), - "line_range values must be greater than or equal to 1, but is: (-12, 45)"), - (snippet_fixture(line_range=(45, 23)), - "the first value of line_range must be less than or equal to the second, but is: (45, 23)") - ]) +@pytest.mark.parametrize( + "snippet_input, expected_message", + [ + ( + snippet_fixture(byte_range=(-12, 45)), + "byte_range values must be greater than or equal to 1, but is: (-12, 45)", + ), + ( + snippet_fixture(byte_range=(45, 23)), + "the first value of byte_range must be less than or equal to the second, but is: (45, 23)", + ), + ( + snippet_fixture(line_range=(-12, 45)), + "line_range values must be greater than or equal to 1, but is: (-12, 45)", + ), + ( + snippet_fixture(line_range=(45, 23)), + "the first value of line_range must be less than or equal to the second, but is: (45, 23)", + ), + ], +) def test_invalid_ranges(snippet_input, expected_message): - validation_messages: List[ValidationMessage] = validate_snippet_within_document(snippet_input, "SPDX-2.3", - document_fixture()) - - expected = ValidationMessage(expected_message, - ValidationContext(spdx_id=snippet_input.spdx_id, - parent_id=document_fixture().creation_info.spdx_id, - element_type=SpdxElementType.SNIPPET, - full_element=snippet_input)) + validation_messages: List[ValidationMessage] = validate_snippet_within_document( + snippet_input, "SPDX-2.3", document_fixture() + ) + + expected = ValidationMessage( + expected_message, + ValidationContext( + spdx_id=snippet_input.spdx_id, + parent_id=document_fixture().creation_info.spdx_id, + element_type=SpdxElementType.SNIPPET, + full_element=snippet_input, + ), + ) assert validation_messages == [expected] diff --git a/tests/spdx/validation/test_spdx_id_validators.py b/tests/spdx/validation/test_spdx_id_validators.py index 4ee3a4c9c..12ca03f7e 100644 --- a/tests/spdx/validation/test_spdx_id_validators.py +++ b/tests/spdx/validation/test_spdx_id_validators.py @@ -29,16 +29,17 @@ snippet_fixture, ) -DOCUMENT = document_fixture(files=[file_fixture(spdx_id="SPDXRef-File1"), - file_fixture(spdx_id="SPDXRef-File2")], - packages=[package_fixture(spdx_id="SPDXRef-Package1"), - package_fixture(spdx_id="SPDXRef-Package2")], - snippets=[snippet_fixture(spdx_id="SPDXRef-Snippet1"), - snippet_fixture(spdx_id="SPDXRef-Snippet2")], - creation_info=creation_info_fixture( - external_document_refs=[ - external_document_ref_fixture(document_ref_id="DocumentRef-external"), - external_document_ref_fixture(document_ref_id="DocumentRef-1.2-ext")])) +DOCUMENT = document_fixture( + files=[file_fixture(spdx_id="SPDXRef-File1"), file_fixture(spdx_id="SPDXRef-File2")], + packages=[package_fixture(spdx_id="SPDXRef-Package1"), package_fixture(spdx_id="SPDXRef-Package2")], + snippets=[snippet_fixture(spdx_id="SPDXRef-Snippet1"), snippet_fixture(spdx_id="SPDXRef-Snippet2")], + creation_info=creation_info_fixture( + external_document_refs=[ + external_document_ref_fixture(document_ref_id="DocumentRef-external"), + external_document_ref_fixture(document_ref_id="DocumentRef-1.2-ext"), + ] + ), +) @pytest.mark.parametrize("spdx_id", ["SPDXRef-DOCUMENT", "SPDXRef-File1", "SPDXRef-1.3-3.7"]) @@ -46,8 +47,9 @@ def test_valid_internal_spdx_ids(spdx_id): assert is_valid_internal_spdx_id(spdx_id) -@pytest.mark.parametrize("spdx_id", - ["spdxId", "spdxRef-DOCUMENT", "SPDXRef.File", "SPDXRef#Snippet", "SPDXRef-1.3_3.7"]) +@pytest.mark.parametrize( + "spdx_id", ["spdxId", "spdxRef-DOCUMENT", "SPDXRef.File", "SPDXRef#Snippet", "SPDXRef-1.3_3.7"] +) def test_invalid_internal_spdx_ids(spdx_id): assert not is_valid_internal_spdx_id(spdx_id) @@ -57,8 +59,9 @@ def test_valid_external_doc_ref_ids(doc_ref_id): assert is_valid_external_doc_ref_id(doc_ref_id) -@pytest.mark.parametrize("doc_ref_id", - ["external-ref", "Documentref-external", "DocumentRef-...#", "DocumentRef-v0_4_2-alpha"]) +@pytest.mark.parametrize( + "doc_ref_id", ["external-ref", "Documentref-external", "DocumentRef-...#", "DocumentRef-v0_4_2-alpha"] +) def test_invalid_external_doc_ref_ids(doc_ref_id): assert not is_valid_external_doc_ref_id(doc_ref_id) @@ -77,43 +80,75 @@ def test_is_external_doc_ref_present_in_document(): def test_list_of_all_spdx_ids(): - TestCase().assertCountEqual(get_list_of_all_spdx_ids(DOCUMENT), - ["SPDXRef-DOCUMENT", "SPDXRef-File1", "SPDXRef-File2", "SPDXRef-Package1", - "SPDXRef-Package2", "SPDXRef-Snippet1", "SPDXRef-Snippet2"]) - - -@pytest.mark.parametrize("spdx_id", - ["DocumentRef-external:SPDXRef-File", "SPDXRef-Package"]) + TestCase().assertCountEqual( + get_list_of_all_spdx_ids(DOCUMENT), + [ + "SPDXRef-DOCUMENT", + "SPDXRef-File1", + "SPDXRef-File2", + "SPDXRef-Package1", + "SPDXRef-Package2", + "SPDXRef-Snippet1", + "SPDXRef-Snippet2", + ], + ) + + +@pytest.mark.parametrize("spdx_id", ["DocumentRef-external:SPDXRef-File", "SPDXRef-Package"]) def test_valid_spdx_id(spdx_id): validation_messages = validate_spdx_id(spdx_id, DOCUMENT) assert validation_messages == [] -@pytest.mark.parametrize("spdx_id, expected_messages", - [("DocumentRef-external:extern:SPDXRef-File", - [f"spdx_id must not contain more than one colon in order to separate the external document reference id from the internal SPDX id, but is: DocumentRef-external:extern:SPDXRef-File"]), - ("DocumentRef external:SPDXRef-File", - ['the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: DocumentRef external', - 'did not find the external document reference "DocumentRef external" in the SPDX document']), - ("DocRef-ext:SPDXRef-File_2", - ['the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: DocRef-ext', - 'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: SPDXRef-File_2', - 'did not find the external document reference "DocRef-ext" in the SPDX document']), - ("DocumentRef-external:SPDXRef-File_2", - ['the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: SPDXRef-File_2']), - ("SPDXRef-42+", - ['spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: SPDXRef-42+']) - ]) +@pytest.mark.parametrize( + "spdx_id, expected_messages", + [ + ( + "DocumentRef-external:extern:SPDXRef-File", + [ + f"spdx_id must not contain more than one colon in order to separate the external document reference id from the internal SPDX id, but is: DocumentRef-external:extern:SPDXRef-File" + ], + ), + ( + "DocumentRef external:SPDXRef-File", + [ + 'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: DocumentRef external', + 'did not find the external document reference "DocumentRef external" in the SPDX document', + ], + ), + ( + "DocRef-ext:SPDXRef-File_2", + [ + 'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: DocRef-ext', + 'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: SPDXRef-File_2', + 'did not find the external document reference "DocRef-ext" in the SPDX document', + ], + ), + ( + "DocumentRef-external:SPDXRef-File_2", + [ + 'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: SPDXRef-File_2' + ], + ), + ( + "SPDXRef-42+", + [ + 'spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: SPDXRef-42+' + ], + ), + ], +) def test_invalid_spdx_id(spdx_id, expected_messages): validation_messages = validate_spdx_id(spdx_id, DOCUMENT) TestCase().assertCountEqual(validation_messages, expected_messages) -@pytest.mark.parametrize("spdx_id", - ["DocumentRef-external:SPDXRef-File", "SPDXRef-DOCUMENT", "SPDXRef-File1", "SPDXRef-Package1", - "SPDXRef-Snippet1"]) +@pytest.mark.parametrize( + "spdx_id", + ["DocumentRef-external:SPDXRef-File", "SPDXRef-DOCUMENT", "SPDXRef-File1", "SPDXRef-Package1", "SPDXRef-Snippet1"], +) def test_valid_spdx_id_with_check_document(spdx_id): validation_messages = validate_spdx_id(spdx_id, DOCUMENT, check_document=True) assert validation_messages == [] @@ -124,8 +159,7 @@ def test_invalid_spdx_id_with_check_document(): assert validation_messages == ['did not find the referenced spdx_id "SPDXRef-Filet" in the SPDX document'] -@pytest.mark.parametrize("spdx_id", - ["DocumentRef-external:SPDXRef-File", "SPDXRef-File1"]) +@pytest.mark.parametrize("spdx_id", ["DocumentRef-external:SPDXRef-File", "SPDXRef-File1"]) def test_valid_spdx_id_with_check_files(spdx_id): validation_messages = validate_spdx_id(spdx_id, DOCUMENT, check_files=True) assert validation_messages == [] @@ -134,5 +168,5 @@ def test_valid_spdx_id_with_check_files(spdx_id): def test_invalid_spdx_id_with_check_files(): validation_messages = validate_spdx_id("SPDXRef-Package1", DOCUMENT, check_files=True) assert validation_messages == [ - 'did not find the referenced spdx_id "SPDXRef-Package1" in the SPDX document\'s files'] - + 'did not find the referenced spdx_id "SPDXRef-Package1" in the SPDX document\'s files' + ] diff --git a/tests/spdx/validation/test_uri_validators.py b/tests/spdx/validation/test_uri_validators.py index fe59b9b74..b4a641786 100644 --- a/tests/spdx/validation/test_uri_validators.py +++ b/tests/spdx/validation/test_uri_validators.py @@ -14,9 +14,15 @@ from spdx.validation.uri_validators import validate_download_location, validate_uri, validate_url -@pytest.mark.parametrize("input_value", ["https://some.url", - "https://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82...", - "http://some.url", "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz"]) +@pytest.mark.parametrize( + "input_value", + [ + "https://some.url", + "https://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82...", + "http://some.url", + "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + ], +) def test_valid_url(input_value): assert validate_url(input_value) == [] @@ -27,85 +33,107 @@ def test_invalid_url(input_value): assert validate_url(input_value) == [f"must be a valid URL, but is: {input_value}"] -@pytest.mark.parametrize("input_value", ["http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", - "git://git.myproject.org/MyProject", - "git+https://git.myproject.org/MyProject.git", - "git+http://git.myproject.org/MyProject", - "git+ssh://git.myproject.org/MyProject.git", - "git+git://git.myproject.org/MyProject", - "git+git@git.myproject.org:MyProject", - "git://git.myproject.org/MyProject#src/somefile.c", - "git+https://git.myproject.org/MyProject#src/Class.java", - "git://git.myproject.org/MyProject.git@master", - "git+https://git.myproject.org/MyProject.git@v1.0", - "git://git.myproject.org/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709", - "git+https://git.myproject.org/MyProject.git@master#/src/MyClass.cpp", - "git+https://git.myproject.org/MyProject@da39a3ee5e6b4b0d3255bfef95601890afd80709#lib/variable.rb", - "hg+http://hg.myproject.org/MyProject", - "hg+https://hg.myproject.org/MyProject", - "hg+ssh://hg.myproject.org/MyProject", - "hg+https://hg.myproject.org/MyProject#src/somefile.c", - "hg+https://hg.myproject.org/MyProject#src/Class.java", - "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b", - "hg+https://hg.myproject.org/MyProject@2019", - "hg+https://hg.myproject.org/MyProject@v1.0", - "hg+https://hg.myproject.org/MyProject@special_feature", - "hg+https://hg.myproject.org/MyProject@master#/src/MyClass.cpp", - "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b#lib/variable.rb", - "svn://svn.myproject.org/svn/MyProject", - "svn+svn://svn.myproject.org/svn/MyProject", - "svn+http://svn.myproject.org/svn/MyProject/trunk", - "svn+https://svn.myproject.org/svn/MyProject/trunk", - "svn+https://svn.myproject.org/MyProject#src/somefile.c", - "svn+https://svn.myproject.org/MyProject#src/Class.java", - "svn+https://svn.myproject.org/MyProject/trunk#src/somefile.c", - "svn+https://svn.myproject.org/MyProject/trunk/src/somefile.c", - "svn+https://svn.myproject.org/svn/MyProject/trunk@2019", - "svn+https://svn.myproject.org/MyProject@123#/src/MyClass.cpp", - "svn+https://svn.myproject.org/MyProject/trunk@1234#lib/variable/variable.rb", - "bzr+https://bzr.myproject.org/MyProject/trunk", - "bzr+http://bzr.myproject.org/MyProject/trunk", - "bzr+sftp://myproject.org/MyProject/trunk", - "bzr+ssh://myproject.org/MyProject/trunk", - "bzr+ftp://myproject.org/MyProject/trunk", - "bzr+lp:MyProject", - "bzr+https://bzr.myproject.org/MyProject/trunk#src/somefile.c", - "bzr+https://bzr.myproject.org/MyProject/trunk#src/Class.java", - "bzr+https://bzr.myproject.org/MyProject/trunk@2019", - "bzr+http://bzr.myproject.org/MyProject/trunk@v1.0", - "bzr+https://bzr.myproject.org/MyProject/trunk@2019#src/somefile.c", - ]) +@pytest.mark.parametrize( + "input_value", + [ + "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + "git://git.myproject.org/MyProject", + "git+https://git.myproject.org/MyProject.git", + "git+http://git.myproject.org/MyProject", + "git+ssh://git.myproject.org/MyProject.git", + "git+git://git.myproject.org/MyProject", + "git+git@git.myproject.org:MyProject", + "git://git.myproject.org/MyProject#src/somefile.c", + "git+https://git.myproject.org/MyProject#src/Class.java", + "git://git.myproject.org/MyProject.git@master", + "git+https://git.myproject.org/MyProject.git@v1.0", + "git://git.myproject.org/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709", + "git+https://git.myproject.org/MyProject.git@master#/src/MyClass.cpp", + "git+https://git.myproject.org/MyProject@da39a3ee5e6b4b0d3255bfef95601890afd80709#lib/variable.rb", + "hg+http://hg.myproject.org/MyProject", + "hg+https://hg.myproject.org/MyProject", + "hg+ssh://hg.myproject.org/MyProject", + "hg+https://hg.myproject.org/MyProject#src/somefile.c", + "hg+https://hg.myproject.org/MyProject#src/Class.java", + "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b", + "hg+https://hg.myproject.org/MyProject@2019", + "hg+https://hg.myproject.org/MyProject@v1.0", + "hg+https://hg.myproject.org/MyProject@special_feature", + "hg+https://hg.myproject.org/MyProject@master#/src/MyClass.cpp", + "hg+https://hg.myproject.org/MyProject@da39a3ee5e6b#lib/variable.rb", + "svn://svn.myproject.org/svn/MyProject", + "svn+svn://svn.myproject.org/svn/MyProject", + "svn+http://svn.myproject.org/svn/MyProject/trunk", + "svn+https://svn.myproject.org/svn/MyProject/trunk", + "svn+https://svn.myproject.org/MyProject#src/somefile.c", + "svn+https://svn.myproject.org/MyProject#src/Class.java", + "svn+https://svn.myproject.org/MyProject/trunk#src/somefile.c", + "svn+https://svn.myproject.org/MyProject/trunk/src/somefile.c", + "svn+https://svn.myproject.org/svn/MyProject/trunk@2019", + "svn+https://svn.myproject.org/MyProject@123#/src/MyClass.cpp", + "svn+https://svn.myproject.org/MyProject/trunk@1234#lib/variable/variable.rb", + "bzr+https://bzr.myproject.org/MyProject/trunk", + "bzr+http://bzr.myproject.org/MyProject/trunk", + "bzr+sftp://myproject.org/MyProject/trunk", + "bzr+ssh://myproject.org/MyProject/trunk", + "bzr+ftp://myproject.org/MyProject/trunk", + "bzr+lp:MyProject", + "bzr+https://bzr.myproject.org/MyProject/trunk#src/somefile.c", + "bzr+https://bzr.myproject.org/MyProject/trunk#src/Class.java", + "bzr+https://bzr.myproject.org/MyProject/trunk@2019", + "bzr+http://bzr.myproject.org/MyProject/trunk@v1.0", + "bzr+https://bzr.myproject.org/MyProject/trunk@2019#src/somefile.c", + ], +) def test_valid_package_download_location(input_value): assert validate_download_location(input_value) == [] # TODO: more negative examples: https://github.com/spdx/tools-python/issues/377 -@pytest.mark.parametrize("input_value", [":::::", ]) +@pytest.mark.parametrize( + "input_value", + [ + ":::::", + ], +) def test_invalid_package_download_location(input_value): assert validate_download_location(input_value) == [ - f"must be a valid download location according to the specification, but is: {input_value}"] - - -@pytest.mark.parametrize("input_value", ["https://some.uri", "http:////some", - "https://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82...", - "h://someweirdtest^?", "https://some.uri that goes on!?"]) + f"must be a valid download location according to the specification, but is: {input_value}" + ] + + +@pytest.mark.parametrize( + "input_value", + [ + "https://some.uri", + "http:////some", + "https://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82...", + "h://someweirdtest^?", + "https://some.uri that goes on!?", + ], +) def test_valid_uri(input_value): message = validate_uri(input_value) assert message == [] -@pytest.mark.parametrize("input_value", ["/invalid/uri", "http//uri", "http://some#uri", "some/uri", "some weird test"]) +@pytest.mark.parametrize( + "input_value", ["/invalid/uri", "http//uri", "http://some#uri", "some/uri", "some weird test"] +) def test_invalid_uri(input_value): message = validate_uri(input_value) - assert message == [f"must be a valid URI specified in RFC-3986 and must contain no fragment (#), but is: {input_value}"] + assert message == [ + f"must be a valid URI specified in RFC-3986 and must contain no fragment (#), but is: {input_value}" + ] @pytest.mark.parametrize("input_value", ["://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82..."]) @pytest.mark.skip( "validate_uri() seems to invalidate URIs without scheme, so it does not run into this case. But I'm not sure yet if this covers all scheme-less examples." - "https://github.com/spdx/tools-python/issues/377") + "https://github.com/spdx/tools-python/issues/377" +) def test_uri_without_scheme(input_value): message = validate_uri(input_value) diff --git a/tests/spdx/writer/json/test_json_writer.py b/tests/spdx/writer/json/test_json_writer.py index 2bfeb5aa5..aff0c9501 100644 --- a/tests/spdx/writer/json/test_json_writer.py +++ b/tests/spdx/writer/json/test_json_writer.py @@ -31,7 +31,7 @@ def test_write_json(temporary_file_path: str): with open(temporary_file_path) as written_file: written_json = json.load(written_file) - with open(os.path.join(os.path.dirname(__file__), 'expected_results', 'expected.json')) as expected_file: + with open(os.path.join(os.path.dirname(__file__), "expected_results", "expected.json")) as expected_file: expected_json = json.load(expected_file) assert written_json == expected_json diff --git a/tests/spdx/writer/rdf/test_checksum_writer.py b/tests/spdx/writer/rdf/test_checksum_writer.py index b2426a123..76560e8e4 100644 --- a/tests/spdx/writer/rdf/test_checksum_writer.py +++ b/tests/spdx/writer/rdf/test_checksum_writer.py @@ -29,27 +29,28 @@ def test_add_checksum_to_graph(): assert (None, SPDX_NAMESPACE.checksumValue, Literal(checksum.value)) in graph -@pytest.mark.parametrize("algorithm,expected", [(ChecksumAlgorithm.SHA1, SPDX_NAMESPACE.checksumAlgorithm_sha1), - (ChecksumAlgorithm.SHA224, SPDX_NAMESPACE.checksumAlgorithm_sha224), - (ChecksumAlgorithm.SHA256, SPDX_NAMESPACE.checksumAlgorithm_sha256), - (ChecksumAlgorithm.SHA384, SPDX_NAMESPACE.checksumAlgorithm_sha384), - (ChecksumAlgorithm.SHA512, SPDX_NAMESPACE.checksumAlgorithm_sha512), - (ChecksumAlgorithm.SHA3_256, SPDX_NAMESPACE.checksumAlgorithm_sha3_256), - (ChecksumAlgorithm.SHA3_384, SPDX_NAMESPACE.checksumAlgorithm_sha3_384), - (ChecksumAlgorithm.SHA3_512, SPDX_NAMESPACE.checksumAlgorithm_sha3_512), - (ChecksumAlgorithm.BLAKE2B_256, - SPDX_NAMESPACE.checksumAlgorithm_blake2b256), - (ChecksumAlgorithm.BLAKE2B_384, - SPDX_NAMESPACE.checksumAlgorithm_blake2b384), - (ChecksumAlgorithm.BLAKE2B_512, - SPDX_NAMESPACE.checksumAlgorithm_blake2b512), - (ChecksumAlgorithm.BLAKE3, SPDX_NAMESPACE.checksumAlgorithm_blake3), - (ChecksumAlgorithm.MD2, SPDX_NAMESPACE.checksumAlgorithm_md2), - (ChecksumAlgorithm.MD4, SPDX_NAMESPACE.checksumAlgorithm_md4), - (ChecksumAlgorithm.MD5, SPDX_NAMESPACE.checksumAlgorithm_md5), - (ChecksumAlgorithm.MD6, SPDX_NAMESPACE.checksumAlgorithm_md6), - (ChecksumAlgorithm.ADLER32, SPDX_NAMESPACE.checksumAlgorithm_adler32) - ]) +@pytest.mark.parametrize( + "algorithm,expected", + [ + (ChecksumAlgorithm.SHA1, SPDX_NAMESPACE.checksumAlgorithm_sha1), + (ChecksumAlgorithm.SHA224, SPDX_NAMESPACE.checksumAlgorithm_sha224), + (ChecksumAlgorithm.SHA256, SPDX_NAMESPACE.checksumAlgorithm_sha256), + (ChecksumAlgorithm.SHA384, SPDX_NAMESPACE.checksumAlgorithm_sha384), + (ChecksumAlgorithm.SHA512, SPDX_NAMESPACE.checksumAlgorithm_sha512), + (ChecksumAlgorithm.SHA3_256, SPDX_NAMESPACE.checksumAlgorithm_sha3_256), + (ChecksumAlgorithm.SHA3_384, SPDX_NAMESPACE.checksumAlgorithm_sha3_384), + (ChecksumAlgorithm.SHA3_512, SPDX_NAMESPACE.checksumAlgorithm_sha3_512), + (ChecksumAlgorithm.BLAKE2B_256, SPDX_NAMESPACE.checksumAlgorithm_blake2b256), + (ChecksumAlgorithm.BLAKE2B_384, SPDX_NAMESPACE.checksumAlgorithm_blake2b384), + (ChecksumAlgorithm.BLAKE2B_512, SPDX_NAMESPACE.checksumAlgorithm_blake2b512), + (ChecksumAlgorithm.BLAKE3, SPDX_NAMESPACE.checksumAlgorithm_blake3), + (ChecksumAlgorithm.MD2, SPDX_NAMESPACE.checksumAlgorithm_md2), + (ChecksumAlgorithm.MD4, SPDX_NAMESPACE.checksumAlgorithm_md4), + (ChecksumAlgorithm.MD5, SPDX_NAMESPACE.checksumAlgorithm_md5), + (ChecksumAlgorithm.MD6, SPDX_NAMESPACE.checksumAlgorithm_md6), + (ChecksumAlgorithm.ADLER32, SPDX_NAMESPACE.checksumAlgorithm_adler32), + ], +) def test_algorithm_to_rdf_string(algorithm, expected): rdf_element = algorithm_to_rdf_string(algorithm) diff --git a/tests/spdx/writer/rdf/test_external_document_ref_writer.py b/tests/spdx/writer/rdf/test_external_document_ref_writer.py index 673eb2873..6e6acf8f7 100644 --- a/tests/spdx/writer/rdf/test_external_document_ref_writer.py +++ b/tests/spdx/writer/rdf/test_external_document_ref_writer.py @@ -21,11 +21,12 @@ def test_add_external_document_ref_to_graph(): add_external_document_ref_to_graph(external_document_ref, graph, URIRef("docNode"), "docNamespace") - assert (URIRef("docNode"), SPDX_NAMESPACE.externalDocumentRef, URIRef("docNamespace#DocumentRef-external")) in graph + assert ( + URIRef("docNode"), + SPDX_NAMESPACE.externalDocumentRef, + URIRef("docNamespace#DocumentRef-external"), + ) in graph assert (None, RDF.type, SPDX_NAMESPACE.ExternalDocumentRef) in graph assert (None, SPDX_NAMESPACE.checksum, None) in graph assert (None, RDF.type, SPDX_NAMESPACE.Checksum) in graph assert (None, SPDX_NAMESPACE.spdxDocument, URIRef(external_document_ref.document_uri)) in graph - - - diff --git a/tests/spdx/writer/rdf/test_license_expression_writer.py b/tests/spdx/writer/rdf/test_license_expression_writer.py index c77641860..73152ee69 100644 --- a/tests/spdx/writer/rdf/test_license_expression_writer.py +++ b/tests/spdx/writer/rdf/test_license_expression_writer.py @@ -20,8 +20,9 @@ def test_add_conjunctive_license_set_to_graph(): graph = Graph() license_expression = get_spdx_licensing().parse("MIT AND GPL-2.0") - add_license_expression_to_graph(license_expression, graph, URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, - "https://namespace") + add_license_expression_to_graph( + license_expression, graph, URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, "https://namespace" + ) assert (URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, None) in graph assert (None, RDF.type, SPDX_NAMESPACE.ConjunctiveLicenseSet) in graph @@ -33,8 +34,9 @@ def test_add_disjunctive_license_set_to_graph(): graph = Graph() license_expression = get_spdx_licensing().parse("MIT OR GPL-2.0") - add_license_expression_to_graph(license_expression, graph, URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, - "https://namespace") + add_license_expression_to_graph( + license_expression, graph, URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, "https://namespace" + ) assert (URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, None) in graph assert (None, RDF.type, SPDX_NAMESPACE.DisjunctiveLicenseSet) in graph @@ -42,18 +44,23 @@ def test_add_disjunctive_license_set_to_graph(): assert (None, SPDX_NAMESPACE.member, URIRef("http://spdx.org/licenses/GPL-2.0-only")) in graph -@pytest.mark.parametrize("license_with_exception," - "expected_triple", [("MIT WITH openvpn-openssl-exception", - (URIRef("http://spdx.org/licenses/openvpn-openssl-exception"), RDF.type, - SPDX_NAMESPACE.LicenseException)), - ("MIT WITH unknown-exception", - (None, SPDX_NAMESPACE.licenseExceptionId, Literal("unknown-exception")))]) +@pytest.mark.parametrize( + "license_with_exception," "expected_triple", + [ + ( + "MIT WITH openvpn-openssl-exception", + (URIRef("http://spdx.org/licenses/openvpn-openssl-exception"), RDF.type, SPDX_NAMESPACE.LicenseException), + ), + ("MIT WITH unknown-exception", (None, SPDX_NAMESPACE.licenseExceptionId, Literal("unknown-exception"))), + ], +) def test_license_exception_to_graph(license_with_exception, expected_triple): graph = Graph() license_expression = get_spdx_licensing().parse(license_with_exception) - add_license_expression_to_graph(license_expression, graph, URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, - "https://namespace") + add_license_expression_to_graph( + license_expression, graph, URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, "https://namespace" + ) assert (URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, None) in graph assert (None, RDF.type, SPDX_NAMESPACE.WithExceptionOperator) in graph diff --git a/tests/spdx/writer/rdf/test_package_writer.py b/tests/spdx/writer/rdf/test_package_writer.py index b1f5ece06..bab01ff53 100644 --- a/tests/spdx/writer/rdf/test_package_writer.py +++ b/tests/spdx/writer/rdf/test_package_writer.py @@ -65,20 +65,34 @@ def test_add_package_verification_code_to_graph(): add_package_verification_code_to_graph(verification_code, graph, URIRef("docNamespace")) assert (None, RDF.type, SPDX_NAMESPACE.PackageVerificationCode) in graph - assert (None, SPDX_NAMESPACE.packageVerificationCodeValue, - Literal("85ed0817af83a24ad8da68c2b5094de69833983c")) in graph + assert ( + None, + SPDX_NAMESPACE.packageVerificationCodeValue, + Literal("85ed0817af83a24ad8da68c2b5094de69833983c"), + ) in graph assert (None, SPDX_NAMESPACE.packageVerificationCodeExcludedFile, Literal("./exclude.py")) in graph -@pytest.mark.parametrize("external_reference,ref_type,category", - [(external_package_ref_fixture(), URIRef("http://spdx.org/rdf/references/maven-central"), - SPDX_NAMESPACE.referenceCategory_packageManager), - (external_package_ref_fixture(locator="acmecorp/acmenator/4.1.3-alpha", - category=ExternalPackageRefCategory.OTHER, - reference_type="LocationRef-acmeforge", - comment="This is the external ref for Acme"), - URIRef("https://some.namespace#LocationRef-acmeforge"), - SPDX_NAMESPACE.referenceCategory_other)]) +@pytest.mark.parametrize( + "external_reference,ref_type,category", + [ + ( + external_package_ref_fixture(), + URIRef("http://spdx.org/rdf/references/maven-central"), + SPDX_NAMESPACE.referenceCategory_packageManager, + ), + ( + external_package_ref_fixture( + locator="acmecorp/acmenator/4.1.3-alpha", + category=ExternalPackageRefCategory.OTHER, + reference_type="LocationRef-acmeforge", + comment="This is the external ref for Acme", + ), + URIRef("https://some.namespace#LocationRef-acmeforge"), + SPDX_NAMESPACE.referenceCategory_other, + ), + ], +) def test_external_package_ref_to_graph(external_reference, ref_type, category): graph = Graph() doc_namespace = "https://some.namespace" diff --git a/tests/spdx/writer/rdf/test_relationship_writer.py b/tests/spdx/writer/rdf/test_relationship_writer.py index 74c576585..dc559caf0 100644 --- a/tests/spdx/writer/rdf/test_relationship_writer.py +++ b/tests/spdx/writer/rdf/test_relationship_writer.py @@ -20,7 +20,7 @@ def test_add_relationship_to_graph(): graph = Graph() add_relationship_to_graph(relationship, graph, "docNamespace", {}) - assert(URIRef("docNamespace#SPDXRef-DOCUMENT"), SPDX_NAMESPACE.relationship, None) in graph + assert (URIRef("docNamespace#SPDXRef-DOCUMENT"), SPDX_NAMESPACE.relationship, None) in graph assert (None, SPDX_NAMESPACE.relationshipType, SPDX_NAMESPACE.relationshipType_describes) in graph assert (None, SPDX_NAMESPACE.relatedSpdxElement, URIRef("docNamespace#SPDXRef-File")) in graph assert (None, RDFS.comment, Literal(relationship.comment)) in graph diff --git a/tests/spdx/writer/rdf/test_snippet_writer.py b/tests/spdx/writer/rdf/test_snippet_writer.py index 4dcf539a3..53c493ded 100644 --- a/tests/spdx/writer/rdf/test_snippet_writer.py +++ b/tests/spdx/writer/rdf/test_snippet_writer.py @@ -35,9 +35,13 @@ def test_add_snippet_to_graph(): assert (None, RDFS.comment, Literal(snippet.comment)) in graph -@pytest.mark.parametrize("range,pointer,predicate", - [((5, 190), POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), - ((1, 3), POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber)]) +@pytest.mark.parametrize( + "range,pointer,predicate", + [ + ((5, 190), POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), + ((1, 3), POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), + ], +) def test_add_ranges_to_graph(range, pointer, predicate): graph = Graph() add_range_to_graph(range, graph, URIRef("snippetNode"), URIRef("docNamespace#SPDXRef-File"), pointer) diff --git a/tests/spdx/writer/rdf/test_writer_utils.py b/tests/spdx/writer/rdf/test_writer_utils.py index 258fa3788..aa74c570f 100644 --- a/tests/spdx/writer/rdf/test_writer_utils.py +++ b/tests/spdx/writer/rdf/test_writer_utils.py @@ -13,12 +13,20 @@ from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id -@pytest.mark.parametrize("spdx_id,namespace,external_namespaces,expected", - [("SPDXRef-File", "docNamespace", {}, "docNamespace#SPDXRef-File"), - ("externalDoc:SPDXRef-File", "docNamespace", {"externalDoc": "externalNamespace"}, - "externalNamespace#SPDXRef-File"), - ("externalDoc#A-Ref", "", {}, "externalDoc#A-Ref"), - ("externalDoc:A-Ref", "", {}, "externalDoc:A-Ref")]) +@pytest.mark.parametrize( + "spdx_id,namespace,external_namespaces,expected", + [ + ("SPDXRef-File", "docNamespace", {}, "docNamespace#SPDXRef-File"), + ( + "externalDoc:SPDXRef-File", + "docNamespace", + {"externalDoc": "externalNamespace"}, + "externalNamespace#SPDXRef-File", + ), + ("externalDoc#A-Ref", "", {}, "externalDoc#A-Ref"), + ("externalDoc:A-Ref", "", {}, "externalDoc:A-Ref"), + ], +) def test_add_namespace_to_spdx_id(spdx_id, namespace, expected, external_namespaces): extended_spdx_id = add_namespace_to_spdx_id(spdx_id, namespace, external_namespaces) diff --git a/tests/spdx/writer/tagvalue/test_creation_info_writer.py b/tests/spdx/writer/tagvalue/test_creation_info_writer.py index 54bd7821f..e54879ee6 100644 --- a/tests/spdx/writer/tagvalue/test_creation_info_writer.py +++ b/tests/spdx/writer/tagvalue/test_creation_info_writer.py @@ -11,27 +11,53 @@ from tests.spdx.fixtures import actor_fixture, creation_info_fixture -@pytest.mark.parametrize("creation_info, expected_calls", - [(creation_info_fixture(), [call("SPDXVersion: SPDX-2.3\n"), call("DataLicense: CC0-1.0\n"), - call("SPDXID: SPDXRef-DOCUMENT\n"), - call("DocumentName: documentName\n"), - call("DocumentNamespace: https://some.namespace\n"), - call("DocumentComment: documentComment\n"), - call("\n## External Document References\n"), call( - "ExternalDocumentRef: DocumentRef-external https://namespace.com SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), - call("\n"), call("## Creation Information\n"), - call("LicenseListVersion: 3.19\n"), - call("Creator: Person: creatorName (some@mail.com)\n"), - call("Created: 2022-12-01T00:00:00Z\n"), - call("CreatorComment: creatorComment\n")]), - (CreationInfo(spdx_version="SPDX-2.3", spdx_id="SPDXRef-DOCUMENT", creators=[actor_fixture()], - name="Test document", document_namespace="https://namespace.com", - created=datetime.datetime(2022, 3, 10)), - [call("SPDXVersion: SPDX-2.3\n"), call("DataLicense: CC0-1.0\n"), - call("SPDXID: SPDXRef-DOCUMENT\n"), call("DocumentName: Test document\n"), - call("DocumentNamespace: https://namespace.com\n"), call("\n"), - call("## Creation Information\n"), call("Creator: Person: actorName (some@mail.com)\n"), - call("Created: 2022-03-10T00:00:00Z\n")])]) +@pytest.mark.parametrize( + "creation_info, expected_calls", + [ + ( + creation_info_fixture(), + [ + call("SPDXVersion: SPDX-2.3\n"), + call("DataLicense: CC0-1.0\n"), + call("SPDXID: SPDXRef-DOCUMENT\n"), + call("DocumentName: documentName\n"), + call("DocumentNamespace: https://some.namespace\n"), + call("DocumentComment: documentComment\n"), + call("\n## External Document References\n"), + call( + "ExternalDocumentRef: DocumentRef-external https://namespace.com SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n" + ), + call("\n"), + call("## Creation Information\n"), + call("LicenseListVersion: 3.19\n"), + call("Creator: Person: creatorName (some@mail.com)\n"), + call("Created: 2022-12-01T00:00:00Z\n"), + call("CreatorComment: creatorComment\n"), + ], + ), + ( + CreationInfo( + spdx_version="SPDX-2.3", + spdx_id="SPDXRef-DOCUMENT", + creators=[actor_fixture()], + name="Test document", + document_namespace="https://namespace.com", + created=datetime.datetime(2022, 3, 10), + ), + [ + call("SPDXVersion: SPDX-2.3\n"), + call("DataLicense: CC0-1.0\n"), + call("SPDXID: SPDXRef-DOCUMENT\n"), + call("DocumentName: Test document\n"), + call("DocumentNamespace: https://namespace.com\n"), + call("\n"), + call("## Creation Information\n"), + call("Creator: Person: actorName (some@mail.com)\n"), + call("Created: 2022-03-10T00:00:00Z\n"), + ], + ), + ], +) def test_creation_info_writer(creation_info, expected_calls): mock: MagicMock = mock_open() with patch(f"{__name__}.open", mock, create=True): diff --git a/tests/spdx/writer/tagvalue/test_package_writer.py b/tests/spdx/writer/tagvalue/test_package_writer.py index a89bcd65a..ec5366617 100644 --- a/tests/spdx/writer/tagvalue/test_package_writer.py +++ b/tests/spdx/writer/tagvalue/test_package_writer.py @@ -25,33 +25,36 @@ def test_package_writer(): mock.assert_called_once_with("foo", "w") handle = mock() handle.write.assert_has_calls( - [call("## Package Information\n"), - call("PackageName: packageName\n"), - call("SPDXID: SPDXRef-Package\n"), - call("PackageVersion: 12.2\n"), - call("PackageFileName: ./packageFileName\n"), - call("PackageSupplier: Person: supplierName (some@mail.com)\n"), - call("PackageOriginator: Person: originatorName (some@mail.com)\n"), - call("PackageDownloadLocation: https://download.com\n"), - call("FilesAnalyzed: True\n"), - call("PackageVerificationCode: 85ed0817af83a24ad8da68c2b5094de69833983c (excludes: ./exclude.py)\n"), - call("PackageChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), - call("PackageHomePage: https://homepage.com\n"), - call("PackageSourceInfo: sourceInfo\n"), - call("PackageLicenseConcluded: MIT AND GPL-2.0-only\n"), - call("PackageLicenseInfoFromFiles: MIT\n"), - call("PackageLicenseInfoFromFiles: GPL-2.0-only\n"), - call('PackageLicenseInfoFromFiles: NOASSERTION\n'), - call("PackageLicenseDeclared: MIT AND GPL-2.0-only\n"), - call("PackageLicenseComments: packageLicenseComment\n"), - call("PackageCopyrightText: packageCopyrightText\n"), - call("PackageSummary: packageSummary\n"), - call("PackageDescription: packageDescription\n"), - call("PackageComment: packageComment\n"), - call("ExternalRef: PACKAGE-MANAGER maven-central org.apache.tomcat:tomcat:9.0.0.M4\n"), - call("ExternalRefComment: externalPackageRefComment\n"), - call("PackageAttributionText: packageAttributionText\n"), - call("PrimaryPackagePurpose: SOURCE\n"), - call("ReleaseDate: 2022-12-01T00:00:00Z\n"), - call("BuiltDate: 2022-12-02T00:00:00Z\n"), - call("ValidUntilDate: 2022-12-03T00:00:00Z\n")]) + [ + call("## Package Information\n"), + call("PackageName: packageName\n"), + call("SPDXID: SPDXRef-Package\n"), + call("PackageVersion: 12.2\n"), + call("PackageFileName: ./packageFileName\n"), + call("PackageSupplier: Person: supplierName (some@mail.com)\n"), + call("PackageOriginator: Person: originatorName (some@mail.com)\n"), + call("PackageDownloadLocation: https://download.com\n"), + call("FilesAnalyzed: True\n"), + call("PackageVerificationCode: 85ed0817af83a24ad8da68c2b5094de69833983c (excludes: ./exclude.py)\n"), + call("PackageChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), + call("PackageHomePage: https://homepage.com\n"), + call("PackageSourceInfo: sourceInfo\n"), + call("PackageLicenseConcluded: MIT AND GPL-2.0-only\n"), + call("PackageLicenseInfoFromFiles: MIT\n"), + call("PackageLicenseInfoFromFiles: GPL-2.0-only\n"), + call("PackageLicenseInfoFromFiles: NOASSERTION\n"), + call("PackageLicenseDeclared: MIT AND GPL-2.0-only\n"), + call("PackageLicenseComments: packageLicenseComment\n"), + call("PackageCopyrightText: packageCopyrightText\n"), + call("PackageSummary: packageSummary\n"), + call("PackageDescription: packageDescription\n"), + call("PackageComment: packageComment\n"), + call("ExternalRef: PACKAGE-MANAGER maven-central org.apache.tomcat:tomcat:9.0.0.M4\n"), + call("ExternalRefComment: externalPackageRefComment\n"), + call("PackageAttributionText: packageAttributionText\n"), + call("PrimaryPackagePurpose: SOURCE\n"), + call("ReleaseDate: 2022-12-01T00:00:00Z\n"), + call("BuiltDate: 2022-12-02T00:00:00Z\n"), + call("ValidUntilDate: 2022-12-03T00:00:00Z\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py index a9c4832f0..a1bb05f9d 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py @@ -20,14 +20,21 @@ def test_scan_relationships(): file_spdx_id = "SPDXRef-File" files = [file_fixture(spdx_id=file_spdx_id)] relationships = [ - relationship_fixture(spdx_element_id=first_package_spdx_id, relationship_type=RelationshipType.CONTAINS, - related_spdx_element_id=file_spdx_id, comment=None), - relationship_fixture(spdx_element_id=second_package_spdx_id, relationship_type=RelationshipType.CONTAINS, - related_spdx_element_id=file_spdx_id, comment=None) + relationship_fixture( + spdx_element_id=first_package_spdx_id, + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id=file_spdx_id, + comment=None, + ), + relationship_fixture( + spdx_element_id=second_package_spdx_id, + relationship_type=RelationshipType.CONTAINS, + related_spdx_element_id=file_spdx_id, + comment=None, + ), ] relationships_to_write, contained_files_by_package_id = scan_relationships(relationships, packages, files) assert relationships_to_write == [] - assert contained_files_by_package_id == {first_package_spdx_id: files, - second_package_spdx_id: files} + assert contained_files_by_package_id == {first_package_spdx_id: files, second_package_spdx_id: files} From faba19008ba6a5a79c34ee7a5468787a2659bb1d Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 28 Mar 2023 16:18:25 +0200 Subject: [PATCH 032/354] [code_style] make files flake8-compliant Signed-off-by: Meret Behrens --- .../typing/dataclass_with_properties.py | 4 +- src/spdx/clitools/pyspdxtools.py | 5 +- .../jsonlikedict/license_expression_parser.py | 5 +- .../jsonlikedict/relationship_parser.py | 13 +-- .../parser/jsonlikedict/snippet_parser.py | 5 +- src/spdx/parser/rdf/creation_info_parser.py | 2 +- src/spdx/parser/rdf/package_parser.py | 3 +- src/spdx/parser/rdf/snippet_parser.py | 2 +- src/spdx/parser/tagvalue/lexer.py | 3 +- src/spdx/validation/checksum_validator.py | 3 +- src/spdx/validation/document_validator.py | 6 +- .../external_document_ref_validator.py | 3 +- .../external_package_ref_validator.py | 15 +++- .../extracted_licensing_info_validator.py | 3 +- src/spdx/validation/file_validator.py | 9 +- .../license_expression_validator.py | 8 +- src/spdx/validation/package_validator.py | 17 ++-- .../package_verification_code_validator.py | 3 +- src/spdx/validation/snippet_validator.py | 10 ++- src/spdx/validation/spdx_id_validators.py | 12 ++- src/spdx/validation/uri_validators.py | 5 +- tests/spdx/fixtures.py | 4 +- .../jsonlikedict/test_annotation_parser.py | 6 +- .../jsonlikedict/test_checksum_parser.py | 3 +- .../jsonlikedict/test_creation_info_parser.py | 3 +- .../test_extracted_licensing_info_parser.py | 12 ++- .../parser/jsonlikedict/test_file_parser.py | 19 +++- .../jsonlikedict/test_package_parser.py | 33 +++++-- .../jsonlikedict/test_snippet_parser.py | 20 +++-- tests/spdx/parser/rdf/test_package_parser.py | 2 +- tests/spdx/parser/rdf/test_rdf_parser.py | 2 +- tests/spdx/parser/rdf/test_snippet_parser.py | 2 +- .../parser/tagvalue/test_annotation_parser.py | 3 +- .../tagvalue/test_creation_info_parser.py | 10 ++- .../test_extracted_licensing_info_parser.py | 10 +-- .../spdx/parser/tagvalue/test_file_parser.py | 6 +- .../parser/tagvalue/test_helper_methods.py | 32 ++++--- .../parser/tagvalue/test_tag_value_lexer.py | 15 ++-- .../validation/test_checksum_validator.py | 89 +++++++++++++------ .../test_creation_info_validator.py | 3 +- .../validation/test_document_validator.py | 9 +- .../test_external_package_ref_validator.py | 51 +++++++---- tests/spdx/validation/test_file_validator.py | 4 +- .../test_license_expression_validator.py | 20 +++-- .../spdx/validation/test_package_validator.py | 3 +- ...est_package_verification_code_validator.py | 6 +- .../validation/test_spdx_id_validators.py | 18 ++-- tests/spdx/validation/test_uri_validators.py | 3 +- .../tagvalue/test_creation_info_writer.py | 3 +- 49 files changed, 348 insertions(+), 179 deletions(-) diff --git a/src/common/typing/dataclass_with_properties.py b/src/common/typing/dataclass_with_properties.py index 3c73ede87..644a1269e 100644 --- a/src/common/typing/dataclass_with_properties.py +++ b/src/common/typing/dataclass_with_properties.py @@ -47,8 +47,8 @@ def get_field_with_better_error_message(self) -> field_type: return get_field(self) except TypeError as err: error_message: str = f"GetterError {self.__class__.__name__}: {err.args[0]}" - # As getters are created dynamically, their argument name is always "the return value". We replace it by the - # actual name so the error message is more helpful. + # As getters are created dynamically, their argument name is always "the return value". + # We replace it by the actual name so the error message is more helpful. raise TypeError( error_message.replace("the return value", field_name, 1) + f': {getattr(self, f"_{field_name}")}' ) diff --git a/src/spdx/clitools/pyspdxtools.py b/src/spdx/clitools/pyspdxtools.py index 4f9ea75be..dece3733f 100644 --- a/src/spdx/clitools/pyspdxtools.py +++ b/src/spdx/clitools/pyspdxtools.py @@ -34,7 +34,8 @@ ) @click.option( "--version", - help='The SPDX version to be used during parsing and validation ("SPDX-2.2" or "SPDX-2.3"). Will be read from the document if not provided.', + help='The SPDX version to be used during parsing and validation ("SPDX-2.2" or "SPDX-2.3"). ' + "Will be read from the document if not provided.", default=None, ) @click.option("--novalidation", is_flag=True, help="Don't validate the provided document.") @@ -54,7 +55,7 @@ def main(infile: str, outfile: str, version: str, novalidation: bool): if not version: version = document.creation_info.spdx_version - if not version in ["SPDX-2.2", "SPDX-2.3"]: + if version not in ["SPDX-2.2", "SPDX-2.3"]: logging.error(f"This tool only supports SPDX versions SPDX-2.2 and SPDX-2.3, but got: {version}") sys.exit(1) diff --git a/src/spdx/parser/jsonlikedict/license_expression_parser.py b/src/spdx/parser/jsonlikedict/license_expression_parser.py index 3e57283cd..74ce63034 100644 --- a/src/spdx/parser/jsonlikedict/license_expression_parser.py +++ b/src/spdx/parser/jsonlikedict/license_expression_parser.py @@ -8,16 +8,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import List, Union +from typing import Union from license_expression import ExpressionError, LicenseExpression, Licensing from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.dict_parsing_functions import append_parsed_field_or_log_error -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import raise_parsing_error_if_logger_has_messages class LicenseExpressionParser: diff --git a/src/spdx/parser/jsonlikedict/relationship_parser.py b/src/spdx/parser/jsonlikedict/relationship_parser.py index 598ec4ecd..4d72f851a 100644 --- a/src/spdx/parser/jsonlikedict/relationship_parser.py +++ b/src/spdx/parser/jsonlikedict/relationship_parser.py @@ -63,9 +63,10 @@ def parse_all_relationships(self, input_doc_dict: Dict) -> List[Relationship]: file_dicts: List[Dict] = input_doc_dict.get("files", []) - # not implemented yet: deal with deprecated fields in file: https://github.com/spdx/tools-python/issues/294 & https://github.com/spdx/tools-python/issues/387 - generated_relationships = self.parse_artifact_of(file_dicts=file_dicts) - dependency_relationships = self.parse_file_dependencies(file_dicts=file_dicts) + # not implemented yet: deal with deprecated fields in file: + # https://github.com/spdx/tools-python/issues/294 & https://github.com/spdx/tools-python/issues/387 + _ = self.parse_artifact_of(file_dicts=file_dicts) + _ = self.parse_file_dependencies(file_dicts=file_dicts) raise_parsing_error_if_logger_has_messages(self.logger) @@ -195,11 +196,13 @@ def invert_relationship(self, relationship: Relationship) -> Relationship: @staticmethod def parse_file_dependencies(file_dicts: List[Dict]) -> List[Relationship]: dependency_relationships = [] - # the field fileDependencies is deprecated and should be converted to a relationship (https://github.com/spdx/tools-python/issues/387) + # the field fileDependencies is deprecated and should be converted to a relationship + # https://github.com/spdx/tools-python/issues/387 return dependency_relationships @staticmethod def parse_artifact_of(file_dicts: List[Dict]) -> List[Relationship]: generated_relationships = [] - # artifactOfs is deprecated and should be converted to an external package and a generated from relationship (https://github.com/spdx/tools-python/issues/294) + # artifactOfs is deprecated and should be converted to an external package and a generated from relationship + # https://github.com/spdx/tools-python/issues/294 return generated_relationships diff --git a/src/spdx/parser/jsonlikedict/snippet_parser.py b/src/spdx/parser/jsonlikedict/snippet_parser.py index d07e6eff6..548a3eb6f 100644 --- a/src/spdx/parser/jsonlikedict/snippet_parser.py +++ b/src/spdx/parser/jsonlikedict/snippet_parser.py @@ -17,10 +17,7 @@ from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.dict_parsing_functions import ( - parse_field_or_log_error, - parse_field_or_no_assertion_or_none, -) +from spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_log_error from spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser from spdx.parser.logger import Logger from spdx.parser.parsing_functions import construct_or_raise_parsing_error diff --git a/src/spdx/parser/rdf/creation_info_parser.py b/src/spdx/parser/rdf/creation_info_parser.py index 6d6ac9b50..57e63ca9d 100644 --- a/src/spdx/parser/rdf/creation_info_parser.py +++ b/src/spdx/parser/rdf/creation_info_parser.py @@ -93,7 +93,7 @@ def parse_namespace_and_spdx_id(graph: Graph) -> (str, str): if not subject: logging.error("No SpdxDocument found, can't parse rdf file.") sys.exit(1) - if not "#" in subject: + if "#" not in subject: logging.error( "No '#' found in the URI of SpdxDocument, " "the URI for the SpdxDocument should be the namespace appended by '#SPDXRef-DOCUMENT." diff --git a/src/spdx/parser/rdf/package_parser.py b/src/spdx/parser/rdf/package_parser.py index a09630d2b..0301ecdee 100644 --- a/src/spdx/parser/rdf/package_parser.py +++ b/src/spdx/parser/rdf/package_parser.py @@ -10,7 +10,7 @@ # limitations under the License. from typing import Optional -from rdflib import DOAP, RDFS, Graph, Literal, URIRef +from rdflib import DOAP, RDFS, Graph, URIRef from spdx.datetime_conversions import datetime_from_str from spdx.model.package import ( @@ -30,7 +30,6 @@ parse_literal, parse_literal_or_no_assertion_or_none, parse_spdx_id, - remove_prefix, ) from spdx.parser.rdf.license_expression_parser import parse_license_expression from spdx.rdfschema.namespace import REFERENCE_NAMESPACE, SPDX_NAMESPACE diff --git a/src/spdx/parser/rdf/snippet_parser.py b/src/spdx/parser/rdf/snippet_parser.py index a21a5a1cf..6a69306f3 100644 --- a/src/spdx/parser/rdf/snippet_parser.py +++ b/src/spdx/parser/rdf/snippet_parser.py @@ -109,7 +109,7 @@ def parse_ranges(start_end_pointer: URIRef, graph: Graph) -> Dict[str, Tuple[int end_pointer_type, end_pointer_node = get_pointer_type(graph, POINTER_NAMESPACE.endPointer, start_end_pointer) if start_pointer_type != end_pointer_type: - raise SPDXParsingError([f"Types of startPointer and endPointer don't match"]) + raise SPDXParsingError(["Types of startPointer and endPointer don't match"]) range_values["startPointer"] = parse_range_value(graph, start_pointer_node, POINTER_MATCHING[start_pointer_type]) range_values["endPointer"] = parse_range_value(graph, end_pointer_node, POINTER_MATCHING[end_pointer_type]) diff --git a/src/spdx/parser/tagvalue/lexer.py b/src/spdx/parser/tagvalue/lexer.py index 319909717..7556267b7 100644 --- a/src/spdx/parser/tagvalue/lexer.py +++ b/src/spdx/parser/tagvalue/lexer.py @@ -137,7 +137,8 @@ def t_text_error(self, t): print("Lexer error in text state") @TOKEN( - r":\s*(ADLER32|BLAKE2b-256|BLAKE2b-384|BLAKE2b-512|BLAKE3|MD2|MD4|MD5|MD6|SHA1|SHA224|SHA256|SHA384|SHA512|SHA3-256|SHA3-384|SHA3-512):\s*([a-f0-9]*)" + r":\s*(ADLER32|BLAKE2b-256|BLAKE2b-384|BLAKE2b-512|BLAKE3|MD2|MD4|MD5|MD6|SHA1|SHA224|SHA256|SHA384|SHA512|" + r"SHA3-256|SHA3-384|SHA3-512):\s*([a-f0-9]*)" ) def t_CHECKSUM(self, t): t.value = t.value[1:].strip() diff --git a/src/spdx/validation/checksum_validator.py b/src/spdx/validation/checksum_validator.py index 16bf157d7..f34cc0a2e 100644 --- a/src/spdx/validation/checksum_validator.py +++ b/src/spdx/validation/checksum_validator.py @@ -71,7 +71,8 @@ def validate_checksum(checksum: Checksum, parent_id: str, spdx_version: str) -> length = algorithm_length[algorithm] validation_messages.append( ValidationMessage( - f"value of {algorithm} must consist of {length} lowercase hexadecimal digits, but is: {checksum.value} (length: {len(checksum.value)} digits)", + f"value of {algorithm} must consist of {length} lowercase hexadecimal digits, but is: " + f"{checksum.value} (length: {len(checksum.value)} digits)", context, ) ) diff --git a/src/spdx/validation/document_validator.py b/src/spdx/validation/document_validator.py index c0da83f46..1446ce1bb 100644 --- a/src/spdx/validation/document_validator.py +++ b/src/spdx/validation/document_validator.py @@ -36,7 +36,8 @@ def validate_full_spdx_document(document: Document, spdx_version: str = None) -> if document_version not in ["SPDX-2.2", "SPDX-2.3"]: validation_messages.append( ValidationMessage( - f'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: {document_version}', + f'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: ' + f"{document_version}", context, ) ) @@ -94,7 +95,8 @@ def validate_full_spdx_document(document: Document, spdx_version: str = None) -> if duplicated_spdx_ids: validation_messages.append( ValidationMessage( - f"every spdx_id must be unique within the document, but found the following duplicates: {sorted(duplicated_spdx_ids)}", + f"every spdx_id must be unique within the document, but found the following duplicates: " + f"{sorted(duplicated_spdx_ids)}", context, ) ) diff --git a/src/spdx/validation/external_document_ref_validator.py b/src/spdx/validation/external_document_ref_validator.py index c527a6c5c..6cd20d2da 100644 --- a/src/spdx/validation/external_document_ref_validator.py +++ b/src/spdx/validation/external_document_ref_validator.py @@ -39,7 +39,8 @@ def validate_external_document_ref( if not is_valid_external_doc_ref_id(external_document_ref.document_ref_id): validation_messages.append( ValidationMessage( - f'document_ref_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: {external_document_ref.document_ref_id}', + f'document_ref_id must only contain letters, numbers, ".", "-" and "+" and must begin with ' + f'"DocumentRef-", but is: {external_document_ref.document_ref_id}', context, ) ) diff --git a/src/spdx/validation/external_package_ref_validator.py b/src/spdx/validation/external_package_ref_validator.py index db7bc16eb..8105ec0f6 100644 --- a/src/spdx/validation/external_package_ref_validator.py +++ b/src/spdx/validation/external_package_ref_validator.py @@ -18,7 +18,11 @@ from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage CPE22TYPE_REGEX = r"^c[pP][eE]:/[AHOaho]?(:[A-Za-z0-9._\-~%]*){0,6}$" -CPE23TYPE_REGEX = r'^cpe:2\.3:[aho\*\-](:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!"#$$%&\'\(\)\+,\/:;<=>@\[\]\^`\{\|}~]))+(\?*|\*?))|[\*\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\*\-]))(:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!"#$$%&\'\(\)\+,\/:;<=>@\[\]\^`\{\|}~]))+(\?*|\*?))|[\*\-])){4}$' +CPE23TYPE_REGEX = ( + r'^cpe:2\.3:[aho\*\-](:(((\?*|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!"#$$%&\'\(\)\+,\/:;<=>@\[\]\^' + r"`\{\|}~]))+(\?*|\*?))|[\*\-])){5}(:(([a-zA-Z]{2,3}(-([a-zA-Z]{2}|[0-9]{3}))?)|[\*\-]))(:(((\?*" + r'|\*?)([a-zA-Z0-9\-\._]|(\\[\\\*\?!"#$$%&\'\(\)\+,\/:;<=>@\[\]\^`\{\|}~]))+(\?*|\*?))|[\*\-])){4}$' +) MAVEN_CENTRAL_REGEX = r"^[^:]+:[^:]+(:[^:]+)?$" NPM_REGEX = r"^[^@]+@[^@]+$" NUGET_REGEX = r"^[^/]+/[^/]+$" @@ -76,7 +80,8 @@ def validate_external_package_ref( elif reference_type not in CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES[category]: validation_messages.append( ValidationMessage( - f"externalPackageRef type in category {category.name} must be one of {CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES[category]}, but is: {reference_type}", + f"externalPackageRef type in category {category.name} must be one of " + f"{CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES[category]}, but is: {reference_type}", context, ) ) @@ -94,7 +99,8 @@ def validate_external_package_ref( if not uritools.isuri(locator) or not locator.startswith("swid"): validation_messages.append( ValidationMessage( - f'externalPackageRef locator of type "swid" must be a valid URI with scheme swid, but is: {locator}', + f'externalPackageRef locator of type "swid" must be a valid URI with scheme swid, ' + f"but is: {locator}", context, ) ) @@ -112,7 +118,8 @@ def validate_against_regex( if not re.match(regex, string_to_validate): return [ ValidationMessage( - f'externalPackageRef locator of type "{reference_type}" must conform with the regex {regex}, but is: {string_to_validate}', + f'externalPackageRef locator of type "{reference_type}" must conform with the regex {regex}, ' + f"but is: {string_to_validate}", context, ) ] diff --git a/src/spdx/validation/extracted_licensing_info_validator.py b/src/spdx/validation/extracted_licensing_info_validator.py index 52e2b35b0..a1def8ae7 100644 --- a/src/spdx/validation/extracted_licensing_info_validator.py +++ b/src/spdx/validation/extracted_licensing_info_validator.py @@ -37,7 +37,8 @@ def validate_extracted_licensing_info(extracted_licensing_infos: ExtractedLicens if license_id and not re.match(r"^LicenseRef-[\da-zA-Z.-]+$", license_id): validation_messages.append( ValidationMessage( - f'license_id must only contain letters, numbers, "." and "-" and must begin with "LicenseRef-", but is: {license_id}', + f'license_id must only contain letters, numbers, "." and "-" and must begin with "LicenseRef-", ' + f"but is: {license_id}", context, ) ) diff --git a/src/spdx/validation/file_validator.py b/src/spdx/validation/file_validator.py index 9e717f50c..c90cbc868 100644 --- a/src/spdx/validation/file_validator.py +++ b/src/spdx/validation/file_validator.py @@ -72,7 +72,8 @@ def validate_file( if ChecksumAlgorithm.SHA1 not in [checksum.algorithm for checksum in file.checksums]: validation_messages.append( ValidationMessage( - f"checksums must contain a SHA1 algorithm checksum, but only contains: {[checksum.algorithm for checksum in file.checksums]}", + f"checksums must contain a SHA1 algorithm checksum, but only contains: " + f"{[checksum.algorithm for checksum in file.checksums]}", context, ) ) @@ -81,10 +82,10 @@ def validate_file( if spdx_version == "SPDX-2.2": if file.license_concluded is None: - validation_messages.append(ValidationMessage(f"license_concluded is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage("license_concluded is mandatory in SPDX-2.2", context)) if not file.license_info_in_file: - validation_messages.append(ValidationMessage(f"license_info_in_file is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage("license_info_in_file is mandatory in SPDX-2.2", context)) if file.copyright_text is None: - validation_messages.append(ValidationMessage(f"copyright_text is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage("copyright_text is mandatory in SPDX-2.2", context)) return validation_messages diff --git a/src/spdx/validation/license_expression_validator.py b/src/spdx/validation/license_expression_validator.py index 45199417f..ebf6e4ae8 100644 --- a/src/spdx/validation/license_expression_validator.py +++ b/src/spdx/validation/license_expression_validator.py @@ -54,7 +54,8 @@ def validate_license_expression( if non_spdx_token not in license_ref_ids: validation_messages.append( ValidationMessage( - f"Unrecognized license reference: {non_spdx_token}. license_expression must only use IDs from the license list or extracted licensing info, but is: {license_expression}", + f"Unrecognized license reference: {non_spdx_token}. license_expression must only use IDs from the " + f"license list or extracted licensing info, but is: {license_expression}", context, ) ) @@ -66,8 +67,9 @@ def validate_license_expression( # So far, it only catches the first such error in the provided string. validation_messages.append(ValidationMessage(f"{err}. for license_expression: {license_expression}", context)) except ExpressionError: - # This error is raised for invalid symbols within the license_expression, but it provides only a string of these. - # On the other hand, get_spdx_licensing().validate() gives an actual list of invalid symbols, so this is handled above. + # This error is raised for invalid symbols within the license_expression, but it provides only a string of + # these. On the other hand, get_spdx_licensing().validate() gives an actual list of invalid symbols, so this is + # handled above. pass return validation_messages diff --git a/src/spdx/validation/package_validator.py b/src/spdx/validation/package_validator.py index 0cf4f577c..ab68757e1 100644 --- a/src/spdx/validation/package_validator.py +++ b/src/spdx/validation/package_validator.py @@ -79,7 +79,8 @@ def validate_package_within_document( if not package.files_analyzed: validation_messages.append( ValidationMessage( - f"license_info_from_files must be None if files_analyzed is False, but is: {license_info_from_files}", + f"license_info_from_files must be None if files_analyzed is False, but is: " + f"{license_info_from_files}", context, ) ) @@ -134,20 +135,20 @@ def validate_package( if spdx_version == "SPDX-2.2": if package.primary_package_purpose is not None: validation_messages.append( - ValidationMessage(f"primary_package_purpose is not supported in SPDX-2.2", context) + ValidationMessage("primary_package_purpose is not supported in SPDX-2.2", context) ) if package.built_date is not None: - validation_messages.append(ValidationMessage(f"built_date is not supported in SPDX-2.2", context)) + validation_messages.append(ValidationMessage("built_date is not supported in SPDX-2.2", context)) if package.release_date is not None: - validation_messages.append(ValidationMessage(f"release_date is not supported in SPDX-2.2", context)) + validation_messages.append(ValidationMessage("release_date is not supported in SPDX-2.2", context)) if package.valid_until_date is not None: - validation_messages.append(ValidationMessage(f"valid_until_date is not supported in SPDX-2.2", context)) + validation_messages.append(ValidationMessage("valid_until_date is not supported in SPDX-2.2", context)) if package.license_concluded is None: - validation_messages.append(ValidationMessage(f"license_concluded is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage("license_concluded is mandatory in SPDX-2.2", context)) if package.license_declared is None: - validation_messages.append(ValidationMessage(f"license_declared is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage("license_declared is mandatory in SPDX-2.2", context)) if package.copyright_text is None: - validation_messages.append(ValidationMessage(f"copyright_text is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage("copyright_text is mandatory in SPDX-2.2", context)) return validation_messages diff --git a/src/spdx/validation/package_verification_code_validator.py b/src/spdx/validation/package_verification_code_validator.py index 69c6bd0ac..b059dc69c 100644 --- a/src/spdx/validation/package_verification_code_validator.py +++ b/src/spdx/validation/package_verification_code_validator.py @@ -32,7 +32,8 @@ def validate_verification_code(verification_code: PackageVerificationCode, paren if not re.match("^[0-9a-f]{40}$", value): validation_messages.append( ValidationMessage( - f"value of verification_code must consist of 40 lowercase hexadecimal digits, but is: {value} (length: {len(value)} digits)", + f"value of verification_code must consist of 40 lowercase hexadecimal digits, but is: {value} " + f"(length: {len(value)} digits)", context, ) ) diff --git a/src/spdx/validation/snippet_validator.py b/src/spdx/validation/snippet_validator.py index 27a049621..c709b1d37 100644 --- a/src/spdx/validation/snippet_validator.py +++ b/src/spdx/validation/snippet_validator.py @@ -81,7 +81,8 @@ def validate_snippet( if snippet.byte_range[0] > snippet.byte_range[1]: validation_messages.append( ValidationMessage( - f"the first value of byte_range must be less than or equal to the second, but is: {snippet.byte_range}", + f"the first value of byte_range must be less than or equal to the second, but is: " + f"{snippet.byte_range}", context, ) ) @@ -97,15 +98,16 @@ def validate_snippet( if snippet.line_range[0] > snippet.line_range[1]: validation_messages.append( ValidationMessage( - f"the first value of line_range must be less than or equal to the second, but is: {snippet.line_range}", + f"the first value of line_range must be less than or equal to the second, " + f"but is: {snippet.line_range}", context, ) ) if spdx_version == "SPDX-2.2": if snippet.license_concluded is None: - validation_messages.append(ValidationMessage(f"license_concluded is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage("license_concluded is mandatory in SPDX-2.2", context)) if snippet.copyright_text is None: - validation_messages.append(ValidationMessage(f"copyright_text is mandatory in SPDX-2.2", context)) + validation_messages.append(ValidationMessage("copyright_text is mandatory in SPDX-2.2", context)) return validation_messages diff --git a/src/spdx/validation/spdx_id_validators.py b/src/spdx/validation/spdx_id_validators.py index 8d941f06e..29164df65 100644 --- a/src/spdx/validation/spdx_id_validators.py +++ b/src/spdx/validation/spdx_id_validators.py @@ -63,18 +63,21 @@ def validate_spdx_id( # # # invalid case # # # if len(split_id) > 2: return [ - f"spdx_id must not contain more than one colon in order to separate the external document reference id from the internal SPDX id, but is: {spdx_id}" + f"spdx_id must not contain more than one colon in order to separate the external document reference id " + f"from the internal SPDX id, but is: {spdx_id}" ] # # # case with external document ref prefix # # # if len(split_id) == 2: if not is_valid_external_doc_ref_id(split_id[0]): validation_messages.append( - f'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: {split_id[0]}' + f'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and ' + f'"+" and must begin with "DocumentRef-", but is: {split_id[0]}' ) if not is_valid_internal_spdx_id(split_id[1]): validation_messages.append( - f'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: {split_id[1]}' + f'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin ' + f'with "SPDXRef-", but is: {split_id[1]}' ) if not is_external_doc_ref_present_in_document(split_id[0], document): validation_messages.append( @@ -86,7 +89,8 @@ def validate_spdx_id( # # # "normal" case # # # if not is_valid_internal_spdx_id(spdx_id): validation_messages.append( - f'spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: {spdx_id}' + f'spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: ' + f"{spdx_id}" ) if check_document: diff --git a/src/spdx/validation/uri_validators.py b/src/spdx/validation/uri_validators.py index 1bc8608dc..8d57c997c 100644 --- a/src/spdx/validation/uri_validators.py +++ b/src/spdx/validation/uri_validators.py @@ -14,7 +14,10 @@ from uritools import isabsuri, urisplit -url_pattern = "(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/|ssh:\\/\\/|git:\\/\\/|svn:\\/\\/|sftp:\\/\\/|ftp:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+){0,100}\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?" +url_pattern = ( + "(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/|ssh:\\/\\/|git:\\/\\/|svn:\\/\\/|sftp:" + "\\/\\/|ftp:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+){0,100}\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?" +) supported_download_repos: str = "(git|hg|svn|bzr)" git_pattern = "(git\\+git@[a-zA-Z0-9\\.\\-]+:[a-zA-Z0-9/\\\\.@\\-]+)" bazaar_pattern = "(bzr\\+lp:[a-zA-Z0-9\\.\\-]+)" diff --git a/tests/spdx/fixtures.py b/tests/spdx/fixtures.py index 56e6d2271..6bfe9f72d 100644 --- a/tests/spdx/fixtures.py +++ b/tests/spdx/fixtures.py @@ -32,8 +32,8 @@ from spdx.model.spdx_none import SpdxNone from spdx.model.version import Version -"""Utility methods to create data model instances. All properties have valid defaults, so they don't need to be -specified unless relevant for the test.""" +# Utility methods to create data model instances. All properties have valid defaults, so they don't need to be +# specified unless relevant for the test. def actor_fixture(actor_type=ActorType.PERSON, name="actorName", email="some@mail.com") -> Actor: diff --git a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py index 2e2da39cf..439883433 100644 --- a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py @@ -132,7 +132,8 @@ def test_parse_all_annotations(): {"annotator": "Person: Jane Doe ()"}, [ "Error while constructing Annotation: ['SetterError Annotation: type of " - 'argument "spdx_id" must be str; got NoneType instead: None\', \'SetterError Annotation: type of argument "annotation_type" must be ' + 'argument "spdx_id" must be str; got NoneType instead: None\', ' + '\'SetterError Annotation: type of argument "annotation_type" must be ' "spdx.model.annotation.AnnotationType; got NoneType instead: None', " '\'SetterError Annotation: type of argument "annotation_date" must be ' "datetime.datetime; got NoneType instead: None', 'SetterError Annotation: " @@ -144,7 +145,8 @@ def test_parse_all_annotations(): {"annotationDate": "2010-01-29T18:30:22Z"}, [ "Error while constructing Annotation: ['SetterError Annotation: type of " - 'argument "spdx_id" must be str; got NoneType instead: None\', \'SetterError Annotation: type of argument "annotation_type" must be ' + 'argument "spdx_id" must be str; got NoneType instead: None\', ' + '\'SetterError Annotation: type of argument "annotation_type" must be ' "spdx.model.annotation.AnnotationType; got NoneType instead: None', " '\'SetterError Annotation: type of argument "annotator" must be ' "spdx.model.actor.Actor; got NoneType instead: None', 'SetterError Annotation: " diff --git a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py index c2a51076d..536b02040 100644 --- a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py @@ -49,6 +49,7 @@ def test_parse_incomplete_checksum(): TestCase().assertCountEqual( err.value.get_messages(), [ - "Error while constructing Checksum: ['SetterError Checksum: type of argument \"value\" must be str; got NoneType instead: None']" + 'Error while constructing Checksum: [\'SetterError Checksum: type of argument "value" must be str; ' + "got NoneType instead: None']" ], ) diff --git a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py index 2ed029280..219daecb3 100644 --- a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py @@ -121,7 +121,8 @@ def test_parse_invalid_creation_info(): err.value.get_messages(), [ "Error while constructing CreationInfo: ['SetterError CreationInfo: type of " - 'argument "document_namespace" must be str; got NoneType instead: None\', \'SetterError CreationInfo: type of argument "data_license" must be str; got ' + 'argument "document_namespace" must be str; got NoneType instead: None\', ' + '\'SetterError CreationInfo: type of argument "data_license" must be str; got ' "NoneType instead: None']" ], ) diff --git a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py index f8c64ea32..b7abde4ae 100644 --- a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py @@ -22,7 +22,9 @@ def test_parse_extracted_licensing_info(): extracted_licensing_infos_dict = { "licenseId": "LicenseRef-Beerware-4.2", "comment": "The beerware license has a couple of other standard variants.", - "extractedText": '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp', + "extractedText": '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you ' + "retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and " + "you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", "name": "Beer-Ware License (Version 42)", "seeAlsos": ["http://people.freebsd.org/~phk/"], } @@ -35,7 +37,9 @@ def test_parse_extracted_licensing_info(): assert extracted_licensing_info.comment == "The beerware license has a couple of other standard variants." assert ( extracted_licensing_info.extracted_text - == '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp' + == '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this ' + "notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is " + "worth it, you can buy me a beer in return Poul-Henning Kamp" ) assert extracted_licensing_info.license_name == "Beer-Ware License (Version 42)" assert extracted_licensing_info.cross_references == ["http://people.freebsd.org/~phk/"] @@ -47,7 +51,9 @@ def test_parse_invalid_extracted_licensing_info(): extracted_licensing_infos_dict = { "licenseId": "LicenseRef-Beerware-4.2", "comment": 56, - "extractedText": '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp', + "extractedText": '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you ' + "retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and " + "you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", "name": "Beer-Ware License (Version 42)", "seeAlsos": ["http://people.freebsd.org/~phk/"], } diff --git a/tests/spdx/parser/jsonlikedict/test_file_parser.py b/tests/spdx/parser/jsonlikedict/test_file_parser.py index ddea8cfe7..3cf41e6e5 100644 --- a/tests/spdx/parser/jsonlikedict/test_file_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_file_parser.py @@ -30,7 +30,8 @@ def test_parse_file(): {"algorithm": "SHA1", "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2758"}, {"algorithm": "MD5", "checksumValue": "624c1abb3664f4b35547e7c73864ad24"}, ], - "comment": "The concluded license was taken from the package level that the file was included in.\nThis information was found in the COPYING.txt file in the xyz directory.", + "comment": "The concluded license was taken from the package level that the file was included in.\nThis " + "information was found in the COPYING.txt file in the xyz directory.", "copyrightText": "Copyright 2008-2010 John Smith", "fileContributors": [ "The Regents of the University of California", @@ -42,7 +43,18 @@ def test_parse_file(): "licenseComments": "The concluded license was taken from the package level that the file was included in.", "licenseConcluded": "(LGPL-2.0-only OR LicenseRef-2)", "licenseInfoInFiles": ["GPL-2.0-only", "LicenseRef-2", "NOASSERTION"], - "noticeText": 'Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: \nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.', + "noticeText": "Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is hereby granted, free of " + "charge, to any person obtaining a copy of this software and associated documentation files " + '(the "Software"), to deal in the Software without restriction, including without limitation ' + "the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of " + "the Software, and to permit persons to whom the Software is furnished to do so, subject to the " + "following conditions: \nThe above copyright notice and this permission notice shall be " + "included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED " + '"AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE ' + "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO " + "EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER " + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN " + "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", } file = file_parser.parse_file(file_dict) @@ -58,7 +70,8 @@ def test_parse_file(): ) assert ( file.comment - == "The concluded license was taken from the package level that the file was included in.\nThis information was found in the COPYING.txt file in the xyz directory." + == "The concluded license was taken from the package level that the file was included in.\nThis information " + "was found in the COPYING.txt file in the xyz directory." ) assert file.copyright_text == "Copyright 2008-2010 John Smith" assert file.file_types == [FileType.SOURCE] diff --git a/tests/spdx/parser/jsonlikedict/test_package_parser.py b/tests/spdx/parser/jsonlikedict/test_package_parser.py index 6890b807f..e4d6c9028 100644 --- a/tests/spdx/parser/jsonlikedict/test_package_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_package_parser.py @@ -29,7 +29,10 @@ def test_parse_package(): package_dict = { "SPDXID": "SPDXRef-Package", "attributionTexts": [ - "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually." + "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for " + "notices about a few contributions that require these additional notices to be distributed. License " + "copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the " + "range, inclusive, is a copyrightable year that would otherwise be listed individually." ], "builtDate": "2011-01-29T18:30:22Z", "checksums": [ @@ -41,12 +44,15 @@ def test_parse_package(): }, { "algorithm": "BLAKE2b-384", - "checksumValue": "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706", + "checksumValue": "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8" + "086984af8706", }, ], "comment": "This is a comment.", "copyrightText": "Copyright 2008-2010 John Smith", - "description": "The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems.", + "description": "The GNU C Library defines functions that are specified by the ISO C standard, as well as " + "additional features specific to POSIX and other derivatives of the Unix operating system, and " + "extensions specific to GNU systems.", "downloadLocation": "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", "externalRefs": [ { @@ -64,7 +70,8 @@ def test_parse_package(): ], "filesAnalyzed": True, "homepage": "http://ftp.gnu.org/gnu/glibc", - "licenseComments": "The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change.", + "licenseComments": "The license for this project changed with the release of version x.y. The version of the " + "project included here post-dates the license change.", "licenseConcluded": "(LGPL-2.0-only OR LicenseRef-3)", "licenseDeclared": "(LGPL-2.0-only AND LicenseRef-3)", "licenseInfoFromFiles": ["GPL-2.0-only", "LicenseRef-2", "LicenseRef-1", "NOASSERTION"], @@ -93,7 +100,7 @@ def test_parse_package(): assert package.file_name == "glibc-2.11.1.tar.gz" assert package.supplier == Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com") assert package.originator == Actor(ActorType.ORGANIZATION, "ExampleCodeInspect", "contact@example.com") - assert package.files_analyzed == True + assert package.files_analyzed is True assert package.verification_code == PackageVerificationCode( value="d6a770ba38583ed4bb4525bd96e50461655d2758", excluded_files=["./package.spdx"] ) @@ -125,13 +132,16 @@ def test_parse_package(): assert package.license_declared == Licensing().parse("(LGPL-2.0-only AND LicenseRef-3)") assert ( package.license_comment - == "The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change." + == "The license for this project changed with the release of version x.y. The version of the project included" + " here post-dates the license change." ) assert package.copyright_text == "Copyright 2008-2010 John Smith" assert package.summary == "GNU C library." assert ( package.description - == "The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems." + == "The GNU C Library defines functions that are specified by the ISO C standard, as well as additional " + "features specific to POSIX and other derivatives of the Unix operating system, and extensions specific " + "to GNU systems." ) assert package.comment == "This is a comment." assert len(package.external_references) == 2 @@ -152,7 +162,10 @@ def test_parse_package(): ], ) assert package.attribution_texts == [ - "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually." + "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for " + "notices about a few contributions that require these additional notices to be distributed. License " + "copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the " + "range, inclusive, is a copyrightable year that would otherwise be listed individually." ] assert package.primary_package_purpose == PackagePurpose.SOURCE assert package.release_date == datetime(2012, 1, 29, 18, 30, 22) @@ -167,7 +180,9 @@ def test_parse_package(): {"SPDXID": "SPDXRef-Package"}, [ "Error while constructing Package: ['SetterError Package: type of " - 'argument "name" must be str; got NoneType instead: None\', \'SetterError Package: type of argument "download_location" must be one of (str, spdx.model.spdx_no_assertion.SpdxNoAssertion, spdx.model.spdx_none.SpdxNone); ' + "argument \"name\" must be str; got NoneType instead: None', 'SetterError Package: type of argument " + '"download_location" must be one of (str, spdx.model.spdx_no_assertion.SpdxNoAssertion, ' + "spdx.model.spdx_none.SpdxNone); " "got NoneType instead: None']" ], ), diff --git a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py index 3a78d4e86..f2b8909b0 100644 --- a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py @@ -23,9 +23,13 @@ def test_parse_snippet(): snippet_dict = { "SPDXID": "SPDXRef-Snippet", - "comment": "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0.", + "comment": "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a " + "commercial scanner identified it as being derived from file foo.c in package xyz which is licensed" + " under GPL-2.0.", "copyrightText": "Copyright 2008-2010 John Smith", - "licenseComments": "The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz.", + "licenseComments": "The concluded license was taken from package xyz, from which the snippet was copied into " + "the current file. The concluded license information was found in the COPYING.txt file in " + "package xyz.", "licenseConcluded": "GPL-2.0-only", "licenseInfoInSnippets": ["GPL-2.0-only", "NOASSERTION"], "name": "from linux kernel", @@ -48,12 +52,14 @@ def test_parse_snippet(): assert snippet.name == "from linux kernel" assert ( snippet.comment - == "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0." + == "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial " + "scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0." ) assert snippet.copyright_text == "Copyright 2008-2010 John Smith" assert ( snippet.license_comment - == "The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz." + == "The concluded license was taken from package xyz, from which the snippet was copied into the current file." + " The concluded license information was found in the COPYING.txt file in package xyz." ) assert snippet.byte_range == (310, 420) assert snippet.line_range == (5, 23) @@ -74,7 +80,8 @@ def test_parse_incomplete_snippet(): err.value.get_messages(), [ "Error while constructing Snippet: ['SetterError Snippet: type of argument " - '"file_spdx_id" must be str; got NoneType instead: None\', \'SetterError Snippet: type of argument "byte_range" must be a tuple; got NoneType ' + "\"file_spdx_id\" must be str; got NoneType instead: None', 'SetterError Snippet: type of argument " + '"byte_range" must be a tuple; got NoneType ' "instead: None']" ], ) @@ -127,6 +134,7 @@ def test_parse_invalid_snippet_range(): TestCase().assertCountEqual( err.value.get_messages(), [ - "Error while parsing snippet ranges: ['Type of startpointer is not the same as type of endpointer.', 'Type of startpointer is not the same as type of endpointer.']" + "Error while parsing snippet ranges: ['Type of startpointer is not the same as type of endpointer.', " + "'Type of startpointer is not the same as type of endpointer.']" ], ) diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index ff4974286..454a37a79 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -37,7 +37,7 @@ def test_package_parser(): assert package.version == "12.2" assert package.file_name == "./packageFileName" assert package.homepage == "https://homepage.com" - assert package.files_analyzed == True + assert package.files_analyzed is True assert package.checksums == [Checksum(ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c")] assert package.source_info == "sourceInfo" assert package.license_concluded == get_spdx_licensing().parse("MIT AND GPL-2.0") diff --git a/tests/spdx/parser/rdf/test_rdf_parser.py b/tests/spdx/parser/rdf/test_rdf_parser.py index 650346d4d..b80fe3581 100644 --- a/tests/spdx/parser/rdf/test_rdf_parser.py +++ b/tests/spdx/parser/rdf/test_rdf_parser.py @@ -17,7 +17,7 @@ def test_rdf_parser_file_not_found(): - with pytest.raises(FileNotFoundError, match="No such file or directory") as err: + with pytest.raises(FileNotFoundError, match="No such file or directory"): wrong_file_path = os.path.join(os.path.dirname(__file__), "hnjfkjsedhnflsiafg.json") rdf_parser.parse_from_file(wrong_file_path) diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index d04d50e6c..b98d8e9c7 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -138,7 +138,7 @@ def test_parse_ranges_wrong_pair_of_pointer_classes(predicate_value_class_member (POINTER_NAMESPACE.startPointer, 100, POINTER_NAMESPACE.LineCharPointer, POINTER_NAMESPACE.lineNumber), (POINTER_NAMESPACE.endPointer, 200, POINTER_NAMESPACE.ByteOffsetPointer, POINTER_NAMESPACE.offset), ], - f"Types of startPointer and endPointer don't match", + "Types of startPointer and endPointer don't match", ), ], ) diff --git a/tests/spdx/parser/tagvalue/test_annotation_parser.py b/tests/spdx/parser/tagvalue/test_annotation_parser.py index 8dd8cb2ec..1fbd2060c 100644 --- a/tests/spdx/parser/tagvalue/test_annotation_parser.py +++ b/tests/spdx/parser/tagvalue/test_annotation_parser.py @@ -57,7 +57,8 @@ def test_parse_annotation(): ), ( "Annotator: Jane Doe()\nAnnotationDate: 201001-29T18:30:22Z\n" - "AnnotationComment: Document level annotation\nAnnotationType: OTHER\nSPDXREF: SPDXRef-DOCUMENT", + "AnnotationComment: Document level annotation\nAnnotationType: OTHER\n" + "SPDXREF: SPDXRef-DOCUMENT", "Error while parsing Annotation: ['Error while parsing Annotator: Token did " "not match specified grammar rule. Line: 1', 'Error while parsing " "AnnotationDate: Token did not match specified grammar rule. Line: 2']", diff --git a/tests/spdx/parser/tagvalue/test_creation_info_parser.py b/tests/spdx/parser/tagvalue/test_creation_info_parser.py index da98350b9..631aa3883 100644 --- a/tests/spdx/parser/tagvalue/test_creation_info_parser.py +++ b/tests/spdx/parser/tagvalue/test_creation_info_parser.py @@ -28,7 +28,9 @@ "SPDXID: SPDXRef-DOCUMENT", "DocumentComment: Sample Comment", "DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", - "ExternalDocumentRef: DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "ExternalDocumentRef: DocumentRef-spdx-tool-1.2 " + "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 " + "SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", "Creator: Person: Bob (bob@example.com)", "Creator: Organization: Acme.", "Created: 2010-02-03T00:00:00Z", @@ -82,7 +84,8 @@ def test_parse_creation_info(): "SPDXID: SPDXRef-DOCUMENT", "DocumentComment: Sample Comment", "DocumentNamespace: Sample Comment", - "ExternalDocumentRef: DocumentRef-spdx-tool-1.2:htp://spdx.org:SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "ExternalDocumentRef: DocumentRef-spdx-tool-1.2:htp://spdx.org:SHA1: " + "d6a770ba38583ed4bb4525bd96e50461655d2759", "Creator: Person Bob (bob@example.com)", "Creator: Organization: Acme [email]", "Created: 2010-02-03T00:00:0Z", @@ -117,7 +120,8 @@ def test_parse_creation_info(): ), ( "ExternalDocumentRef: Document_ref document_uri SHA1: afded", - 'Error while parsing CreationInfo: ["Error while parsing ExternalDocumentRef: Couldn\'t match Checksum. Line: 1"]', + "Error while parsing CreationInfo: [\"Error while parsing ExternalDocumentRef: Couldn't match " + 'Checksum. Line: 1"]', ), ] ), diff --git a/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py b/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py index 4107cc78b..f97bff015 100644 --- a/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py @@ -22,9 +22,9 @@ def test_parse_extracted_licensing_info(): extracted_licensing_info_str = "\n".join( [ "LicenseID: LicenseRef-Beerware-4.2", - 'ExtractedText: "THE BEER-WARE LICENSE" (Revision 42): phk@FreeBSD.ORG wrote this file. As long as you ' - "retain this notice you can do whatever you want with this stuff. If we meet some day, and you think this " - "stuff is worth it, you can buy me a beer in return Poul-Henning Kamp" + 'ExtractedText: "THE BEER-WARE LICENSE" (Revision 42): phk@FreeBSD.ORG wrote this file. As long as' + " you retain this notice you can do whatever you want with this stuff. If we meet some day, and you think " + "this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", "LicenseName: Beer-Ware License (Version 42)", "LicenseCrossReference: http://people.freebsd.org/~phk/", "LicenseCrossReference: http://another.cross.reference/", @@ -55,8 +55,8 @@ def test_parse_invalid_extracted_licensing_info(): extracted_licensing_info_str = "\n".join( [ 'ExtractedText: "THE BEER-WARE LICENSE" (Revision 42): phk@FreeBSD.ORG wrote this file. ' - "As long as you retain this notice you can do whatever you want with this stuff. If we meet some day, and you " - "think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "As long as you retain this notice you can do whatever you want with this stuff. If we meet some day, " + "and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", "LicenseName: Beer-Ware License (Version 42)", "LicenseCrossReference: http://people.freebsd.org/~phk/", "LicenseComment: The beerware license has a couple of other standard variants.", diff --git a/tests/spdx/parser/tagvalue/test_file_parser.py b/tests/spdx/parser/tagvalue/test_file_parser.py index 95cb8e322..ac6148bcd 100644 --- a/tests/spdx/parser/tagvalue/test_file_parser.py +++ b/tests/spdx/parser/tagvalue/test_file_parser.py @@ -32,7 +32,8 @@ def test_parse_file(): "LicenseInfoInFile: NOASSERTION", "FileCopyrightText: Copyright 2014 Acme Inc.", "FileComment: Very long file", - "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts.", + "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts." + "", ] ) document = parser.parse("\n".join([DOCUMENT_STR, file_str])) @@ -63,7 +64,8 @@ def test_parse_invalid_file(): "LicenseInfoInFile: Apache-2.0", "FileCopyrightText: Copyright 2014 Acme Inc.", "FileComment: Very long file", - "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts.", + "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts." + "", ] ) diff --git a/tests/spdx/parser/tagvalue/test_helper_methods.py b/tests/spdx/parser/tagvalue/test_helper_methods.py index 6c0e7eb7a..828083836 100644 --- a/tests/spdx/parser/tagvalue/test_helper_methods.py +++ b/tests/spdx/parser/tagvalue/test_helper_methods.py @@ -38,9 +38,11 @@ "73b4ad9a34e5f76cb2525ea6bb8b1dcf9ba79426b3295bd18bc6d148cba4fcc2ca3cf2630fd481b47caaac9127103933", ), ( - "SHA512: c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f15af43e7cb5547f1a464053", + "SHA512: c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34a" + "eb7ac10f15af43e7cb5547f1a464053", ChecksumAlgorithm.SHA512, - "c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f15af43e7cb5547f1a464053", + "c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f" + "15af43e7cb5547f1a464053", ), ( "SHA3-256: 1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce", @@ -48,14 +50,17 @@ "1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce", ), ( - "SHA3-384: dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166", + "SHA3-384: dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c16" + "6", ChecksumAlgorithm.SHA3_384, "dd9e30747551865b483bd76bd967384dce0e5670d1b1c3f701cffac7f49b1c46791253493835136b3aa5f679e364c166", ), ( - "SHA3-512: 906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d111310266a5d46e2bc1ffbb36", + "SHA3-512: 906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd" + "3a101e1d111310266a5d46e2bc1ffbb36", ChecksumAlgorithm.SHA3_512, - "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d111310266a5d46e2bc1ffbb36", + "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d11" + "1310266a5d46e2bc1ffbb36", ), ( "BLAKE2b-256: a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7", @@ -63,19 +68,26 @@ "a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7", ), ( - "BLAKE2B-384: 902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2", + "BLAKE2B-384: 902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4" + "d0b2", ChecksumAlgorithm.BLAKE2B_384, "902511afc8939c0193d87857f45a19eddfd7e0413b0f8701a3baaf1b025f882b45a8fbf623fa0ad79b64850ac7a4d0b2", ), ( - "BLAKE2B-512: 72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8c4af74dce531ca8ebd8824c", + "BLAKE2B-512: 72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945" + "470842d90b5e8c4af74dce531ca8ebd8824c", ChecksumAlgorithm.BLAKE2B_512, - "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8c4af74dce531ca8ebd8824c", + "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8" + "c4af74dce531ca8ebd8824c", ), ( - "BLAKE3: a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed", + "BLAKE3: a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67" + "239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967" + "a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed", ChecksumAlgorithm.BLAKE3, - "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed", + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dc" + "ec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a1300685" + "7d3b9985174bf67239874dcec4cbbc9839496179feafed", ), ("MD2: af1eec2a1b18886c3f3cc244349d91d8", ChecksumAlgorithm.MD2, "af1eec2a1b18886c3f3cc244349d91d8"), ("MD4: d4c41ce30a517d6ce9d79c8c17bb4b66", ChecksumAlgorithm.MD4, "d4c41ce30a517d6ce9d79c8c17bb4b66"), diff --git a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py index e9010eb70..2a8bb670b 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py @@ -58,8 +58,10 @@ def test_tokenization_of_document(lexer): def test_tokenization_of_external_document_references(lexer): data = "\n".join( [ - "ExternalDocumentRef:DocumentRef-spdx-tool-2.1 http://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", - "ExternalDocumentRef:DocumentRef-spdx-tool-2.1 ldap://[2001:db8::7]/c=GB?objectClass?one SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "ExternalDocumentRef:DocumentRef-spdx-tool-2.1 http://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3" + "-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "ExternalDocumentRef:DocumentRef-spdx-tool-2.1 ldap://[2001:db8::7]/c=GB?objectClass?one " + "SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", ] ) lexer.input(data) @@ -67,14 +69,16 @@ def test_tokenization_of_external_document_references(lexer): token_assert_helper( lexer.token(), "LINE", - "DocumentRef-spdx-tool-2.1 http://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "DocumentRef-spdx-tool-2.1 http://spdx.org/spdxdocs/spdx-tools-v2.1-3F2504E0-4F89-41D3-9A0C-0305E82C3301 " + "SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", 1, ) token_assert_helper(lexer.token(), "EXT_DOC_REF", "ExternalDocumentRef", 2) token_assert_helper( lexer.token(), "LINE", - "DocumentRef-spdx-tool-2.1 ldap://[2001:db8::7]/c=GB?objectClass?one SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "DocumentRef-spdx-tool-2.1 ldap://[2001:db8::7]/c=GB?objectClass?one " + "SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", 2, ) @@ -91,7 +95,8 @@ def test_tokenization_of_file(lexer): "LicenseInfoInFile: Apache-2.0", "FileCopyrightText: Copyright 2014 Acme Inc.", "FileComment: Very long file", - "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts.", + "FileAttributionText: Acknowledgements that might be required to be communicated in some contexts." + "", ] ) diff --git a/tests/spdx/validation/test_checksum_validator.py b/tests/spdx/validation/test_checksum_validator.py index 12c89bccf..7f4ae51d5 100644 --- a/tests/spdx/validation/test_checksum_validator.py +++ b/tests/spdx/validation/test_checksum_validator.py @@ -32,7 +32,8 @@ ), Checksum( ChecksumAlgorithm.SHA512, - "c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f15af43e7cb5547f1a464053", + "c2aa8a5d297f5e888ce9a30d3745ccc5a628533449a9f98524de3d23695a268f394a67faf8ef370727c2946f1dbbec34aeb7ac10f" + "15af43e7cb5547f1a464053", ), Checksum(ChecksumAlgorithm.SHA3_256, "1e772489c042f49aeaae32b00fc5ef170a25afa741cffaafadde597d4d1727ce"), Checksum( @@ -41,7 +42,8 @@ ), Checksum( ChecksumAlgorithm.SHA3_512, - "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d111310266a5d46e2bc1ffbb36", + "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d11" + "1310266a5d46e2bc1ffbb36", ), Checksum(ChecksumAlgorithm.BLAKE2B_256, "a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7"), Checksum( @@ -50,11 +52,14 @@ ), Checksum( ChecksumAlgorithm.BLAKE2B_512, - "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8c4af74dce531ca8ebd8824c", + "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8" + "c4af74dce531ca8ebd8824c", ), Checksum( ChecksumAlgorithm.BLAKE3, - "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed", + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874d" + "cec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006" + "857d3b9985174bf67239874dcec4cbbc9839496179feafed", ), Checksum(ChecksumAlgorithm.MD2, "af1eec2a1b18886c3f3cc244349d91d8"), Checksum(ChecksumAlgorithm.MD4, "d4c41ce30a517d6ce9d79c8c17bb4b66"), @@ -77,78 +82,106 @@ def test_valid_checksum(checksum): [ ( Checksum(ChecksumAlgorithm.SHA1, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA1 must consist of 40 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.SHA1 must consist of 40 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.SHA224, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA224 must consist of 56 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.SHA224 must consist of 56 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.SHA256, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA256 must consist of 64 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.SHA256 must consist of 64 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.SHA384, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA384 must consist of 96 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.SHA384 must consist of 96 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.SHA512, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA512 must consist of 128 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.SHA512 must consist of 128 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.SHA3_256, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA3_256 must consist of 64 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.SHA3_256 must consist of 64 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.SHA3_384, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA3_384 must consist of 96 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.SHA3_384 must consist of 96 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.SHA3_512, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.SHA3_512 must consist of 128 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.SHA3_512 must consist of 128 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.BLAKE2B_256, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.BLAKE2B_256 must consist of 64 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.BLAKE2B_256 must consist of 64 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.BLAKE2B_384, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.BLAKE2B_384 must consist of 96 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.BLAKE2B_384 must consist of 96 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.BLAKE2B_512, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.BLAKE2B_512 must consist of 128 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.BLAKE2B_512 must consist of 128 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.BLAKE3, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.BLAKE3 must consist of at least 256 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.BLAKE3 must consist of at least 256 lowercase hexadecimal digits, but is: af1e" + "ec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.MD2, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), - "value of ChecksumAlgorithm.MD2 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364f3ebbb42c484ff43d00791c (length: 40 digits)", + "value of ChecksumAlgorithm.MD2 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364" + "f3ebbb42c484ff43d00791c (length: 40 digits)", ), ( Checksum(ChecksumAlgorithm.MD4, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), - "value of ChecksumAlgorithm.MD4 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364f3ebbb42c484ff43d00791c (length: 40 digits)", + "value of ChecksumAlgorithm.MD4 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364" + "f3ebbb42c484ff43d00791c (length: 40 digits)", ), ( Checksum(ChecksumAlgorithm.MD5, "71c4025dd9897b364f3ebbb42c484ff43d00791c"), - "value of ChecksumAlgorithm.MD5 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364f3ebbb42c484ff43d00791c (length: 40 digits)", + "value of ChecksumAlgorithm.MD5 must consist of 32 lowercase hexadecimal digits, but is: 71c4025dd9897b364" + "f3ebbb42c484ff43d00791c (length: 40 digits)", ), ( Checksum( ChecksumAlgorithm.MD6, - "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed5", + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf672398" + "74dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967" + "a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582" + "b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b" + "5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc983949617" + "9feafed5", ), - "value of ChecksumAlgorithm.MD6 must consist of between 0 and 512 lowercase hexadecimal digits, but is: a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed5 (length: 513 digits)", + "value of ChecksumAlgorithm.MD6 must consist of between 0 and 512 lowercase hexadecimal digits, but is: " + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dc" + "ec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a1300685" + "7d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6a" + "c3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341" + "bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed5 " + "(length: 513 digits)", ), ( Checksum(ChecksumAlgorithm.ADLER32, "af1eec2a1b18886c3f3cc244349d91d8"), - "value of ChecksumAlgorithm.ADLER32 must consist of 8 lowercase hexadecimal digits, but is: af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", + "value of ChecksumAlgorithm.ADLER32 must consist of 8 lowercase hexadecimal digits, but is: " + "af1eec2a1b18886c3f3cc244349d91d8 (length: 32 digits)", ), ( Checksum(ChecksumAlgorithm.SHA1, "CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4"), - "value of ChecksumAlgorithm.SHA1 must consist of 40 lowercase hexadecimal digits, but is: CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4 (length: 40 digits)", + "value of ChecksumAlgorithm.SHA1 must consist of 40 lowercase hexadecimal digits, but is: " + "CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4 (length: 40 digits)", ), ], ) @@ -174,7 +207,8 @@ def test_invalid_checksum(checksum, expected_message): ), Checksum( ChecksumAlgorithm.SHA3_512, - "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d111310266a5d46e2bc1ffbb36", + "906bca5580be8c95ae44f775363fb69968ad568898dfb03e0ff96cd9445a0b75f817b68e5c1e80ad624031f851cfddd3a101e1d1" + "11310266a5d46e2bc1ffbb36", ), Checksum(ChecksumAlgorithm.BLAKE2B_256, "a0eb3ddfa5807780a562b9c313b2537f1e8dc621e9a524f8c1ffcf07a79e35c7"), Checksum( @@ -183,11 +217,14 @@ def test_invalid_checksum(checksum, expected_message): ), Checksum( ChecksumAlgorithm.BLAKE2B_512, - "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e8c4af74dce531ca8ebd8824c", + "72c23b0160e1af3cb159f0cc96210c5e9aecc5a65d4618566776fa6117bf84929dcef56c7f8b087691c23000c945470842d90b5e" + "8c4af74dce531ca8ebd8824c", ), Checksum( ChecksumAlgorithm.BLAKE3, - "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874dcec4cbbc9839496179feafed", + "a872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006857d3b9985174bf67239874" + "dcec4cbbc9839496179feafeda872cac2efd29ed2ad8b5faa79b63f983341bea41183582b8863d952f6ac3e1cdfe0189967a13006" + "857d3b9985174bf67239874dcec4cbbc9839496179feafed", ), Checksum(ChecksumAlgorithm.ADLER32, "02ec0130"), ], diff --git a/tests/spdx/validation/test_creation_info_validator.py b/tests/spdx/validation/test_creation_info_validator.py index 79274c906..b278e2f0c 100644 --- a/tests/spdx/validation/test_creation_info_validator.py +++ b/tests/spdx/validation/test_creation_info_validator.py @@ -37,7 +37,8 @@ def test_valid_creation_info(): ( creation_info_fixture(document_namespace="some_namespace"), "SPDXRef-DOCUMENT", - "document_namespace must be a valid URI specified in RFC-3986 and must contain no fragment (#), but is: some_namespace", + "document_namespace must be a valid URI specified in RFC-3986 and must contain no fragment (#), " + "but is: some_namespace", ), ], ) diff --git a/tests/spdx/validation/test_document_validator.py b/tests/spdx/validation/test_document_validator.py index c5cc55c64..d26258b63 100644 --- a/tests/spdx/validation/test_document_validator.py +++ b/tests/spdx/validation/test_document_validator.py @@ -60,7 +60,8 @@ def test_valid_document(): ( creation_info_fixture(spdx_version="SPDX-2.1"), "SPDX-2.1", - 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s spdx_version is: SPDX-2.1', + 'only SPDX versions "SPDX-2.2" and "SPDX-2.3" are supported, but the document\'s ' + "spdx_version is: SPDX-2.1", ), ], ) @@ -107,7 +108,8 @@ def test_document_does_not_describe_an_element(): assert validation_messages == [ ValidationMessage( - 'there must be at least one relationship "SPDXRef-DOCUMENT DESCRIBES ..." or "... DESCRIBED_BY SPDXRef-DOCUMENT"', + 'there must be at least one relationship "SPDXRef-DOCUMENT DESCRIBES ..." or "... DESCRIBED_BY ' + 'SPDXRef-DOCUMENT"', ValidationContext(spdx_id="SPDXRef-DOCUMENT", element_type=SpdxElementType.DOCUMENT), ) ] @@ -130,7 +132,8 @@ def test_duplicated_spdx_ids(): assert validation_messages == [ ValidationMessage( - "every spdx_id must be unique within the document, but found the following duplicates: ['SPDXRef-2', 'SPDXRef-3', 'SPDXRef-DOCUMENT']", + "every spdx_id must be unique within the document, but found the following duplicates: ['SPDXRef-2', " + "'SPDXRef-3', 'SPDXRef-DOCUMENT']", context, ) ] diff --git a/tests/spdx/validation/test_external_package_ref_validator.py b/tests/spdx/validation/test_external_package_ref_validator.py index 8037141d1..b3dfa48d8 100644 --- a/tests/spdx/validation/test_external_package_ref_validator.py +++ b/tests/spdx/validation/test_external_package_ref_validator.py @@ -39,7 +39,8 @@ ( ExternalPackageRefCategory.SECURITY, "url", - "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/secp256k1_twist_attacks.md", + "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/" + "secp256k1_twist_attacks.md", ), (ExternalPackageRefCategory.SECURITY, "swid", "swid:2df9de35-0aff-4a86-ace6-f7dddd1ade4c"), (ExternalPackageRefCategory.PACKAGE_MANAGER, "maven-central", "org.apache.tomcat:tomcat:9.0.0.M4"), @@ -120,13 +121,15 @@ def test_valid_external_package_ref(category, reference_type, locator): ExternalPackageRefCategory.SECURITY, "cpe22Typo", "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", - "externalPackageRef type in category SECURITY must be one of ['cpe22Type', 'cpe23Type', 'advisory', 'fix', 'url', 'swid'], but is: cpe22Typo", + "externalPackageRef type in category SECURITY must be one of ['cpe22Type', 'cpe23Type', 'advisory', 'fix'" + ", 'url', 'swid'], but is: cpe22Typo", ), ( ExternalPackageRefCategory.PACKAGE_MANAGER, "nugat", "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", - "externalPackageRef type in category PACKAGE_MANAGER must be one of ['maven-central', 'npm', 'nuget', 'bower', 'purl'], but is: nugat", + "externalPackageRef type in category PACKAGE_MANAGER must be one of ['maven-central', 'npm', 'nuget'," + " 'bower', 'purl'], but is: nugat", ), ( ExternalPackageRefCategory.PERSISTENT_ID, @@ -160,85 +163,96 @@ def test_invalid_external_package_ref_types(category, reference_type, locator, e ExternalPackageRefCategory.SECURITY, "cpe22Type", "cpe:o:canonical:ubuntu_linux:10.04:-:lts", - f'externalPackageRef locator of type "cpe22Type" must conform with the regex {CPE22TYPE_REGEX}, but is: cpe:o:canonical:ubuntu_linux:10.04:-:lts', + f'externalPackageRef locator of type "cpe22Type" must conform with the regex {CPE22TYPE_REGEX}, but is: ' + f"cpe:o:canonical:ubuntu_linux:10.04:-:lts", ), ( ExternalPackageRefCategory.SECURITY, "cpe23Type", "cpe:2.3:/o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*", - f'externalPackageRef locator of type "cpe23Type" must conform with the regex {CPE23TYPE_REGEX}, but is: cpe:2.3:/o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*', + f'externalPackageRef locator of type "cpe23Type" must conform with the regex {CPE23TYPE_REGEX}, but is: ' + f"cpe:2.3:/o:canonical:ubuntu_linux:10.04:-:lts:*:*:*:*:*", ), ( ExternalPackageRefCategory.SECURITY, "advisory", "http://locatorurl", - f'externalPackageRef locator of type "advisory" must be a valid URL, but is: http://locatorurl', + 'externalPackageRef locator of type "advisory" must be a valid URL, but is: http://locatorurl', ), ( ExternalPackageRefCategory.SECURITY, "fix", "http://fixurl", - f'externalPackageRef locator of type "fix" must be a valid URL, but is: http://fixurl', + 'externalPackageRef locator of type "fix" must be a valid URL, but is: http://fixurl', ), ( ExternalPackageRefCategory.SECURITY, "url", "http://url", - f'externalPackageRef locator of type "url" must be a valid URL, but is: http://url', + 'externalPackageRef locator of type "url" must be a valid URL, but is: http://url', ), ( ExternalPackageRefCategory.SECURITY, "swid", "2df9de35-0aff-4a86-ace6-f7dddd1ade4c", - f'externalPackageRef locator of type "swid" must be a valid URI with scheme swid, but is: 2df9de35-0aff-4a86-ace6-f7dddd1ade4c', + 'externalPackageRef locator of type "swid" must be a valid URI with scheme swid, but is: ' + "2df9de35-0aff-4a86-ace6-f7dddd1ade4c", ), ( ExternalPackageRefCategory.PACKAGE_MANAGER, "maven-central", "org.apache.tomcat:tomcat:tomcat:9.0.0.M4", - f'externalPackageRef locator of type "maven-central" must conform with the regex {MAVEN_CENTRAL_REGEX}, but is: org.apache.tomcat:tomcat:tomcat:9.0.0.M4', + f'externalPackageRef locator of type "maven-central" must conform with the regex {MAVEN_CENTRAL_REGEX}, ' + f"but is: org.apache.tomcat:tomcat:tomcat:9.0.0.M4", ), ( ExternalPackageRefCategory.PACKAGE_MANAGER, "npm", "http-server:0.3.0", - f'externalPackageRef locator of type "npm" must conform with the regex {NPM_REGEX}, but is: http-server:0.3.0', + f'externalPackageRef locator of type "npm" must conform with the regex {NPM_REGEX}, ' + f"but is: http-server:0.3.0", ), ( ExternalPackageRefCategory.PACKAGE_MANAGER, "nuget", "Microsoft.AspNet.MVC@5.0.0", - f'externalPackageRef locator of type "nuget" must conform with the regex {NUGET_REGEX}, but is: Microsoft.AspNet.MVC@5.0.0', + f'externalPackageRef locator of type "nuget" must conform with the regex {NUGET_REGEX}, ' + f"but is: Microsoft.AspNet.MVC@5.0.0", ), ( ExternalPackageRefCategory.PACKAGE_MANAGER, "bower", "modernizr:2.6.2", - f'externalPackageRef locator of type "bower" must conform with the regex {BOWER_REGEX}, but is: modernizr:2.6.2', + f'externalPackageRef locator of type "bower" must conform with the regex {BOWER_REGEX}, ' + f"but is: modernizr:2.6.2", ), ( ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "pkg:npm@12.3.1", - f'externalPackageRef locator of type "purl" must conform with the regex {PURL_REGEX}, but is: pkg:npm@12.3.1', + f'externalPackageRef locator of type "purl" must conform with the regex {PURL_REGEX}, ' + f"but is: pkg:npm@12.3.1", ), ( ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2", - f'externalPackageRef locator of type "swh" must conform with the regex {SWH_REGEX}, but is: swh:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2', + f'externalPackageRef locator of type "swh" must conform with the regex {SWH_REGEX}, ' + f"but is: swh:cnt:94a9ed024d3859793618152ea559a168bbcbb5e2", ), ( ExternalPackageRefCategory.PERSISTENT_ID, "gitoid", "gitoid:blob:sha1:3557f7eb43c621c71483743d4b37059bb80933e7f71277c0c3b3846159d1f61c", - f'externalPackageRef locator of type "gitoid" must conform with the regex {GITOID_REGEX}, but is: gitoid:blob:sha1:3557f7eb43c621c71483743d4b37059bb80933e7f71277c0c3b3846159d1f61c', + f'externalPackageRef locator of type "gitoid" must conform with the regex {GITOID_REGEX}, ' + f"but is: gitoid:blob:sha1:3557f7eb43c621c71483743d4b37059bb80933e7f71277c0c3b3846159d1f61c", ), ( ExternalPackageRefCategory.PERSISTENT_ID, "gitoid", "gitoid:blob:sha256:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64", - f'externalPackageRef locator of type "gitoid" must conform with the regex {GITOID_REGEX}, but is: gitoid:blob:sha256:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64', + f'externalPackageRef locator of type "gitoid" must conform with the regex {GITOID_REGEX},' + f" but is: gitoid:blob:sha256:261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64", ), ( ExternalPackageRefCategory.OTHER, @@ -273,7 +287,8 @@ def test_invalid_external_package_ref_locators(category, reference_type, locator ( ExternalPackageRefCategory.SECURITY, "url", - "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/secp256k1_twist_attacks.md", + "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/" + "secp256k1_twist_attacks.md", ), (ExternalPackageRefCategory.SECURITY, "swid", "swid:2df9de35-0aff-4a86-ace6-f7dddd1ade4c"), ], diff --git a/tests/spdx/validation/test_file_validator.py b/tests/spdx/validation/test_file_validator.py index 5caedeee9..e215d56c9 100644 --- a/tests/spdx/validation/test_file_validator.py +++ b/tests/spdx/validation/test_file_validator.py @@ -33,12 +33,12 @@ def test_valid_file(): ( file_fixture(name="/invalid/file/name"), file_fixture().spdx_id, - f'file name must not be an absolute path starting with "/", but is: /invalid/file/name', + 'file name must not be an absolute path starting with "/", but is: /invalid/file/name', ), ( file_fixture(checksums=[Checksum(ChecksumAlgorithm.MD2, "d4c41ce30a517d6ce9d79c8c17bb4b66")]), file_fixture().spdx_id, - f"checksums must contain a SHA1 algorithm checksum, but only contains: []", + "checksums must contain a SHA1 algorithm checksum, but only contains: []", ), ], ) diff --git a/tests/spdx/validation/test_license_expression_validator.py b/tests/spdx/validation/test_license_expression_validator.py index 579f0f2c0..4a81ec525 100644 --- a/tests/spdx/validation/test_license_expression_validator.py +++ b/tests/spdx/validation/test_license_expression_validator.py @@ -87,7 +87,8 @@ def test_invalid_license_expression_with_unknown_symbols(expression_string, unkn validation_messages: List[ValidationMessage] = validate_license_expression(license_expression, document, parent_id) expected_messages = [ ValidationMessage( - f"Unrecognized license reference: {symbol}. license_expression must only use IDs from the license list or extracted licensing info, but is: {license_expression}", + f"Unrecognized license reference: {symbol}. license_expression must only use IDs from the license list or " + f"extracted licensing info, but is: {license_expression}", context, ) for symbol in unknown_symbols @@ -101,23 +102,30 @@ def test_invalid_license_expression_with_unknown_symbols(expression_string, unkn [ ( "MIT with MIT", - 'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "MIT" at position: 9. for license_expression: MIT WITH MIT', + 'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "MIT" at ' + "position: 9. for license_expression: MIT WITH MIT", ), ( f"GPL-2.0-or-later and {FIXTURE_LICENSE_ID} with {FIXTURE_LICENSE_ID}", - f'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "{FIXTURE_LICENSE_ID}" at position: 39. for license_expression: GPL-2.0-or-later AND {FIXTURE_LICENSE_ID} WITH {FIXTURE_LICENSE_ID}', + f'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: ' + f'"{FIXTURE_LICENSE_ID}" at position: 39. for license_expression: GPL-2.0-or-later AND ' + f"{FIXTURE_LICENSE_ID} WITH {FIXTURE_LICENSE_ID}", ), ( f"GPL-2.0-or-later with MIT and {FIXTURE_LICENSE_ID} with GPL-2.0-or-later", - f'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "MIT" at position: 22. for license_expression: GPL-2.0-or-later WITH MIT AND {FIXTURE_LICENSE_ID} WITH GPL-2.0-or-later', + f'A plain license symbol cannot be used as an exception in a "WITH symbol" statement. for token: "MIT" at ' + f"position: 22. for license_expression: GPL-2.0-or-later WITH MIT AND {FIXTURE_LICENSE_ID} " + f"WITH GPL-2.0-or-later", ), ( "389-exception with 389-exception", - 'A license exception symbol can only be used as an exception in a "WITH exception" statement. for token: "389-exception". for license_expression: 389-exception WITH 389-exception', + 'A license exception symbol can only be used as an exception in a "WITH exception" statement. for token: ' + '"389-exception". for license_expression: 389-exception WITH 389-exception', ), ( "389-exception with MIT", - 'A license exception symbol can only be used as an exception in a "WITH exception" statement. for token: "389-exception". for license_expression: 389-exception WITH MIT', + 'A license exception symbol can only be used as an exception in a "WITH exception" statement. for token: ' + '"389-exception". for license_expression: 389-exception WITH MIT', ), ], ) diff --git a/tests/spdx/validation/test_package_validator.py b/tests/spdx/validation/test_package_validator.py index 58e021b4a..24ecd6160 100644 --- a/tests/spdx/validation/test_package_validator.py +++ b/tests/spdx/validation/test_package_validator.py @@ -39,7 +39,8 @@ def test_valid_package(): package_fixture( files_analyzed=False, verification_code=package_verification_code_fixture(), license_info_from_files=[] ), - f"verification_code must be None if files_analyzed is False, but is: {package_verification_code_fixture()}", + f"verification_code must be None if files_analyzed is False, but is: " + f"{package_verification_code_fixture()}", ), ( package_fixture(files_analyzed=False, license_info_from_files=[SpdxNone()], verification_code=None), diff --git a/tests/spdx/validation/test_package_verification_code_validator.py b/tests/spdx/validation/test_package_verification_code_validator.py index 963eb29a8..d6ddb1548 100644 --- a/tests/spdx/validation/test_package_verification_code_validator.py +++ b/tests/spdx/validation/test_package_verification_code_validator.py @@ -28,11 +28,13 @@ def test_valid_package_verification_code(): [ ( PackageVerificationCode("71c4025dd9897b364f3ebbb42c484ff43d00791cab", []), - "value of verification_code must consist of 40 lowercase hexadecimal digits, but is: 71c4025dd9897b364f3ebbb42c484ff43d00791cab (length: 42 digits)", + "value of verification_code must consist of 40 lowercase hexadecimal digits, but is: " + "71c4025dd9897b364f3ebbb42c484ff43d00791cab (length: 42 digits)", ), ( PackageVerificationCode("CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4", []), - "value of verification_code must consist of 40 lowercase hexadecimal digits, but is: CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4 (length: 40 digits)", + "value of verification_code must consist of 40 lowercase hexadecimal digits, but is: " + "CE9F343C4BA371746FD7EAD9B59031AE34D8AFC4 (length: 40 digits)", ), ( PackageVerificationCode("71c4025dd9897b364f3ebbb42c484ff43d00791c", ["/invalid/excluded/file"]), diff --git a/tests/spdx/validation/test_spdx_id_validators.py b/tests/spdx/validation/test_spdx_id_validators.py index 12ca03f7e..e29697862 100644 --- a/tests/spdx/validation/test_spdx_id_validators.py +++ b/tests/spdx/validation/test_spdx_id_validators.py @@ -107,34 +107,40 @@ def test_valid_spdx_id(spdx_id): ( "DocumentRef-external:extern:SPDXRef-File", [ - f"spdx_id must not contain more than one colon in order to separate the external document reference id from the internal SPDX id, but is: DocumentRef-external:extern:SPDXRef-File" + "spdx_id must not contain more than one colon in order to separate the external document reference id" + " from the internal SPDX id, but is: DocumentRef-external:extern:SPDXRef-File" ], ), ( "DocumentRef external:SPDXRef-File", [ - 'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: DocumentRef external', + 'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" ' + 'and must begin with "DocumentRef-", but is: DocumentRef external', 'did not find the external document reference "DocumentRef external" in the SPDX document', ], ), ( "DocRef-ext:SPDXRef-File_2", [ - 'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" and must begin with "DocumentRef-", but is: DocRef-ext', - 'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: SPDXRef-File_2', + 'the external document reference part of spdx_id must only contain letters, numbers, ".", "-" and "+" ' + 'and must begin with "DocumentRef-", but is: DocRef-ext', + 'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin ' + 'with "SPDXRef-", but is: SPDXRef-File_2', 'did not find the external document reference "DocRef-ext" in the SPDX document', ], ), ( "DocumentRef-external:SPDXRef-File_2", [ - 'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: SPDXRef-File_2' + 'the internal SPDX id part of spdx_id must only contain letters, numbers, "." and "-" and must begin ' + 'with "SPDXRef-", but is: SPDXRef-File_2' ], ), ( "SPDXRef-42+", [ - 'spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: SPDXRef-42+' + 'spdx_id must only contain letters, numbers, "." and "-" and must begin with "SPDXRef-", but is: ' + "SPDXRef-42+" ], ), ], diff --git a/tests/spdx/validation/test_uri_validators.py b/tests/spdx/validation/test_uri_validators.py index b4a641786..59a8dd1e5 100644 --- a/tests/spdx/validation/test_uri_validators.py +++ b/tests/spdx/validation/test_uri_validators.py @@ -131,7 +131,8 @@ def test_invalid_uri(input_value): @pytest.mark.parametrize("input_value", ["://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82..."]) @pytest.mark.skip( - "validate_uri() seems to invalidate URIs without scheme, so it does not run into this case. But I'm not sure yet if this covers all scheme-less examples." + "validate_uri() seems to invalidate URIs without scheme, so it does not run into this case. But I'm not sure yet " + "if this covers all scheme-less examples." "https://github.com/spdx/tools-python/issues/377" ) def test_uri_without_scheme(input_value): diff --git a/tests/spdx/writer/tagvalue/test_creation_info_writer.py b/tests/spdx/writer/tagvalue/test_creation_info_writer.py index e54879ee6..161d4047e 100644 --- a/tests/spdx/writer/tagvalue/test_creation_info_writer.py +++ b/tests/spdx/writer/tagvalue/test_creation_info_writer.py @@ -25,7 +25,8 @@ call("DocumentComment: documentComment\n"), call("\n## External Document References\n"), call( - "ExternalDocumentRef: DocumentRef-external https://namespace.com SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n" + "ExternalDocumentRef: DocumentRef-external https://namespace.com " + "SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n" ), call("\n"), call("## Creation Information\n"), From f66fdcad7ffce110acc11f8974270c0b05731def Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 30 Mar 2023 11:07:40 +0200 Subject: [PATCH 033/354] fix GitHub Action Signed-off-by: Meret Behrens --- .github/workflows/check_codestyle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_codestyle.yml b/.github/workflows/check_codestyle.yml index aa05fce9f..89f6a13b5 100644 --- a/.github/workflows/check_codestyle.yml +++ b/.github/workflows/check_codestyle.yml @@ -25,7 +25,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Installation - run: pip install ".[codestyle]" + run: pip install ".[code_style]" - name: Check code with isort run: | isort src tests --check From bde2774124735aac9397003fc0986c31a7b9d7b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 30 Mar 2023 12:28:13 +0200 Subject: [PATCH 034/354] [issue-511] replace license text with SPDX license identifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx/casing_tools.py | 13 +++---------- src/spdx/clitools/pyspdxtools.py | 2 ++ src/spdx/datetime_conversions.py | 13 +++---------- src/spdx/document_utils.py | 13 +++---------- src/spdx/formats.py | 13 +++---------- src/spdx/jsonschema/annotation_converter.py | 13 +++---------- src/spdx/jsonschema/annotation_properties.py | 13 +++---------- src/spdx/jsonschema/checksum_converter.py | 13 +++---------- src/spdx/jsonschema/checksum_properties.py | 13 +++---------- src/spdx/jsonschema/converter.py | 13 +++---------- src/spdx/jsonschema/creation_info_converter.py | 13 +++---------- src/spdx/jsonschema/creation_info_properties.py | 13 +++---------- src/spdx/jsonschema/document_converter.py | 13 +++---------- src/spdx/jsonschema/document_properties.py | 13 +++---------- .../jsonschema/external_document_ref_converter.py | 13 +++---------- .../jsonschema/external_document_ref_properties.py | 13 +++---------- .../jsonschema/external_package_ref_converter.py | 13 +++---------- .../jsonschema/external_package_ref_properties.py | 13 +++---------- .../extracted_licensing_info_converter.py | 13 +++---------- .../extracted_licensing_info_properties.py | 13 +++---------- src/spdx/jsonschema/file_converter.py | 13 +++---------- src/spdx/jsonschema/file_properties.py | 13 +++---------- src/spdx/jsonschema/json_property.py | 13 +++---------- src/spdx/jsonschema/optional_utils.py | 13 +++---------- src/spdx/jsonschema/package_converter.py | 13 +++---------- src/spdx/jsonschema/package_properties.py | 13 +++---------- .../package_verification_code_converter.py | 13 +++---------- .../package_verification_code_properties.py | 13 +++---------- src/spdx/jsonschema/relationship_converter.py | 13 +++---------- src/spdx/jsonschema/relationship_properties.py | 13 +++---------- src/spdx/jsonschema/snippet_converter.py | 13 +++---------- src/spdx/jsonschema/snippet_properties.py | 13 +++---------- src/spdx/model/actor.py | 13 +++---------- src/spdx/model/annotation.py | 13 +++---------- src/spdx/model/checksum.py | 13 +++---------- src/spdx/model/document.py | 13 +++---------- src/spdx/model/external_document_ref.py | 13 +++---------- src/spdx/model/extracted_licensing_info.py | 13 +++---------- src/spdx/model/file.py | 13 +++---------- src/spdx/model/package.py | 13 +++---------- src/spdx/model/relationship.py | 13 +++---------- src/spdx/model/relationship_filters.py | 13 +++---------- src/spdx/model/snippet.py | 13 +++---------- src/spdx/model/spdx_no_assertion.py | 13 +++---------- src/spdx/model/spdx_none.py | 13 +++---------- src/spdx/model/version.py | 13 +++---------- src/spdx/parser/actor_parser.py | 13 +++---------- src/spdx/parser/error.py | 13 +++---------- src/spdx/parser/json/json_parser.py | 13 +++---------- src/spdx/parser/jsonlikedict/annotation_parser.py | 13 +++---------- src/spdx/parser/jsonlikedict/checksum_parser.py | 13 +++---------- .../parser/jsonlikedict/creation_info_parser.py | 13 +++---------- .../parser/jsonlikedict/dict_parsing_functions.py | 13 +++---------- .../jsonlikedict/extracted_licensing_info_parser.py | 13 +++---------- src/spdx/parser/jsonlikedict/file_parser.py | 13 +++---------- .../parser/jsonlikedict/json_like_dict_parser.py | 13 +++---------- .../jsonlikedict/license_expression_parser.py | 13 +++---------- src/spdx/parser/jsonlikedict/package_parser.py | 13 +++---------- src/spdx/parser/jsonlikedict/relationship_parser.py | 13 +++---------- src/spdx/parser/jsonlikedict/snippet_parser.py | 13 +++---------- src/spdx/parser/logger.py | 13 +++---------- src/spdx/parser/parsing_functions.py | 13 +++---------- src/spdx/parser/rdf/annotation_parser.py | 13 +++---------- src/spdx/parser/rdf/checksum_parser.py | 13 +++---------- src/spdx/parser/rdf/creation_info_parser.py | 13 +++---------- .../parser/rdf/extracted_licensing_info_parser.py | 13 +++---------- src/spdx/parser/rdf/file_parser.py | 13 +++---------- src/spdx/parser/rdf/graph_parsing_functions.py | 13 +++---------- src/spdx/parser/rdf/license_expression_parser.py | 13 +++---------- src/spdx/parser/rdf/package_parser.py | 13 +++---------- src/spdx/parser/rdf/rdf_parser.py | 13 +++---------- src/spdx/parser/rdf/relationship_parser.py | 13 +++---------- src/spdx/parser/rdf/snippet_parser.py | 13 +++---------- src/spdx/parser/tagvalue/helper_methods.py | 13 +++---------- src/spdx/parser/tagvalue/lexer.py | 1 + src/spdx/parser/tagvalue/parser.py | 1 + src/spdx/parser/tagvalue/tagvalue_parser.py | 13 +++---------- src/spdx/parser/xml/xml_parser.py | 13 +++---------- src/spdx/parser/yaml/yaml_parser.py | 13 +++---------- src/spdx/rdfschema/namespace.py | 13 +++---------- src/spdx/validation/actor_validator.py | 13 +++---------- src/spdx/validation/annotation_validator.py | 13 +++---------- src/spdx/validation/checksum_validator.py | 13 +++---------- src/spdx/validation/creation_info_validator.py | 13 +++---------- src/spdx/validation/document_validator.py | 13 +++---------- .../validation/external_document_ref_validator.py | 13 +++---------- .../validation/external_package_ref_validator.py | 13 +++---------- .../extracted_licensing_info_validator.py | 13 +++---------- src/spdx/validation/file_validator.py | 13 +++---------- src/spdx/validation/license_expression_validator.py | 13 +++---------- src/spdx/validation/package_validator.py | 13 +++---------- .../package_verification_code_validator.py | 13 +++---------- src/spdx/validation/relationship_validator.py | 13 +++---------- src/spdx/validation/snippet_validator.py | 13 +++---------- src/spdx/validation/spdx_id_validators.py | 13 +++---------- src/spdx/validation/uri_validators.py | 13 +++---------- src/spdx/validation/validation_message.py | 13 +++---------- src/spdx/writer/json/json_writer.py | 13 +++---------- src/spdx/writer/rdf/annotation_writer.py | 13 +++---------- src/spdx/writer/rdf/checksum_writer.py | 13 +++---------- src/spdx/writer/rdf/creation_info_writer.py | 13 +++---------- src/spdx/writer/rdf/external_document_ref_writer.py | 13 +++---------- .../writer/rdf/extracted_licensing_info_writer.py | 13 +++---------- src/spdx/writer/rdf/file_writer.py | 13 +++---------- src/spdx/writer/rdf/license_expression_writer.py | 13 +++---------- src/spdx/writer/rdf/package_writer.py | 13 +++---------- src/spdx/writer/rdf/rdf_writer.py | 13 +++---------- src/spdx/writer/rdf/relationship_writer.py | 13 +++---------- src/spdx/writer/rdf/snippet_writer.py | 13 +++---------- src/spdx/writer/rdf/writer_utils.py | 13 +++---------- src/spdx/writer/write_anything.py | 13 +++---------- src/spdx/writer/xml/xml_writer.py | 13 +++---------- src/spdx/writer/yaml/yaml_writer.py | 13 +++---------- tests/spdx/fixtures.py | 13 +++---------- tests/spdx/jsonschema/test_annotation_converter.py | 13 +++---------- tests/spdx/jsonschema/test_checksum_converter.py | 13 +++---------- tests/spdx/jsonschema/test_converter.py | 13 +++---------- .../spdx/jsonschema/test_creation_info_converter.py | 13 +++---------- tests/spdx/jsonschema/test_document_converter.py | 13 +++---------- .../test_external_document_ref_converter.py | 13 +++---------- .../test_external_package_ref_converter.py | 13 +++---------- .../test_extracted_licensing_info_converter.py | 13 +++---------- tests/spdx/jsonschema/test_file_converter.py | 13 +++---------- tests/spdx/jsonschema/test_package_converter.py | 13 +++---------- .../test_package_verification_code_converter.py | 13 +++---------- .../spdx/jsonschema/test_relationship_converter.py | 13 +++---------- tests/spdx/jsonschema/test_snippet_converter.py | 13 +++---------- tests/spdx/mock_utils.py | 13 +++---------- tests/spdx/model/test_version.py | 13 +++---------- tests/spdx/parser/json/test_json_parser.py | 13 +++---------- .../parser/jsonlikedict/test_annotation_parser.py | 13 +++---------- .../parser/jsonlikedict/test_checksum_parser.py | 13 +++---------- .../jsonlikedict/test_creation_info_parser.py | 13 +++---------- .../test_extracted_licensing_info_parser.py | 13 +++---------- tests/spdx/parser/jsonlikedict/test_file_parser.py | 13 +++---------- .../jsonlikedict/test_license_expression_parser.py | 13 +++---------- .../spdx/parser/jsonlikedict/test_package_parser.py | 13 +++---------- .../parser/jsonlikedict/test_relationship_parser.py | 13 +++---------- .../spdx/parser/jsonlikedict/test_snippet_parser.py | 13 +++---------- tests/spdx/parser/rdf/test_annotation_parser.py | 13 +++---------- tests/spdx/parser/rdf/test_checksum_parser.py | 13 +++---------- tests/spdx/parser/rdf/test_creation_info_parser.py | 13 +++---------- .../rdf/test_extracted_licensing_info_parser.py | 13 +++---------- tests/spdx/parser/rdf/test_file_parser.py | 13 +++---------- .../spdx/parser/rdf/test_graph_parsing_function.py | 13 +++---------- .../parser/rdf/test_license_expression_parser.py | 13 +++---------- tests/spdx/parser/rdf/test_package_parser.py | 13 +++---------- tests/spdx/parser/rdf/test_rdf_parser.py | 13 +++---------- tests/spdx/parser/rdf/test_relationship_parser.py | 13 +++---------- tests/spdx/parser/rdf/test_snippet_parser.py | 13 +++---------- .../spdx/parser/tagvalue/test_annotation_parser.py | 13 +++---------- .../parser/tagvalue/test_creation_info_parser.py | 13 +++---------- .../test_extracted_licensing_info_parser.py | 13 +++---------- tests/spdx/parser/tagvalue/test_file_parser.py | 13 +++---------- tests/spdx/parser/tagvalue/test_helper_methods.py | 13 +++---------- tests/spdx/parser/tagvalue/test_package_parser.py | 13 +++---------- .../parser/tagvalue/test_relationship_parser.py | 13 +++---------- tests/spdx/parser/tagvalue/test_snippet_parser.py | 13 +++---------- tests/spdx/parser/tagvalue/test_tag_value_lexer.py | 13 +++---------- tests/spdx/parser/tagvalue/test_tag_value_parser.py | 13 +++---------- tests/spdx/test_actor_parser.py | 13 +++---------- tests/spdx/test_casing_tools.py | 13 +++---------- tests/spdx/test_datetime_conversions.py | 13 +++---------- tests/spdx/validation/test_actor_validator.py | 13 +++---------- tests/spdx/validation/test_annotation_validator.py | 13 +++---------- tests/spdx/validation/test_checksum_validator.py | 13 +++---------- .../spdx/validation/test_creation_info_validator.py | 13 +++---------- tests/spdx/validation/test_document_validator.py | 13 +++---------- .../test_external_document_ref_validator.py | 13 +++---------- .../test_external_package_ref_validator.py | 13 +++---------- .../test_extracted_licensing_info_validator.py | 13 +++---------- tests/spdx/validation/test_file_validator.py | 13 +++---------- .../validation/test_license_expression_validator.py | 13 +++---------- tests/spdx/validation/test_package_validator.py | 13 +++---------- .../test_package_verification_code_validator.py | 13 +++---------- .../spdx/validation/test_relationship_validator.py | 13 +++---------- tests/spdx/validation/test_snippet_validator.py | 13 +++---------- tests/spdx/validation/test_spdx_id_validators.py | 13 +++---------- tests/spdx/validation/test_uri_validators.py | 13 +++---------- tests/spdx/writer/json/test_json_writer.py | 13 +++---------- tests/spdx/writer/rdf/test_annotation_writer.py | 13 +++---------- tests/spdx/writer/rdf/test_checksum_writer.py | 13 +++---------- tests/spdx/writer/rdf/test_creation_info_writer.py | 13 +++---------- .../writer/rdf/test_external_document_ref_writer.py | 13 +++---------- .../rdf/test_extracted_licensing_info_writer.py | 13 +++---------- tests/spdx/writer/rdf/test_file_writer.py | 13 +++---------- .../writer/rdf/test_license_expression_writer.py | 13 +++---------- tests/spdx/writer/rdf/test_package_writer.py | 13 +++---------- tests/spdx/writer/rdf/test_rdf_writer.py | 13 +++---------- tests/spdx/writer/rdf/test_relationship_writer.py | 13 +++---------- tests/spdx/writer/rdf/test_snippet_writer.py | 13 +++---------- tests/spdx/writer/rdf/test_writer_utils.py | 13 +++---------- 192 files changed, 571 insertions(+), 1890 deletions(-) diff --git a/src/spdx/casing_tools.py b/src/spdx/casing_tools.py index fdbc07f15..d77ba9222 100644 --- a/src/spdx/casing_tools.py +++ b/src/spdx/casing_tools.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from re import sub diff --git a/src/spdx/clitools/pyspdxtools.py b/src/spdx/clitools/pyspdxtools.py index dece3733f..e5ee38166 100644 --- a/src/spdx/clitools/pyspdxtools.py +++ b/src/spdx/clitools/pyspdxtools.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 # Copyright (c) 2020 Yash Varshney +# Copyright (c) 2023 spdx contributors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/src/spdx/datetime_conversions.py b/src/spdx/datetime_conversions.py index e0a1383bc..e74e09474 100644 --- a/src/spdx/datetime_conversions.py +++ b/src/spdx/datetime_conversions.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime diff --git a/src/spdx/document_utils.py b/src/spdx/document_utils.py index b212cc77b..d3bf3ddcc 100644 --- a/src/spdx/document_utils.py +++ b/src/spdx/document_utils.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Union from spdx.model.document import Document diff --git a/src/spdx/formats.py b/src/spdx/formats.py index 2b6b2d64c..eefd51369 100644 --- a/src/spdx/formats.py +++ b/src/spdx/formats.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from spdx.parser.error import SPDXParsingError diff --git a/src/spdx/jsonschema/annotation_converter.py b/src/spdx/jsonschema/annotation_converter.py index b06c932da..7688d81cb 100644 --- a/src/spdx/jsonschema/annotation_converter.py +++ b/src/spdx/jsonschema/annotation_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Type from spdx.datetime_conversions import datetime_to_iso_string diff --git a/src/spdx/jsonschema/annotation_properties.py b/src/spdx/jsonschema/annotation_properties.py index ffed44494..688eb9530 100644 --- a/src/spdx/jsonschema/annotation_properties.py +++ b/src/spdx/jsonschema/annotation_properties.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/checksum_converter.py b/src/spdx/jsonschema/checksum_converter.py index edc466311..cd430c274 100644 --- a/src/spdx/jsonschema/checksum_converter.py +++ b/src/spdx/jsonschema/checksum_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Type from spdx.jsonschema.checksum_properties import ChecksumProperty diff --git a/src/spdx/jsonschema/checksum_properties.py b/src/spdx/jsonschema/checksum_properties.py index d0733fa65..9ab691bee 100644 --- a/src/spdx/jsonschema/checksum_properties.py +++ b/src/spdx/jsonschema/checksum_properties.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/converter.py b/src/spdx/jsonschema/converter.py index 45444dc03..484777898 100644 --- a/src/spdx/jsonschema/converter.py +++ b/src/spdx/jsonschema/converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from abc import ABC, abstractmethod from typing import Any, Dict, Generic, Type, TypeVar diff --git a/src/spdx/jsonschema/creation_info_converter.py b/src/spdx/jsonschema/creation_info_converter.py index 96ded13a0..70e0b3e29 100644 --- a/src/spdx/jsonschema/creation_info_converter.py +++ b/src/spdx/jsonschema/creation_info_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Type from spdx.datetime_conversions import datetime_to_iso_string diff --git a/src/spdx/jsonschema/creation_info_properties.py b/src/spdx/jsonschema/creation_info_properties.py index 35acc20ba..79aa266ae 100644 --- a/src/spdx/jsonschema/creation_info_properties.py +++ b/src/spdx/jsonschema/creation_info_properties.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/document_converter.py b/src/spdx/jsonschema/document_converter.py index 598dceb2d..3a1675745 100644 --- a/src/spdx/jsonschema/document_converter.py +++ b/src/spdx/jsonschema/document_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Type from spdx.document_utils import get_contained_spdx_element_ids diff --git a/src/spdx/jsonschema/document_properties.py b/src/spdx/jsonschema/document_properties.py index 7acd02520..a1413d004 100644 --- a/src/spdx/jsonschema/document_properties.py +++ b/src/spdx/jsonschema/document_properties.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/external_document_ref_converter.py b/src/spdx/jsonschema/external_document_ref_converter.py index 03dccf795..196fac7de 100644 --- a/src/spdx/jsonschema/external_document_ref_converter.py +++ b/src/spdx/jsonschema/external_document_ref_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Type from spdx.jsonschema.checksum_converter import ChecksumConverter diff --git a/src/spdx/jsonschema/external_document_ref_properties.py b/src/spdx/jsonschema/external_document_ref_properties.py index d014e4e77..d80990c2d 100644 --- a/src/spdx/jsonschema/external_document_ref_properties.py +++ b/src/spdx/jsonschema/external_document_ref_properties.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/external_package_ref_converter.py b/src/spdx/jsonschema/external_package_ref_converter.py index 5dbbb1e45..91e1104c3 100644 --- a/src/spdx/jsonschema/external_package_ref_converter.py +++ b/src/spdx/jsonschema/external_package_ref_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Type from spdx.jsonschema.converter import TypedConverter diff --git a/src/spdx/jsonschema/external_package_ref_properties.py b/src/spdx/jsonschema/external_package_ref_properties.py index 9c90f3317..f922e95d5 100644 --- a/src/spdx/jsonschema/external_package_ref_properties.py +++ b/src/spdx/jsonschema/external_package_ref_properties.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/extracted_licensing_info_converter.py b/src/spdx/jsonschema/extracted_licensing_info_converter.py index 9d7ea23c5..0af7469df 100644 --- a/src/spdx/jsonschema/extracted_licensing_info_converter.py +++ b/src/spdx/jsonschema/extracted_licensing_info_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Type from spdx.jsonschema.converter import TypedConverter diff --git a/src/spdx/jsonschema/extracted_licensing_info_properties.py b/src/spdx/jsonschema/extracted_licensing_info_properties.py index f1b793fbe..46b6b6290 100644 --- a/src/spdx/jsonschema/extracted_licensing_info_properties.py +++ b/src/spdx/jsonschema/extracted_licensing_info_properties.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/file_converter.py b/src/spdx/jsonschema/file_converter.py index 3b22a6108..518de6719 100644 --- a/src/spdx/jsonschema/file_converter.py +++ b/src/spdx/jsonschema/file_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Type from spdx.jsonschema.annotation_converter import AnnotationConverter diff --git a/src/spdx/jsonschema/file_properties.py b/src/spdx/jsonschema/file_properties.py index 8706a092f..7b308134a 100644 --- a/src/spdx/jsonschema/file_properties.py +++ b/src/spdx/jsonschema/file_properties.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/json_property.py b/src/spdx/jsonschema/json_property.py index fa0114bac..7e7cd27f3 100644 --- a/src/spdx/jsonschema/json_property.py +++ b/src/spdx/jsonschema/json_property.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum diff --git a/src/spdx/jsonschema/optional_utils.py b/src/spdx/jsonschema/optional_utils.py index 3d5d6746a..a204015ad 100644 --- a/src/spdx/jsonschema/optional_utils.py +++ b/src/spdx/jsonschema/optional_utils.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Callable, Optional, TypeVar T = TypeVar("T") diff --git a/src/spdx/jsonschema/package_converter.py b/src/spdx/jsonschema/package_converter.py index da70b9720..86ea5aeb4 100644 --- a/src/spdx/jsonschema/package_converter.py +++ b/src/spdx/jsonschema/package_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Type from spdx.datetime_conversions import datetime_to_iso_string diff --git a/src/spdx/jsonschema/package_properties.py b/src/spdx/jsonschema/package_properties.py index b59d94723..f62ce2fbb 100644 --- a/src/spdx/jsonschema/package_properties.py +++ b/src/spdx/jsonschema/package_properties.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/package_verification_code_converter.py b/src/spdx/jsonschema/package_verification_code_converter.py index df72b9dcd..13959ace3 100644 --- a/src/spdx/jsonschema/package_verification_code_converter.py +++ b/src/spdx/jsonschema/package_verification_code_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Type from spdx.jsonschema.converter import TypedConverter diff --git a/src/spdx/jsonschema/package_verification_code_properties.py b/src/spdx/jsonschema/package_verification_code_properties.py index 845058469..7499c5acd 100644 --- a/src/spdx/jsonschema/package_verification_code_properties.py +++ b/src/spdx/jsonschema/package_verification_code_properties.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/relationship_converter.py b/src/spdx/jsonschema/relationship_converter.py index b2482f640..5527f2551 100644 --- a/src/spdx/jsonschema/relationship_converter.py +++ b/src/spdx/jsonschema/relationship_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Type from spdx.jsonschema.converter import TypedConverter diff --git a/src/spdx/jsonschema/relationship_properties.py b/src/spdx/jsonschema/relationship_properties.py index f5461f1ce..a96d1f287 100644 --- a/src/spdx/jsonschema/relationship_properties.py +++ b/src/spdx/jsonschema/relationship_properties.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/jsonschema/snippet_converter.py b/src/spdx/jsonschema/snippet_converter.py index d26e20ad5..b80907e9a 100644 --- a/src/spdx/jsonschema/snippet_converter.py +++ b/src/spdx/jsonschema/snippet_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Dict, Tuple, Type from spdx.jsonschema.annotation_converter import AnnotationConverter diff --git a/src/spdx/jsonschema/snippet_properties.py b/src/spdx/jsonschema/snippet_properties.py index 2fd5eadd8..0ee8ba324 100644 --- a/src/spdx/jsonschema/snippet_properties.py +++ b/src/spdx/jsonschema/snippet_properties.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx/model/actor.py b/src/spdx/model/actor.py index 022954f3a..66e38bd83 100644 --- a/src/spdx/model/actor.py +++ b/src/spdx/model/actor.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import Optional diff --git a/src/spdx/model/annotation.py b/src/spdx/model/annotation.py index 2cfe0b212..0718191b6 100644 --- a/src/spdx/model/annotation.py +++ b/src/spdx/model/annotation.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from enum import Enum, auto diff --git a/src/spdx/model/checksum.py b/src/spdx/model/checksum.py index 4e9249615..e4f121086 100644 --- a/src/spdx/model/checksum.py +++ b/src/spdx/model/checksum.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx/model/document.py b/src/spdx/model/document.py index d727955ec..e083cd4fa 100644 --- a/src/spdx/model/document.py +++ b/src/spdx/model/document.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from dataclasses import field from datetime import datetime from typing import List, Optional diff --git a/src/spdx/model/external_document_ref.py b/src/spdx/model/external_document_ref.py index f99ad545f..35c045f2a 100644 --- a/src/spdx/model/external_document_ref.py +++ b/src/spdx/model/external_document_ref.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx/model/extracted_licensing_info.py b/src/spdx/model/extracted_licensing_info.py index 4d05a079f..3133f9e5f 100644 --- a/src/spdx/model/extracted_licensing_info.py +++ b/src/spdx/model/extracted_licensing_info.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from dataclasses import field from typing import List, Optional, Union diff --git a/src/spdx/model/file.py b/src/spdx/model/file.py index 6205ff998..db51ab511 100644 --- a/src/spdx/model/file.py +++ b/src/spdx/model/file.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from dataclasses import field from enum import Enum, auto from typing import List, Optional, Union diff --git a/src/spdx/model/package.py b/src/spdx/model/package.py index 2aa8731b4..b468d576c 100644 --- a/src/spdx/model/package.py +++ b/src/spdx/model/package.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from dataclasses import field from datetime import datetime from enum import Enum, auto diff --git a/src/spdx/model/relationship.py b/src/spdx/model/relationship.py index 19ecc2d8b..565de3f74 100644 --- a/src/spdx/model/relationship.py +++ b/src/spdx/model/relationship.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import Optional, Union diff --git a/src/spdx/model/relationship_filters.py b/src/spdx/model/relationship_filters.py index 394a89479..f2e8a856a 100644 --- a/src/spdx/model/relationship_filters.py +++ b/src/spdx/model/relationship_filters.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List from spdx.model.document import Document diff --git a/src/spdx/model/snippet.py b/src/spdx/model/snippet.py index 2b12a7fc9..6b39cbae0 100644 --- a/src/spdx/model/snippet.py +++ b/src/spdx/model/snippet.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from dataclasses import field from typing import List, Optional, Tuple, Union diff --git a/src/spdx/model/spdx_no_assertion.py b/src/spdx/model/spdx_no_assertion.py index 3a12ed36c..3f02d10b9 100644 --- a/src/spdx/model/spdx_no_assertion.py +++ b/src/spdx/model/spdx_no_assertion.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 SPDX_NO_ASSERTION_STRING = "NOASSERTION" diff --git a/src/spdx/model/spdx_none.py b/src/spdx/model/spdx_none.py index e4e97c534..b44b705b3 100644 --- a/src/spdx/model/spdx_none.py +++ b/src/spdx/model/spdx_none.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 SPDX_NONE_STRING = "NONE" diff --git a/src/spdx/model/version.py b/src/spdx/model/version.py index 94a586d62..c045ef8ae 100644 --- a/src/spdx/model/version.py +++ b/src/spdx/model/version.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import re diff --git a/src/spdx/parser/actor_parser.py b/src/spdx/parser/actor_parser.py index 3ac5ddb9e..3266a51b0 100644 --- a/src/spdx/parser/actor_parser.py +++ b/src/spdx/parser/actor_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import re from typing import Match, Optional, Pattern diff --git a/src/spdx/parser/error.py b/src/spdx/parser/error.py index 580c4cfad..a0e7678e3 100644 --- a/src/spdx/parser/error.py +++ b/src/spdx/parser/error.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/parser/json/json_parser.py b/src/spdx/parser/json/json_parser.py index 9ee169b3c..24f10a5ca 100644 --- a/src/spdx/parser/json/json_parser.py +++ b/src/spdx/parser/json/json_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import json from typing import Dict diff --git a/src/spdx/parser/jsonlikedict/annotation_parser.py b/src/spdx/parser/jsonlikedict/annotation_parser.py index 72338179a..2ac696d09 100644 --- a/src/spdx/parser/jsonlikedict/annotation_parser.py +++ b/src/spdx/parser/jsonlikedict/annotation_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Dict, List, Optional diff --git a/src/spdx/parser/jsonlikedict/checksum_parser.py b/src/spdx/parser/jsonlikedict/checksum_parser.py index de09fc4ed..bf2070727 100644 --- a/src/spdx/parser/jsonlikedict/checksum_parser.py +++ b/src/spdx/parser/jsonlikedict/checksum_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict, Optional from spdx.model.checksum import Checksum, ChecksumAlgorithm diff --git a/src/spdx/parser/jsonlikedict/creation_info_parser.py b/src/spdx/parser/jsonlikedict/creation_info_parser.py index 835aa6702..bb7a2935b 100644 --- a/src/spdx/parser/jsonlikedict/creation_info_parser.py +++ b/src/spdx/parser/jsonlikedict/creation_info_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Dict, List, Optional diff --git a/src/spdx/parser/jsonlikedict/dict_parsing_functions.py b/src/spdx/parser/jsonlikedict/dict_parsing_functions.py index 4e791f6b4..57cdd710f 100644 --- a/src/spdx/parser/jsonlikedict/dict_parsing_functions.py +++ b/src/spdx/parser/jsonlikedict/dict_parsing_functions.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Callable, Dict, List, Optional from spdx.model.spdx_no_assertion import SpdxNoAssertion diff --git a/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py b/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py index 65ec7495f..6190d38bd 100644 --- a/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py +++ b/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict, List, Optional, Union from spdx.model.extracted_licensing_info import ExtractedLicensingInfo diff --git a/src/spdx/parser/jsonlikedict/file_parser.py b/src/spdx/parser/jsonlikedict/file_parser.py index 501ba4b76..f671ccb36 100644 --- a/src/spdx/parser/jsonlikedict/file_parser.py +++ b/src/spdx/parser/jsonlikedict/file_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict, List, Optional, Union from license_expression import LicenseExpression diff --git a/src/spdx/parser/jsonlikedict/json_like_dict_parser.py b/src/spdx/parser/jsonlikedict/json_like_dict_parser.py index 148cd4dd2..1073fb57b 100644 --- a/src/spdx/parser/jsonlikedict/json_like_dict_parser.py +++ b/src/spdx/parser/jsonlikedict/json_like_dict_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict from spdx.model.document import Document diff --git a/src/spdx/parser/jsonlikedict/license_expression_parser.py b/src/spdx/parser/jsonlikedict/license_expression_parser.py index 74ce63034..73e0b4ba3 100644 --- a/src/spdx/parser/jsonlikedict/license_expression_parser.py +++ b/src/spdx/parser/jsonlikedict/license_expression_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Union from license_expression import ExpressionError, LicenseExpression, Licensing diff --git a/src/spdx/parser/jsonlikedict/package_parser.py b/src/spdx/parser/jsonlikedict/package_parser.py index 9ed80c0ee..afb12dc7f 100644 --- a/src/spdx/parser/jsonlikedict/package_parser.py +++ b/src/spdx/parser/jsonlikedict/package_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Dict, List, Optional, Union diff --git a/src/spdx/parser/jsonlikedict/relationship_parser.py b/src/spdx/parser/jsonlikedict/relationship_parser.py index 4d72f851a..d1d0ae8a8 100644 --- a/src/spdx/parser/jsonlikedict/relationship_parser.py +++ b/src/spdx/parser/jsonlikedict/relationship_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict, List, Optional from common.typing.constructor_type_errors import ConstructorTypeErrors diff --git a/src/spdx/parser/jsonlikedict/snippet_parser.py b/src/spdx/parser/jsonlikedict/snippet_parser.py index 548a3eb6f..0a6fbcbb9 100644 --- a/src/spdx/parser/jsonlikedict/snippet_parser.py +++ b/src/spdx/parser/jsonlikedict/snippet_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import Dict, List, Optional, Tuple, Union diff --git a/src/spdx/parser/logger.py b/src/spdx/parser/logger.py index 312a959d0..4ebc1479d 100644 --- a/src/spdx/parser/logger.py +++ b/src/spdx/parser/logger.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/parser/parsing_functions.py b/src/spdx/parser/parsing_functions.py index f8cd3ce25..32d2f3184 100644 --- a/src/spdx/parser/parsing_functions.py +++ b/src/spdx/parser/parsing_functions.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Dict from common.typing.constructor_type_errors import ConstructorTypeErrors diff --git a/src/spdx/parser/rdf/annotation_parser.py b/src/spdx/parser/rdf/annotation_parser.py index 80d6229bf..6f6a0a39f 100644 --- a/src/spdx/parser/rdf/annotation_parser.py +++ b/src/spdx/parser/rdf/annotation_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef from spdx.datetime_conversions import datetime_from_str diff --git a/src/spdx/parser/rdf/checksum_parser.py b/src/spdx/parser/rdf/checksum_parser.py index 91fd82244..57dd247f2 100644 --- a/src/spdx/parser/rdf/checksum_parser.py +++ b/src/spdx/parser/rdf/checksum_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import Graph, URIRef from spdx.model.checksum import Checksum, ChecksumAlgorithm diff --git a/src/spdx/parser/rdf/creation_info_parser.py b/src/spdx/parser/rdf/creation_info_parser.py index 57e63ca9d..938becb6e 100644 --- a/src/spdx/parser/rdf/creation_info_parser.py +++ b/src/spdx/parser/rdf/creation_info_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import logging import sys from typing import Tuple diff --git a/src/spdx/parser/rdf/extracted_licensing_info_parser.py b/src/spdx/parser/rdf/extracted_licensing_info_parser.py index 2fa598696..663c2e260 100644 --- a/src/spdx/parser/rdf/extracted_licensing_info_parser.py +++ b/src/spdx/parser/rdf/extracted_licensing_info_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef from spdx.model.extracted_licensing_info import ExtractedLicensingInfo diff --git a/src/spdx/parser/rdf/file_parser.py b/src/spdx/parser/rdf/file_parser.py index 5f0a0a5cd..c42b6d1e5 100644 --- a/src/spdx/parser/rdf/file_parser.py +++ b/src/spdx/parser/rdf/file_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef from spdx.model.file import File, FileType diff --git a/src/spdx/parser/rdf/graph_parsing_functions.py b/src/spdx/parser/rdf/graph_parsing_functions.py index 297f6e9ba..5accd10d9 100644 --- a/src/spdx/parser/rdf/graph_parsing_functions.py +++ b/src/spdx/parser/rdf/graph_parsing_functions.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum from typing import Any, Callable, Optional, Type diff --git a/src/spdx/parser/rdf/license_expression_parser.py b/src/spdx/parser/rdf/license_expression_parser.py index 346fd5143..629b3fe9c 100644 --- a/src/spdx/parser/rdf/license_expression_parser.py +++ b/src/spdx/parser/rdf/license_expression_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Union from license_expression import LicenseExpression, get_spdx_licensing diff --git a/src/spdx/parser/rdf/package_parser.py b/src/spdx/parser/rdf/package_parser.py index 0301ecdee..b4be7fdae 100644 --- a/src/spdx/parser/rdf/package_parser.py +++ b/src/spdx/parser/rdf/package_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Optional from rdflib import DOAP, RDFS, Graph, URIRef diff --git a/src/spdx/parser/rdf/rdf_parser.py b/src/spdx/parser/rdf/rdf_parser.py index 60f0bfb9f..ae6baf3bc 100644 --- a/src/spdx/parser/rdf/rdf_parser.py +++ b/src/spdx/parser/rdf/rdf_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, Graph from spdx.model.document import Document diff --git a/src/spdx/parser/rdf/relationship_parser.py b/src/spdx/parser/rdf/relationship_parser.py index e0bb13e17..44d840e95 100644 --- a/src/spdx/parser/rdf/relationship_parser.py +++ b/src/spdx/parser/rdf/relationship_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef from spdx.model.relationship import Relationship, RelationshipType diff --git a/src/spdx/parser/rdf/snippet_parser.py b/src/spdx/parser/rdf/snippet_parser.py index 6a69306f3..284e1328a 100644 --- a/src/spdx/parser/rdf/snippet_parser.py +++ b/src/spdx/parser/rdf/snippet_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict, Optional, Tuple from rdflib import RDF, RDFS, Graph diff --git a/src/spdx/parser/tagvalue/helper_methods.py b/src/spdx/parser/tagvalue/helper_methods.py index 3814b3d29..ef904cfa3 100644 --- a/src/spdx/parser/tagvalue/helper_methods.py +++ b/src/spdx/parser/tagvalue/helper_methods.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import re from typing import Any, Callable, Dict, Optional diff --git a/src/spdx/parser/tagvalue/lexer.py b/src/spdx/parser/tagvalue/lexer.py index 7556267b7..9a857827b 100644 --- a/src/spdx/parser/tagvalue/lexer.py +++ b/src/spdx/parser/tagvalue/lexer.py @@ -1,5 +1,6 @@ # Copyright (c) 2014 Ahmed H. Ismail # Copyright (c) 2023 spdx contributors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/src/spdx/parser/tagvalue/parser.py b/src/spdx/parser/tagvalue/parser.py index 8f4ec2790..e52e6c9bf 100644 --- a/src/spdx/parser/tagvalue/parser.py +++ b/src/spdx/parser/tagvalue/parser.py @@ -1,5 +1,6 @@ # Copyright (c) 2014 Ahmed H. Ismail # Copyright (c) 2023 spdx contributors +# SPDX-License-Identifier: Apache-2.0 # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/src/spdx/parser/tagvalue/tagvalue_parser.py b/src/spdx/parser/tagvalue/tagvalue_parser.py index d71c3c047..948c97e78 100644 --- a/src/spdx/parser/tagvalue/tagvalue_parser.py +++ b/src/spdx/parser/tagvalue/tagvalue_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from spdx.model.document import Document from spdx.parser.tagvalue.parser import Parser diff --git a/src/spdx/parser/xml/xml_parser.py b/src/spdx/parser/xml/xml_parser.py index 9f9189a45..61c24edaa 100644 --- a/src/spdx/parser/xml/xml_parser.py +++ b/src/spdx/parser/xml/xml_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Any, Dict import xmltodict diff --git a/src/spdx/parser/yaml/yaml_parser.py b/src/spdx/parser/yaml/yaml_parser.py index b3750938d..4cfa9e5bf 100644 --- a/src/spdx/parser/yaml/yaml_parser.py +++ b/src/spdx/parser/yaml/yaml_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict import yaml diff --git a/src/spdx/rdfschema/namespace.py b/src/spdx/rdfschema/namespace.py index b29f55ad5..822872c54 100644 --- a/src/spdx/rdfschema/namespace.py +++ b/src/spdx/rdfschema/namespace.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import Namespace SPDX_NAMESPACE = Namespace("http://spdx.org/rdf/terms#") diff --git a/src/spdx/validation/actor_validator.py b/src/spdx/validation/actor_validator.py index 192b95774..a1c3fecea 100644 --- a/src/spdx/validation/actor_validator.py +++ b/src/spdx/validation/actor_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/validation/annotation_validator.py b/src/spdx/validation/annotation_validator.py index e162f2d1c..6e7774658 100644 --- a/src/spdx/validation/annotation_validator.py +++ b/src/spdx/validation/annotation_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/validation/checksum_validator.py b/src/spdx/validation/checksum_validator.py index f34cc0a2e..c5221598a 100644 --- a/src/spdx/validation/checksum_validator.py +++ b/src/spdx/validation/checksum_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import re from typing import Dict, List diff --git a/src/spdx/validation/creation_info_validator.py b/src/spdx/validation/creation_info_validator.py index a73e98635..5650d9945 100644 --- a/src/spdx/validation/creation_info_validator.py +++ b/src/spdx/validation/creation_info_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/validation/document_validator.py b/src/spdx/validation/document_validator.py index 1446ce1bb..0db5ef98a 100644 --- a/src/spdx/validation/document_validator.py +++ b/src/spdx/validation/document_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List from spdx.model.document import Document diff --git a/src/spdx/validation/external_document_ref_validator.py b/src/spdx/validation/external_document_ref_validator.py index 6cd20d2da..3089bb0f2 100644 --- a/src/spdx/validation/external_document_ref_validator.py +++ b/src/spdx/validation/external_document_ref_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/validation/external_package_ref_validator.py b/src/spdx/validation/external_package_ref_validator.py index 8105ec0f6..429caf422 100644 --- a/src/spdx/validation/external_package_ref_validator.py +++ b/src/spdx/validation/external_package_ref_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import re from typing import Dict, List diff --git a/src/spdx/validation/extracted_licensing_info_validator.py b/src/spdx/validation/extracted_licensing_info_validator.py index a1def8ae7..bb8f76281 100644 --- a/src/spdx/validation/extracted_licensing_info_validator.py +++ b/src/spdx/validation/extracted_licensing_info_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import re from typing import List, Optional diff --git a/src/spdx/validation/file_validator.py b/src/spdx/validation/file_validator.py index c90cbc868..1f9e666c9 100644 --- a/src/spdx/validation/file_validator.py +++ b/src/spdx/validation/file_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx/validation/license_expression_validator.py b/src/spdx/validation/license_expression_validator.py index ebf6e4ae8..e4af4ee5e 100644 --- a/src/spdx/validation/license_expression_validator.py +++ b/src/spdx/validation/license_expression_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional, Union diff --git a/src/spdx/validation/package_validator.py b/src/spdx/validation/package_validator.py index ab68757e1..ed22dbe83 100644 --- a/src/spdx/validation/package_validator.py +++ b/src/spdx/validation/package_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx/validation/package_verification_code_validator.py b/src/spdx/validation/package_verification_code_validator.py index b059dc69c..3ca65249f 100644 --- a/src/spdx/validation/package_verification_code_validator.py +++ b/src/spdx/validation/package_verification_code_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import re from typing import List diff --git a/src/spdx/validation/relationship_validator.py b/src/spdx/validation/relationship_validator.py index 11268d07c..bad94f78f 100644 --- a/src/spdx/validation/relationship_validator.py +++ b/src/spdx/validation/relationship_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/validation/snippet_validator.py b/src/spdx/validation/snippet_validator.py index c709b1d37..f312308f3 100644 --- a/src/spdx/validation/snippet_validator.py +++ b/src/spdx/validation/snippet_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx/validation/spdx_id_validators.py b/src/spdx/validation/spdx_id_validators.py index 29164df65..00c80f11d 100644 --- a/src/spdx/validation/spdx_id_validators.py +++ b/src/spdx/validation/spdx_id_validators.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import re from typing import List diff --git a/src/spdx/validation/uri_validators.py b/src/spdx/validation/uri_validators.py index 8d57c997c..68bbed6dc 100644 --- a/src/spdx/validation/uri_validators.py +++ b/src/spdx/validation/uri_validators.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import re from typing import List diff --git a/src/spdx/validation/validation_message.py b/src/spdx/validation/validation_message.py index c1679f1c7..21af28cb4 100644 --- a/src/spdx/validation/validation_message.py +++ b/src/spdx/validation/validation_message.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from dataclasses import dataclass from enum import Enum, auto diff --git a/src/spdx/writer/json/json_writer.py b/src/spdx/writer/json/json_writer.py index 4cfef383a..97a29d598 100644 --- a/src/spdx/writer/json/json_writer.py +++ b/src/spdx/writer/json/json_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import json from typing import List diff --git a/src/spdx/writer/rdf/annotation_writer.py b/src/spdx/writer/rdf/annotation_writer.py index 6aa234ae6..4b288b9ad 100644 --- a/src/spdx/writer/rdf/annotation_writer.py +++ b/src/spdx/writer/rdf/annotation_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef diff --git a/src/spdx/writer/rdf/checksum_writer.py b/src/spdx/writer/rdf/checksum_writer.py index 335b89d31..1cc9ab6b5 100644 --- a/src/spdx/writer/rdf/checksum_writer.py +++ b/src/spdx/writer/rdf/checksum_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, BNode, Graph, Literal, URIRef from spdx.model.checksum import Checksum, ChecksumAlgorithm diff --git a/src/spdx/writer/rdf/creation_info_writer.py b/src/spdx/writer/rdf/creation_info_writer.py index 795ed2f1e..0e792ece1 100644 --- a/src/spdx/writer/rdf/creation_info_writer.py +++ b/src/spdx/writer/rdf/creation_info_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef from spdx.datetime_conversions import datetime_to_iso_string diff --git a/src/spdx/writer/rdf/external_document_ref_writer.py b/src/spdx/writer/rdf/external_document_ref_writer.py index 85ef8da65..f652ff552 100644 --- a/src/spdx/writer/rdf/external_document_ref_writer.py +++ b/src/spdx/writer/rdf/external_document_ref_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, Graph, URIRef from spdx.model.external_document_ref import ExternalDocumentRef diff --git a/src/spdx/writer/rdf/extracted_licensing_info_writer.py b/src/spdx/writer/rdf/extracted_licensing_info_writer.py index 96bd3888e..d6af55f9c 100644 --- a/src/spdx/writer/rdf/extracted_licensing_info_writer.py +++ b/src/spdx/writer/rdf/extracted_licensing_info_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef from spdx.model.extracted_licensing_info import ExtractedLicensingInfo diff --git a/src/spdx/writer/rdf/file_writer.py b/src/spdx/writer/rdf/file_writer.py index c896cdea8..6bbcf637f 100644 --- a/src/spdx/writer/rdf/file_writer.py +++ b/src/spdx/writer/rdf/file_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict from rdflib import RDF, RDFS, Graph, Literal, URIRef diff --git a/src/spdx/writer/rdf/license_expression_writer.py b/src/spdx/writer/rdf/license_expression_writer.py index bb584817f..a6e230a41 100644 --- a/src/spdx/writer/rdf/license_expression_writer.py +++ b/src/spdx/writer/rdf/license_expression_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Union from boolean import Expression diff --git a/src/spdx/writer/rdf/package_writer.py b/src/spdx/writer/rdf/package_writer.py index 84cf94b8d..83db8e11a 100644 --- a/src/spdx/writer/rdf/package_writer.py +++ b/src/spdx/writer/rdf/package_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict from rdflib import DOAP, RDF, RDFS, XSD, BNode, Graph, Literal, URIRef diff --git a/src/spdx/writer/rdf/rdf_writer.py b/src/spdx/writer/rdf/rdf_writer.py index 64daf7389..fb6aeed1d 100644 --- a/src/spdx/writer/rdf/rdf_writer.py +++ b/src/spdx/writer/rdf/rdf_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict, List from rdflib import DOAP, Graph diff --git a/src/spdx/writer/rdf/relationship_writer.py b/src/spdx/writer/rdf/relationship_writer.py index a59a2f537..9435ee433 100644 --- a/src/spdx/writer/rdf/relationship_writer.py +++ b/src/spdx/writer/rdf/relationship_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef diff --git a/src/spdx/writer/rdf/snippet_writer.py b/src/spdx/writer/rdf/snippet_writer.py index ab50ddd9d..d4c8e7024 100644 --- a/src/spdx/writer/rdf/snippet_writer.py +++ b/src/spdx/writer/rdf/snippet_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict, Optional, Tuple from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef diff --git a/src/spdx/writer/rdf/writer_utils.py b/src/spdx/writer/rdf/writer_utils.py index cfbe3b42e..6e18ccf44 100644 --- a/src/spdx/writer/rdf/writer_utils.py +++ b/src/spdx/writer/rdf/writer_utils.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import logging from datetime import datetime from typing import Any, Dict, Optional diff --git a/src/spdx/writer/write_anything.py b/src/spdx/writer/write_anything.py index b3ba5248e..7e97654eb 100644 --- a/src/spdx/writer/write_anything.py +++ b/src/spdx/writer/write_anything.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from spdx.formats import FileFormat, file_name_to_format from spdx.model.document import Document from spdx.writer.json import json_writer diff --git a/src/spdx/writer/xml/xml_writer.py b/src/spdx/writer/xml/xml_writer.py index d347b7d6d..0bc6a47aa 100644 --- a/src/spdx/writer/xml/xml_writer.py +++ b/src/spdx/writer/xml/xml_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List import xmltodict diff --git a/src/spdx/writer/yaml/yaml_writer.py b/src/spdx/writer/yaml/yaml_writer.py index 2dc365f95..7a9536816 100644 --- a/src/spdx/writer/yaml/yaml_writer.py +++ b/src/spdx/writer/yaml/yaml_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List import yaml diff --git a/tests/spdx/fixtures.py b/tests/spdx/fixtures.py index 6bfe9f72d..d8588214e 100644 --- a/tests/spdx/fixtures.py +++ b/tests/spdx/fixtures.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from license_expression import get_spdx_licensing diff --git a/tests/spdx/jsonschema/test_annotation_converter.py b/tests/spdx/jsonschema/test_annotation_converter.py index 15b2d17f8..61facc040 100644 --- a/tests/spdx/jsonschema/test_annotation_converter.py +++ b/tests/spdx/jsonschema/test_annotation_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime import pytest diff --git a/tests/spdx/jsonschema/test_checksum_converter.py b/tests/spdx/jsonschema/test_checksum_converter.py index 60393d7e6..5808a0682 100644 --- a/tests/spdx/jsonschema/test_checksum_converter.py +++ b/tests/spdx/jsonschema/test_checksum_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx.jsonschema.checksum_converter import ChecksumConverter diff --git a/tests/spdx/jsonschema/test_converter.py b/tests/spdx/jsonschema/test_converter.py index e5dff510b..f5bae70a4 100644 --- a/tests/spdx/jsonschema/test_converter.py +++ b/tests/spdx/jsonschema/test_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import auto from typing import Any, Type diff --git a/tests/spdx/jsonschema/test_creation_info_converter.py b/tests/spdx/jsonschema/test_creation_info_converter.py index f527b586f..5921d911f 100644 --- a/tests/spdx/jsonschema/test_creation_info_converter.py +++ b/tests/spdx/jsonschema/test_creation_info_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime import pytest diff --git a/tests/spdx/jsonschema/test_document_converter.py b/tests/spdx/jsonschema/test_document_converter.py index 8832b852f..7bb1d5ac5 100644 --- a/tests/spdx/jsonschema/test_document_converter.py +++ b/tests/spdx/jsonschema/test_document_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Union from unittest import mock diff --git a/tests/spdx/jsonschema/test_external_document_ref_converter.py b/tests/spdx/jsonschema/test_external_document_ref_converter.py index 53bfb3bd4..a6437d604 100644 --- a/tests/spdx/jsonschema/test_external_document_ref_converter.py +++ b/tests/spdx/jsonschema/test_external_document_ref_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock from unittest.mock import MagicMock diff --git a/tests/spdx/jsonschema/test_external_package_ref_converter.py b/tests/spdx/jsonschema/test_external_package_ref_converter.py index 323df18d4..016aa75c4 100644 --- a/tests/spdx/jsonschema/test_external_package_ref_converter.py +++ b/tests/spdx/jsonschema/test_external_package_ref_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx.jsonschema.external_package_ref_converter import ExternalPackageRefConverter diff --git a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py index 7d62fa150..19324e961 100644 --- a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py +++ b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx.jsonschema.extracted_licensing_info_converter import ExtractedLicensingInfoConverter diff --git a/tests/spdx/jsonschema/test_file_converter.py b/tests/spdx/jsonschema/test_file_converter.py index e78e63681..076ecdd90 100644 --- a/tests/spdx/jsonschema/test_file_converter.py +++ b/tests/spdx/jsonschema/test_file_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Union from unittest import mock diff --git a/tests/spdx/jsonschema/test_package_converter.py b/tests/spdx/jsonschema/test_package_converter.py index 31516fa0f..bff476822 100644 --- a/tests/spdx/jsonschema/test_package_converter.py +++ b/tests/spdx/jsonschema/test_package_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Union from unittest import mock diff --git a/tests/spdx/jsonschema/test_package_verification_code_converter.py b/tests/spdx/jsonschema/test_package_verification_code_converter.py index 66daf34e0..e506676a6 100644 --- a/tests/spdx/jsonschema/test_package_verification_code_converter.py +++ b/tests/spdx/jsonschema/test_package_verification_code_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx.jsonschema.package_verification_code_converter import PackageVerificationCodeConverter diff --git a/tests/spdx/jsonschema/test_relationship_converter.py b/tests/spdx/jsonschema/test_relationship_converter.py index d03d6271d..2b78bf9e4 100644 --- a/tests/spdx/jsonschema/test_relationship_converter.py +++ b/tests/spdx/jsonschema/test_relationship_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx.jsonschema.relationship_converter import RelationshipConverter diff --git a/tests/spdx/jsonschema/test_snippet_converter.py b/tests/spdx/jsonschema/test_snippet_converter.py index a77b70ea0..baceeffbd 100644 --- a/tests/spdx/jsonschema/test_snippet_converter.py +++ b/tests/spdx/jsonschema/test_snippet_converter.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Union from unittest import mock diff --git a/tests/spdx/mock_utils.py b/tests/spdx/mock_utils.py index c99715903..075b51117 100644 --- a/tests/spdx/mock_utils.py +++ b/tests/spdx/mock_utils.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest.mock import NonCallableMagicMock diff --git a/tests/spdx/model/test_version.py b/tests/spdx/model/test_version.py index 574a5faa2..ab6a719d1 100644 --- a/tests/spdx/model/test_version.py +++ b/tests/spdx/model/test_version.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/parser/json/test_json_parser.py b/tests/spdx/parser/json/test_json_parser.py index b61a01ad8..e14fb510c 100644 --- a/tests/spdx/parser/json/test_json_parser.py +++ b/tests/spdx/parser/json/test_json_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os diff --git a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py index 439883433..ed7af5334 100644 --- a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import datetime from unittest import TestCase diff --git a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py index 536b02040..a64289b48 100644 --- a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import TestCase import pytest diff --git a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py index 219daecb3..aab81b3cc 100644 --- a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from unittest import TestCase diff --git a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py index b7abde4ae..71d25f325 100644 --- a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import TestCase import pytest diff --git a/tests/spdx/parser/jsonlikedict/test_file_parser.py b/tests/spdx/parser/jsonlikedict/test_file_parser.py index 3cf41e6e5..b784d096a 100644 --- a/tests/spdx/parser/jsonlikedict/test_file_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_file_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import TestCase import pytest diff --git a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py index 8157afcdf..2bb9a7899 100644 --- a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import TestCase import pytest diff --git a/tests/spdx/parser/jsonlikedict/test_package_parser.py b/tests/spdx/parser/jsonlikedict/test_package_parser.py index e4d6c9028..d2b41ffde 100644 --- a/tests/spdx/parser/jsonlikedict/test_package_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_package_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from unittest import TestCase diff --git a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py index 01f67833a..464c39f02 100644 --- a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import TestCase import pytest diff --git a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py index f2b8909b0..cdf96de14 100644 --- a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import TestCase import pytest diff --git a/tests/spdx/parser/rdf/test_annotation_parser.py b/tests/spdx/parser/rdf/test_annotation_parser.py index d0b6068c2..de8a956bb 100644 --- a/tests/spdx/parser/rdf/test_annotation_parser.py +++ b/tests/spdx/parser/rdf/test_annotation_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os from datetime import datetime diff --git a/tests/spdx/parser/rdf/test_checksum_parser.py b/tests/spdx/parser/rdf/test_checksum_parser.py index 2597fd83f..add7e4155 100644 --- a/tests/spdx/parser/rdf/test_checksum_parser.py +++ b/tests/spdx/parser/rdf/test_checksum_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os import pytest diff --git a/tests/spdx/parser/rdf/test_creation_info_parser.py b/tests/spdx/parser/rdf/test_creation_info_parser.py index ba5cd19c2..696dd7c06 100644 --- a/tests/spdx/parser/rdf/test_creation_info_parser.py +++ b/tests/spdx/parser/rdf/test_creation_info_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os from datetime import datetime from typing import List, Tuple diff --git a/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py b/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py index db09dd0ff..46eacfe96 100644 --- a/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os from rdflib import RDF, Graph diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py index 33d168b4b..acc40aea4 100644 --- a/tests/spdx/parser/rdf/test_file_parser.py +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os from unittest import TestCase diff --git a/tests/spdx/parser/rdf/test_graph_parsing_function.py b/tests/spdx/parser/rdf/test_graph_parsing_function.py index 5a1118c2a..db9fa1d69 100644 --- a/tests/spdx/parser/rdf/test_graph_parsing_function.py +++ b/tests/spdx/parser/rdf/test_graph_parsing_function.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from rdflib import Graph, Namespace, URIRef diff --git a/tests/spdx/parser/rdf/test_license_expression_parser.py b/tests/spdx/parser/rdf/test_license_expression_parser.py index 3a529e768..6124d3bfe 100644 --- a/tests/spdx/parser/rdf/test_license_expression_parser.py +++ b/tests/spdx/parser/rdf/test_license_expression_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os from unittest import TestCase diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index 454a37a79..2410c15d9 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os from unittest import TestCase diff --git a/tests/spdx/parser/rdf/test_rdf_parser.py b/tests/spdx/parser/rdf/test_rdf_parser.py index b80fe3581..754c9ae1f 100644 --- a/tests/spdx/parser/rdf/test_rdf_parser.py +++ b/tests/spdx/parser/rdf/test_rdf_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os import pytest diff --git a/tests/spdx/parser/rdf/test_relationship_parser.py b/tests/spdx/parser/rdf/test_relationship_parser.py index e96fee535..e3a7ae2ed 100644 --- a/tests/spdx/parser/rdf/test_relationship_parser.py +++ b/tests/spdx/parser/rdf/test_relationship_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os from rdflib import RDF, Graph diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index b98d8e9c7..2f33d22b1 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os from unittest import TestCase diff --git a/tests/spdx/parser/tagvalue/test_annotation_parser.py b/tests/spdx/parser/tagvalue/test_annotation_parser.py index 1fbd2060c..91bf81497 100644 --- a/tests/spdx/parser/tagvalue/test_annotation_parser.py +++ b/tests/spdx/parser/tagvalue/test_annotation_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime import pytest diff --git a/tests/spdx/parser/tagvalue/test_creation_info_parser.py b/tests/spdx/parser/tagvalue/test_creation_info_parser.py index 631aa3883..bab2e5e11 100644 --- a/tests/spdx/parser/tagvalue/test_creation_info_parser.py +++ b/tests/spdx/parser/tagvalue/test_creation_info_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from unittest import TestCase diff --git a/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py b/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py index f97bff015..617ecbae5 100644 --- a/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import TestCase import pytest diff --git a/tests/spdx/parser/tagvalue/test_file_parser.py b/tests/spdx/parser/tagvalue/test_file_parser.py index ac6148bcd..eeffaf6dd 100644 --- a/tests/spdx/parser/tagvalue/test_file_parser.py +++ b/tests/spdx/parser/tagvalue/test_file_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from license_expression import get_spdx_licensing diff --git a/tests/spdx/parser/tagvalue/test_helper_methods.py b/tests/spdx/parser/tagvalue/test_helper_methods.py index 828083836..9d384e8f7 100644 --- a/tests/spdx/parser/tagvalue/test_helper_methods.py +++ b/tests/spdx/parser/tagvalue/test_helper_methods.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx.model.checksum import ChecksumAlgorithm diff --git a/tests/spdx/parser/tagvalue/test_package_parser.py b/tests/spdx/parser/tagvalue/test_package_parser.py index f5c75d751..fd4518b3d 100644 --- a/tests/spdx/parser/tagvalue/test_package_parser.py +++ b/tests/spdx/parser/tagvalue/test_package_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from unittest import TestCase diff --git a/tests/spdx/parser/tagvalue/test_relationship_parser.py b/tests/spdx/parser/tagvalue/test_relationship_parser.py index fc74b05b7..857166ed5 100644 --- a/tests/spdx/parser/tagvalue/test_relationship_parser.py +++ b/tests/spdx/parser/tagvalue/test_relationship_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx.model.relationship import Relationship, RelationshipType diff --git a/tests/spdx/parser/tagvalue/test_snippet_parser.py b/tests/spdx/parser/tagvalue/test_snippet_parser.py index 4e563a581..271ebead9 100644 --- a/tests/spdx/parser/tagvalue/test_snippet_parser.py +++ b/tests/spdx/parser/tagvalue/test_snippet_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import TestCase import pytest diff --git a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py index 2a8bb670b..6792316fd 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py @@ -1,14 +1,7 @@ # Copyright (c) 2014 Ahmed H. Ismail -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx.parser.tagvalue.lexer import SPDXLexer diff --git a/tests/spdx/parser/tagvalue/test_tag_value_parser.py b/tests/spdx/parser/tagvalue/test_tag_value_parser.py index 1cd0183e0..d9c50c901 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_parser.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_parser.py @@ -1,14 +1,7 @@ # Copyright (c) 2014 Ahmed H. Ismail -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os import pytest diff --git a/tests/spdx/test_actor_parser.py b/tests/spdx/test_actor_parser.py index dfd43a172..0dfe56081 100644 --- a/tests/spdx/test_actor_parser.py +++ b/tests/spdx/test_actor_parser.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import TestCase import pytest diff --git a/tests/spdx/test_casing_tools.py b/tests/spdx/test_casing_tools.py index 354cb7657..77c19f977 100644 --- a/tests/spdx/test_casing_tools.py +++ b/tests/spdx/test_casing_tools.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx.casing_tools import camel_case_to_snake_case, snake_case_to_camel_case diff --git a/tests/spdx/test_datetime_conversions.py b/tests/spdx/test_datetime_conversions.py index b396edf13..db1df249e 100644 --- a/tests/spdx/test_datetime_conversions.py +++ b/tests/spdx/test_datetime_conversions.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime import pytest diff --git a/tests/spdx/validation/test_actor_validator.py b/tests/spdx/validation/test_actor_validator.py index 19a99b8c7..78227da70 100644 --- a/tests/spdx/validation/test_actor_validator.py +++ b/tests/spdx/validation/test_actor_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_annotation_validator.py b/tests/spdx/validation/test_annotation_validator.py index aba5995d5..d04c7d1c2 100644 --- a/tests/spdx/validation/test_annotation_validator.py +++ b/tests/spdx/validation/test_annotation_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_checksum_validator.py b/tests/spdx/validation/test_checksum_validator.py index 7f4ae51d5..6217f859a 100644 --- a/tests/spdx/validation/test_checksum_validator.py +++ b/tests/spdx/validation/test_checksum_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_creation_info_validator.py b/tests/spdx/validation/test_creation_info_validator.py index b278e2f0c..a67ca5c45 100644 --- a/tests/spdx/validation/test_creation_info_validator.py +++ b/tests/spdx/validation/test_creation_info_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_document_validator.py b/tests/spdx/validation/test_document_validator.py index d26258b63..d242a52c6 100644 --- a/tests/spdx/validation/test_document_validator.py +++ b/tests/spdx/validation/test_document_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/tests/spdx/validation/test_external_document_ref_validator.py b/tests/spdx/validation/test_external_document_ref_validator.py index 4ad65edf4..8402c070d 100644 --- a/tests/spdx/validation/test_external_document_ref_validator.py +++ b/tests/spdx/validation/test_external_document_ref_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_external_package_ref_validator.py b/tests/spdx/validation/test_external_package_ref_validator.py index b3dfa48d8..2e509c603 100644 --- a/tests/spdx/validation/test_external_package_ref_validator.py +++ b/tests/spdx/validation/test_external_package_ref_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_extracted_licensing_info_validator.py b/tests/spdx/validation/test_extracted_licensing_info_validator.py index ce82f0626..19fb0875f 100644 --- a/tests/spdx/validation/test_extracted_licensing_info_validator.py +++ b/tests/spdx/validation/test_extracted_licensing_info_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_file_validator.py b/tests/spdx/validation/test_file_validator.py index e215d56c9..210b23987 100644 --- a/tests/spdx/validation/test_file_validator.py +++ b/tests/spdx/validation/test_file_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List from unittest import TestCase diff --git a/tests/spdx/validation/test_license_expression_validator.py b/tests/spdx/validation/test_license_expression_validator.py index 4a81ec525..48cb1f31a 100644 --- a/tests/spdx/validation/test_license_expression_validator.py +++ b/tests/spdx/validation/test_license_expression_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List from unittest import TestCase diff --git a/tests/spdx/validation/test_package_validator.py b/tests/spdx/validation/test_package_validator.py index 24ecd6160..aeee350c9 100644 --- a/tests/spdx/validation/test_package_validator.py +++ b/tests/spdx/validation/test_package_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List from unittest import TestCase diff --git a/tests/spdx/validation/test_package_verification_code_validator.py b/tests/spdx/validation/test_package_verification_code_validator.py index d6ddb1548..ca59c074a 100644 --- a/tests/spdx/validation/test_package_verification_code_validator.py +++ b/tests/spdx/validation/test_package_verification_code_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/validation/test_relationship_validator.py b/tests/spdx/validation/test_relationship_validator.py index 83e8bc1a6..a208be609 100644 --- a/tests/spdx/validation/test_relationship_validator.py +++ b/tests/spdx/validation/test_relationship_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_snippet_validator.py b/tests/spdx/validation/test_snippet_validator.py index 5c9881653..8b25d01ee 100644 --- a/tests/spdx/validation/test_snippet_validator.py +++ b/tests/spdx/validation/test_snippet_validator.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List from unittest import TestCase diff --git a/tests/spdx/validation/test_spdx_id_validators.py b/tests/spdx/validation/test_spdx_id_validators.py index e29697862..a32e46acd 100644 --- a/tests/spdx/validation/test_spdx_id_validators.py +++ b/tests/spdx/validation/test_spdx_id_validators.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import TestCase import pytest diff --git a/tests/spdx/validation/test_uri_validators.py b/tests/spdx/validation/test_uri_validators.py index 59a8dd1e5..119be756a 100644 --- a/tests/spdx/validation/test_uri_validators.py +++ b/tests/spdx/validation/test_uri_validators.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/writer/json/test_json_writer.py b/tests/spdx/writer/json/test_json_writer.py index aff0c9501..432498abd 100644 --- a/tests/spdx/writer/json/test_json_writer.py +++ b/tests/spdx/writer/json/test_json_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import json import os diff --git a/tests/spdx/writer/rdf/test_annotation_writer.py b/tests/spdx/writer/rdf/test_annotation_writer.py index 1e616ac6a..6ac4e2f15 100644 --- a/tests/spdx/writer/rdf/test_annotation_writer.py +++ b/tests/spdx/writer/rdf/test_annotation_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, Graph, Literal, URIRef from spdx.datetime_conversions import datetime_to_iso_string diff --git a/tests/spdx/writer/rdf/test_checksum_writer.py b/tests/spdx/writer/rdf/test_checksum_writer.py index 76560e8e4..38451242c 100644 --- a/tests/spdx/writer/rdf/test_checksum_writer.py +++ b/tests/spdx/writer/rdf/test_checksum_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from rdflib import RDF, Graph, Literal, URIRef diff --git a/tests/spdx/writer/rdf/test_creation_info_writer.py b/tests/spdx/writer/rdf/test_creation_info_writer.py index 0a3e5155a..310903677 100644 --- a/tests/spdx/writer/rdf/test_creation_info_writer.py +++ b/tests/spdx/writer/rdf/test_creation_info_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, Graph, Literal, URIRef from spdx.datetime_conversions import datetime_to_iso_string diff --git a/tests/spdx/writer/rdf/test_external_document_ref_writer.py b/tests/spdx/writer/rdf/test_external_document_ref_writer.py index 6e6acf8f7..6a8ddc4e7 100644 --- a/tests/spdx/writer/rdf/test_external_document_ref_writer.py +++ b/tests/spdx/writer/rdf/test_external_document_ref_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, Graph, URIRef from spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py b/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py index 3019d62ac..0dd2df95c 100644 --- a/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py +++ b/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, Graph, Literal, URIRef from spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/tests/spdx/writer/rdf/test_file_writer.py b/tests/spdx/writer/rdf/test_file_writer.py index d28a1c9b8..17092c457 100644 --- a/tests/spdx/writer/rdf/test_file_writer.py +++ b/tests/spdx/writer/rdf/test_file_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, Graph, Literal, URIRef from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE diff --git a/tests/spdx/writer/rdf/test_license_expression_writer.py b/tests/spdx/writer/rdf/test_license_expression_writer.py index 73152ee69..f90022cb1 100644 --- a/tests/spdx/writer/rdf/test_license_expression_writer.py +++ b/tests/spdx/writer/rdf/test_license_expression_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from license_expression import get_spdx_licensing from rdflib import RDF, Graph, Literal, URIRef diff --git a/tests/spdx/writer/rdf/test_package_writer.py b/tests/spdx/writer/rdf/test_package_writer.py index bab01ff53..6fd86351b 100644 --- a/tests/spdx/writer/rdf/test_package_writer.py +++ b/tests/spdx/writer/rdf/test_package_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from rdflib import DOAP, RDF, RDFS, XSD, Graph, Literal, URIRef diff --git a/tests/spdx/writer/rdf/test_rdf_writer.py b/tests/spdx/writer/rdf/test_rdf_writer.py index 3d99c2389..d3fb42380 100644 --- a/tests/spdx/writer/rdf/test_rdf_writer.py +++ b/tests/spdx/writer/rdf/test_rdf_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import os import pytest diff --git a/tests/spdx/writer/rdf/test_relationship_writer.py b/tests/spdx/writer/rdf/test_relationship_writer.py index dc559caf0..3c208b7c3 100644 --- a/tests/spdx/writer/rdf/test_relationship_writer.py +++ b/tests/spdx/writer/rdf/test_relationship_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, Literal, URIRef from spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/tests/spdx/writer/rdf/test_snippet_writer.py b/tests/spdx/writer/rdf/test_snippet_writer.py index 53c493ded..9f6343876 100644 --- a/tests/spdx/writer/rdf/test_snippet_writer.py +++ b/tests/spdx/writer/rdf/test_snippet_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from rdflib import RDF, RDFS, Graph, Literal, URIRef diff --git a/tests/spdx/writer/rdf/test_writer_utils.py b/tests/spdx/writer/rdf/test_writer_utils.py index aa74c570f..dd9978b3f 100644 --- a/tests/spdx/writer/rdf/test_writer_utils.py +++ b/tests/spdx/writer/rdf/test_writer_utils.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id From 8da3a321a1cdb93329299534eb0f80bcb0b9f0f4 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 30 Mar 2023 12:28:32 +0200 Subject: [PATCH 035/354] [issue-547] rdf parser: use licenseID from extracted licensing info URIRef if no licenseId node is provided Signed-off-by: Meret Behrens --- .../rdf/extracted_licensing_info_parser.py | 11 +- src/spdx/parser/rdf/rdf_parser.py | 4 +- .../formats/SPDXRdfExample-v2.2.spdx.rdf.xml | 4146 +++++++++++++++++ .../rdf/data/file_to_test_rdf_parser.rdf.xml | 8 + .../test_extracted_licensing_info_parser.py | 48 +- tests/spdx/parser/rdf/test_rdf_parser.py | 19 + 6 files changed, 4225 insertions(+), 11 deletions(-) create mode 100644 tests/spdx/data/formats/SPDXRdfExample-v2.2.spdx.rdf.xml diff --git a/src/spdx/parser/rdf/extracted_licensing_info_parser.py b/src/spdx/parser/rdf/extracted_licensing_info_parser.py index 663c2e260..1763eb214 100644 --- a/src/spdx/parser/rdf/extracted_licensing_info_parser.py +++ b/src/spdx/parser/rdf/extracted_licensing_info_parser.py @@ -10,9 +10,18 @@ from spdx.rdfschema.namespace import SPDX_NAMESPACE -def parse_extracted_licensing_info(extracted_licensing_info_node: URIRef, graph: Graph) -> ExtractedLicensingInfo: +def parse_extracted_licensing_info( + extracted_licensing_info_node: URIRef, graph: Graph, doc_namespace: str +) -> ExtractedLicensingInfo: logger = Logger() license_id = parse_literal(logger, graph, extracted_licensing_info_node, SPDX_NAMESPACE.licenseId) + if not license_id: + license_id = ( + extracted_licensing_info_node.fragment + if extracted_licensing_info_node.startswith(f"{doc_namespace}#") + else extracted_licensing_info_node.toPython() + ) + extracted_text = parse_literal(logger, graph, extracted_licensing_info_node, SPDX_NAMESPACE.extractedText) comment = parse_literal(logger, graph, extracted_licensing_info_node, RDFS.comment) license_name = parse_literal_or_no_assertion_or_none( diff --git a/src/spdx/parser/rdf/rdf_parser.py b/src/spdx/parser/rdf/rdf_parser.py index ae6baf3bc..09b2173e0 100644 --- a/src/spdx/parser/rdf/rdf_parser.py +++ b/src/spdx/parser/rdf/rdf_parser.py @@ -65,7 +65,9 @@ def translate_graph_to_document(graph: Graph) -> Document: extracted_licensing_infos = [] for _, _, extracted_licensing_info_node in graph.triples((None, SPDX_NAMESPACE.hasExtractedLicensingInfo, None)): try: - extracted_licensing_infos.append(parse_extracted_licensing_info(extracted_licensing_info_node, graph)) + extracted_licensing_infos.append( + parse_extracted_licensing_info(extracted_licensing_info_node, graph, creation_info.document_namespace) + ) except SPDXParsingError as err: logger.extend(err.get_messages()) parsed_fields["extracted_licensing_info"] = extracted_licensing_infos diff --git a/tests/spdx/data/formats/SPDXRdfExample-v2.2.spdx.rdf.xml b/tests/spdx/data/formats/SPDXRdfExample-v2.2.spdx.rdf.xml new file mode 100644 index 000000000..f5c306f74 --- /dev/null +++ b/tests/spdx/data/formats/SPDXRdfExample-v2.2.spdx.rdf.xml @@ -0,0 +1,4146 @@ + + + + from linux kernel + + + + + 23 + + + Copyright 2010, 2011 Source Auditor Inc. + Open Logic Inc. + ./src/org/spdx/parser/DOAPProject.java + Black Duck Software In.c + Source Auditor Inc. + SPDX Technical Team Members + + + + <div class="optional-license-text"> + <p>Apache License + <br /> + +Version 2.0, January 2004 + <br /> + +http://www.apache.org/licenses/ + </p> + + </div> + <div class="optional-license-text"> + <p>TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION</p> + + </div> + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">1.</var> + Definitions. + +<ul style="list-style:none"> +<li> + <p>&quot;License&quot; shall mean the terms and conditions for use, reproduction, and distribution + as defined by Sections 1 through 9 of this document.</p> + + </li> +<li> + <p>&quot;Licensor&quot; shall mean the copyright owner or entity authorized by the copyright owner + that is granting the License.</p> + + </li> +<li> + <p>&quot;Legal Entity&quot; shall mean the union of the acting entity and all other entities that + control, are controlled by, or are under common control with that entity. For the purposes of + this definition, &quot;control&quot; means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or otherwise, or (ii) ownership of + fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such + entity.</p> + + </li> +<li> + <p>&quot;You&quot; (or &quot;Your&quot;) shall mean an individual or Legal Entity exercising + permissions granted by this License.</p> + + </li> +<li> + <p>&quot;Source&quot; form shall mean the preferred form for making modifications, including but not + limited to software source code, documentation source, and configuration files.</p> + + </li> +<li> + <p>&quot;Object&quot; form shall mean any form resulting from mechanical transformation or + translation of a Source form, including but not limited to compiled object code, generated + documentation, and conversions to other media types.</p> + + </li> +<li> + <p>&quot;Work&quot; shall mean the work of authorship, whether in Source or Object form, made + available under the License, as indicated by a copyright notice that is included in or + attached to the work (an example is provided in the Appendix below).</p> + + </li> +<li> + <p>&quot;Derivative Works&quot; shall mean any work, whether in Source or Object form, that is based + on (or derived from) the Work and for which the editorial revisions, annotations, + elaborations, or other modifications represent, as a whole, an original work of authorship. + For the purposes of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative + Works thereof.</p> + + </li> +<li> + <p>&quot;Contribution&quot; shall mean any work of authorship, including the original version of the + Work and any modifications or additions to that Work or Derivative Works thereof, that is + intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an + individual or Legal Entity authorized to submit on behalf of the copyright owner. For the + purposes of this definition, &quot;submitted&quot; means any form of electronic, verbal, or + written communication sent to the Licensor or its representatives, including but not limited + to communication on electronic mailing lists, source code control systems, and issue tracking + systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and + improving the Work, but excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as &quot;Not a Contribution.&quot;</p> + + </li> +<li> + <p>&quot;Contributor&quot; shall mean Licensor and any individual or Legal Entity on behalf of whom + a Contribution has been received by Licensor and subsequently incorporated within the + Work.</p> + + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">2.</var> + Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor + hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, + irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, + publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or + Object form. + </li> +<li> + <var class="replacable-license-text">3.</var> + Grant of Patent License. Subject to the terms and conditions of this License, each Contributor + hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, + irrevocable (except as stated in this section) patent license to make, have made, use, offer + to sell, sell, import, and otherwise transfer the Work, where such license applies only to + those patent claims licensable by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) with the Work to which such + Contribution(s) was submitted. If You institute patent litigation against any entity + (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a + Contribution incorporated within the Work constitutes direct or contributory patent + infringement, then any patent licenses granted to You under this License for that Work shall + terminate as of the date such litigation is filed. + </li> +<li> + <var class="replacable-license-text">4.</var> + Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof + in any medium, with or without modifications, and in Source or Object form, provided that You + meet the following conditions: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">(a)</var> + You must give any other recipients of the Work or Derivative Works a copy of this License; and + </li> +<li> + <var class="replacable-license-text">(b)</var> + You must cause any modified files to carry prominent notices stating that You changed the files; and + </li> +<li> + <var class="replacable-license-text">(c)</var> + You must retain, in the Source form of any Derivative Works that You distribute, all + copyright, patent, trademark, and attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of the Derivative Works; and + </li> +<li> + <var class="replacable-license-text">(d)</var> + If the Work includes a &quot;NOTICE&quot; text file as part of its distribution, then any + Derivative Works that You distribute must include a readable copy of the attribution + notices contained within such NOTICE file, excluding those notices that do not pertain to + any part of the Derivative Works, in at least one of the following places: within a NOTICE + text file distributed as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, within a display generated + by the Derivative Works, if and wherever such third-party notices normally appear. The + contents of the NOTICE file are for informational purposes only and do not modify the + License. You may add Your own attribution notices within Derivative Works that You + distribute, alongside or as an addendum to the NOTICE text from the Work, provided that + such additional attribution notices cannot be construed as modifying the License. + <p>You may add Your own copyright statement to Your modifications and may provide additional or + different license terms and conditions for use, reproduction, or distribution of Your + modifications, or for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with the conditions stated + in this License.</p> + + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">5.</var> + Submission of Contributions. Unless You explicitly state otherwise, any Contribution + intentionally submitted for inclusion in the Work by You to the Licensor shall be under the + terms and conditions of this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate + license agreement you may have executed with Licensor regarding such Contributions. + </li> +<li> + <var class="replacable-license-text">6.</var> + Trademarks. This License does not grant permission to use the trade names, trademarks, service + marks, or product names of the Licensor, except as required for reasonable and customary use + in describing the origin of the Work and reproducing the content of the NOTICE file. + </li> +<li> + <var class="replacable-license-text">7.</var> + Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor + provides the Work (and each Contributor provides its Contributions) on an &quot;AS IS&quot; + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, + without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, + or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any risks associated with Your + exercise of permissions under this License. + </li> +<li> + <var class="replacable-license-text">8.</var> + Limitation of Liability. In no event and under no legal theory, whether in tort (including + negligence), contract, or otherwise, unless required by applicable law (such as deliberate and + grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for + damages, including any direct, indirect, special, incidental, or consequential damages of any + character arising as a result of this License or out of the use or inability to use the Work + (including but not limited to damages for loss of goodwill, work stoppage, computer failure or + malfunction, or any and all other commercial damages or losses), even if such Contributor has + been advised of the possibility of such damages. + </li> +<li> + <var class="replacable-license-text">9.</var> + Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works + thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, + indemnity, or other liability obligations and/or rights consistent with this License. However, + in accepting such obligations, You may act only on Your own behalf and on Your sole + responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability incurred by, or claims asserted + against, such Contributor by reason of your accepting any such warranty or additional + liability. + </li> +</ul> + + <div class="optional-license-text"> + <p>END OF TERMS AND CONDITIONS</p> + + <p>APPENDIX: How to apply the Apache License to your work.</p> + + <p>To apply the Apache License to your work, attach the following boilerplate notice, with the fields + enclosed by brackets &quot;[]&quot; replaced with your own identifying information. (Don&apos;t + include the brackets!) The text should be enclosed in the appropriate comment syntax for the file + format. We also recommend that a file or class name and description of purpose be included on the same + &quot;printed page&quot; as the copyright notice for easier identification within third-party + archives.</p> + + <p>Copyright <var class="replacable-license-text">[yyyy] [name of copyright owner]</var></p> + + <p>Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); + <br /> + +you may not use this file except in compliance with the License. + <br /> + +You may obtain a copy of the License at + </p> + + <p>http://www.apache.org/licenses/LICENSE-2.0</p> + + <p>Unless required by applicable law or agreed to in writing, software + <br /> + +distributed under the License is distributed on an &quot;AS IS&quot; BASIS, + <br /> + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + <br /> + +See the License for the specific language governing permissions and + <br /> + +limitations under the License. + </p> + + </div> + + This license was released January 2004 + Apache License 2.0 + + + 0 + 2021-05-20 - 16:57:10 + http://www.apache.org/licenses/LICENSE-2.0 + true + false + true + true + + + <<beginOptional>> Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +<<endOptional>><<beginOptional>> TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +<<endOptional>> + + <<var;name="bullet";original="1.";match=".{0,20}">> Definitions. + + "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + + "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + + <<var;name="bullet";original="2.";match=".{0,20}">> Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + + <<var;name="bullet";original="3.";match=".{0,20}">> Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + + <<var;name="bullet";original="4.";match=".{0,20}">> Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + <<var;name="bullet";original="(a)";match=".{0,20}">> You must give any other recipients of the Work or Derivative Works a copy of this License; and + + <<var;name="bullet";original="(b)";match=".{0,20}">> You must cause any modified files to carry prominent notices stating that You changed the files; and + + <<var;name="bullet";original="(c)";match=".{0,20}">> You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + <<var;name="bullet";original="(d)";match=".{0,20}">> If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + + <<var;name="bullet";original="5.";match=".{0,20}">> Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + + <<var;name="bullet";original="6.";match=".{0,20}">> Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + + <<var;name="bullet";original="7.";match=".{0,20}">> Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + + <<var;name="bullet";original="8.";match=".{0,20}">> Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + + <<var;name="bullet";original="9.";match=".{0,20}">> Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.<<beginOptional>> END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright <<var;name="copyright";original="[yyyy] [name of copyright owner]";match=".+">> + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + +<<endOptional>> + + + 1 + 2021-05-20 - 16:57:10 + https://opensource.org/licenses/Apache-2.0 + true + false + true + true + + + Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + + + + <p>Copyright <var class="replacable-license-text">[yyyy] [name of copyright owner]</var></p> + + <p>Licensed under the Apache License, Version 2.0 (the &quot;License&quot;); + <br /> + +you may not use this file except in compliance with the License. + <br /> + +You may obtain a copy of the License at + </p> + + <p>http://www.apache.org/licenses/LICENSE-2.0</p> + + <p>Unless required by applicable law or agreed to in writing, software + <br /> + +distributed under the License is distributed on an &quot;AS IS&quot; BASIS, + <br /> + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + <br /> + +See the License for the specific language governing permissions and + <br /> + +limitations under the License. + </p> + + + Copyright <<var;name="copyright";original="[yyyy] [name of copyright owner]";match=".+">> + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. + + + true + true + https://opensource.org/licenses/Apache-2.0 + http://www.apache.org/licenses/LICENSE-2.0 + false + Apache-2.0 + Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + + + + + + 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 + + + Protecode Inc. + + + + + + + + + 5 + + + + + + Copyright 2008-2010 John Smith + The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. + + + + + 420 + + + + + + 310 + + + + + + + + + https://opensource.org/licenses/GPL-2.0 + This license was released: June 1991. This license identifier refers to the choice to use the code under GPL-2.0-only, as distinguished from use of code under GPL-2.0-or-later (i.e., GPL-2.0 or some later version). The license notice (as seen in the Standard License Header field below) states which of these applies to the code in the file. The example in the exhibit to the license shows the license notice for the "or later" approach. + GPL-2.0-only + https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html + + <div class="optional-license-text"> + <p> + GNU GENERAL PUBLIC LICENSE<br /> + + Version 2, June 1991 + </p> + + </div> + <p> + Copyright (C) 1989, 1991 Free Software Foundation, Inc.<var class="replacable-license-text"></var><br /> + + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<var class="optional-license-text">,</var> + USA + </p> + + <p> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + </p> + + <p> + Preamble + </p> + + <p> + The licenses for most software are designed to take away your freedom + to share and change it. By contrast, the GNU General Public License is + intended to guarantee your freedom to share and change free software--to + make sure the software is free for all its users. This General Public + License applies to most of the Free Software Foundation&apos;s software + and to any other program whose authors commit to using it. (Some other + Free Software Foundation software is covered by the GNU Lesser General + Public License instead.) You can apply it to your programs, too. + </p> + + <p> + When we speak of free software, we are referring to freedom, not price. + Our General Public Licenses are designed to make sure that you have + the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get + it if you want it, that you can change the software or use pieces of + it in new free programs; and that you know you can do these things. + </p> + + <p> + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the + rights. These restrictions translate to certain responsibilities for + you if you distribute copies of the software, or if you modify it. + </p> + + <p> + For example, if you distribute copies of such a program, whether gratis + or for a fee, you must give the recipients all the rights that you + have. You must make sure that they, too, receive or can get the source + code. And you must show them these terms so they know their rights. + </p> + + <p> + We protect your rights with two steps: (1) copyright the + software, and (2) offer you this license which gives you legal + permission to copy, distribute and/or modify the software. + </p> + + <p> + Also, for each author&apos;s protection and ours, we want to make + certain that everyone understands that there is no warranty for + this free software. If the software is modified by someone else + and passed on, we want its recipients to know that what they + have is not the original, so that any problems introduced by + others will not reflect on the original authors&apos; reputations. + </p> + + <p> + Finally, any free program is threatened constantly by software patents. + We wish to avoid the danger that redistributors of a free program + will individually obtain patent licenses, in effect making the program + proprietary. To prevent this, we have made it clear that any patent + must be licensed for everyone&apos;s free use or not licensed at all. + </p> + + <p> + The precise terms and conditions for copying, + distribution and modification follow. + </p> + + <p> + <var class="replacable-license-text"></var> + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + </p> + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">0.</var> + This License applies to any program or other work which contains a + notice placed by the copyright holder saying it may be distributed + under the terms of this General Public License. The &quot;Program&quot;, below, + refers to any such program or work, and a &quot;work based on the Program&quot; + means either the Program or any derivative work under copyright law: + that is to say, a work containing the Program or a portion of it, + either verbatim or with modifications and/or translated into another + language. (Hereinafter, translation is included without limitation + in the term &quot;modification&quot;.) Each licensee is addressed as &quot;you&quot;. + <p> + Activities other than copying, distribution and modification are + not covered by this License; they are outside its scope. The act + of running the Program is not restricted, and the output from the + Program is covered only if its contents constitute a work based + on the Program (independent of having been made by running the + Program). Whether that is true depends on what the Program does. + </p> + + </li> +<li> + <var class="replacable-license-text">1.</var> + You may copy and distribute verbatim copies of the Program&apos;s source + code as you receive it, in any medium, provided that you conspicuously + and appropriately publish on each copy an appropriate copyright notice + and disclaimer of warranty; keep intact all the notices that refer to + this License and to the absence of any warranty; and give any other + recipients of the Program a copy of this License along with the Program. + <p> + You may charge a fee for the physical act of + transferring a copy, and you may at your option + offer warranty protection in exchange for a fee. + </p> + + </li> +<li> + <var class="replacable-license-text">2.</var> + You may modify your copy or copies of the Program or any portion + of it, thus forming a work based on the Program, and copy and + distribute such modifications or work under the terms of Section + 1 above, provided that you also meet all of these conditions: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">a)</var> + You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + </li> +<li> + <var class="replacable-license-text">b)</var> + You must cause any work that you distribute or publish, + that in whole or in part contains or is derived from the + Program or any part thereof, to be licensed as a whole at no + charge to all third parties under the terms of this License. + </li> +<li> + <var class="replacable-license-text">c)</var> + If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display + an announcement including an appropriate copyright notice and + a notice that there is no warranty (or else, saying that you + provide a warranty) and that users may redistribute the program + under these conditions, and telling the user how to view a copy + of this License. (Exception: if the Program itself is interactive + but does not normally print such an announcement, your work + based on the Program is not required to print an announcement.) + </li> +</ul> + <p> + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the + Program, and can be reasonably considered independent and separate + works in themselves, then this License, and its terms, do not + apply to those sections when you distribute them as separate + works. But when you distribute the same sections as part of a + whole which is a work based on the Program, the distribution + of the whole must be on the terms of this License, whose + permissions for other licensees extend to the entire whole, + and thus to each and every part regardless of who wrote it. + </p> + + <p> + Thus, it is not the intent of this section to claim rights or + contest your rights to work written entirely by you; rather, + the intent is to exercise the right to control the distribution + of derivative or collective works based on the Program. + </p> + + <p> + In addition, mere aggregation of another work not based on + the Program with the Program (or with a work based on the + Program) on a volume of a storage or distribution medium does + not bring the other work under the scope of this License. + </p> + + </li> +<li> + <var class="replacable-license-text">3.</var> + You may copy and distribute the Program (or a work based on it, + under Section 2) in object code or executable form under the terms of + Sections 1 and 2 above provided that you also do one of the following: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">a)</var> + Accompany it with the complete corresponding machine-readable source + code, which must be distributed under the terms of Sections 1 and + 2 above on a medium customarily used for software interchange; or, + </li> +<li> + <var class="replacable-license-text">b)</var> + Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to + be distributed under the terms of Sections 1 and 2 above + on a medium customarily used for software interchange; or, + </li> +<li> + <var class="replacable-license-text">c)</var> + Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative + is allowed only for noncommercial distribution and only if + you received the program in object code or executable form + with such an offer, in accord with Subsection b above.) + </li> +</ul> + <p> + The source code for a work means the preferred form of the work + for making modifications to it. For an executable work, complete + source code means all the source code for all modules it contains, + plus any associated interface definition files, plus the scripts + used to control compilation and installation of the executable. + However, as a special exception, the source code distributed + need not include anything that is normally distributed (in either + source or binary form) with the major components (compiler, + kernel, and so on) of the operating system on which the executable + runs, unless that component itself accompanies the executable. + </p> + + <p> + If distribution of executable or object code is made by offering + access to copy from a designated place, then offering equivalent + access to copy the source code from the same place counts as + distribution of the source code, even though third parties are + not compelled to copy the source along with the object code. + </p> + + </li> +<li> + <var class="replacable-license-text">4.</var> + You may not copy, modify, sublicense, or distribute the Program + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense or distribute the Program + is void, and will automatically terminate your rights under + this License. However, parties who have received copies, or + rights, from you under this License will not have their licenses + terminated so long as such parties remain in full compliance. + </li> +<li> + <var class="replacable-license-text">5.</var> + You are not required to accept this License, since you have + not signed it. However, nothing else grants you permission to + modify or distribute the Program or its derivative works. These + actions are prohibited by law if you do not accept this License. + Therefore, by modifying or distributing the Program (or any + work based on the Program), you indicate your acceptance of this + License to do so, and all its terms and conditions for copying, + distributing or modifying the Program or works based on it. + </li> +<li> + <var class="replacable-license-text">6.</var> + Each time you redistribute the Program (or any work based on the + Program), the recipient automatically receives a license from the + original licensor to copy, distribute or modify the Program subject to + these terms and conditions. You may not impose any further restrictions + on the recipients&apos; exercise of the rights granted herein. You are not + responsible for enforcing compliance by third parties to this License. + </li> +<li> + <var class="replacable-license-text">7.</var> + If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement + or otherwise) that contradict the conditions of this License, + they do not excuse you from the conditions of this License. If you + cannot distribute so as to satisfy simultaneously your obligations + under this License and any other pertinent obligations, then as a + consequence you may not distribute the Program at all. For example, + if a patent license would not permit royalty-free redistribution of + the Program by all those who receive copies directly or indirectly + through you, then the only way you could satisfy both it and this + License would be to refrain entirely from distribution of the Program. + <p> + If any portion of this section is held invalid or + unenforceable under any particular circumstance, the + balance of the section is intended to apply and the section + as a whole is intended to apply in other circumstances. + </p> + + <p> + It is not the purpose of this section to induce you to infringe + any patents or other property right claims or to contest + validity of any such claims; this section has the sole purpose + of protecting the integrity of the free software distribution + system, which is implemented by public license practices. Many + people have made generous contributions to the wide range of + software distributed through that system in reliance on consistent + application of that system; it is up to the author/donor to + decide if he or she is willing to distribute software through + any other system and a licensee cannot impose that choice. + </p> + + <p> + This section is intended to make thoroughly clear what is + believed to be a consequence of the rest of this License. + </p> + + </li> +<li> + <var class="replacable-license-text">8.</var> + If the distribution and/or use of the Program is restricted in + certain countries either by patents or by copyrighted interfaces, + the original copyright holder who places the Program under this + License may add an explicit geographical distribution limitation + excluding those countries, so that distribution is permitted only + in or among countries not thus excluded. In such case, this License + incorporates the limitation as if written in the body of this License. + </li> +<li> + <var class="replacable-license-text">9.</var> + The Free Software Foundation may publish revised and/or new + versions of the General Public License from time to time. Such + new versions will be similar in spirit to the present version, + but may differ in detail to address new problems or concerns. + <p> + Each version is given a distinguishing version number. If the + Program specifies a version number of this License which applies + to it and &quot;any later version&quot;, you have the option of following + the terms and conditions either of that version or of any later + version published by the Free Software Foundation. If the Program + does not specify a version number of this License, you may choose + any version ever published by the Free Software Foundation. + </p> + + </li> +<li> + <var class="replacable-license-text">10.</var> + If you wish to incorporate parts of the Program into other free + programs whose distribution conditions are different, write to the + author to ask for permission. For software which is copyrighted by the + Free Software Foundation, write to the Free Software Foundation; we + sometimes make exceptions for this. Our decision will be guided by the + two goals of preserving the free status of all derivatives of our free + software and of promoting the sharing and reuse of software generally. + <p> + NO WARRANTY + </p> + + </li> +<li> + <var class="replacable-license-text">11.</var> + BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY + FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT + WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER + PARTIES PROVIDE THE PROGRAM &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, + EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF + THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU + ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + </li> +<li> + <var class="replacable-license-text">12.</var> + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR + DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL + DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM + (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED + INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF + THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER + OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + </li> +</ul> + <div class="optional-license-text"> + <p> + END OF TERMS AND CONDITIONS + </p> + + <p> + How to Apply These Terms to Your New Programs + </p> + + <p> + If you develop a new program, and you want it to be + of the greatest possible use to the public, the best + way to achieve this is to make it free software which + everyone can redistribute and change under these terms. + </p> + + <p> + To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + convey the exclusion of warranty; and each file should have at least + the &quot;copyright&quot; line and a pointer to where the full notice is found. + </p> + + <p> + <var class="optional-license-text">&lt;</var>one line to give the program&apos;s name and <var class="replacable-license-text">an</var> idea of what it does.<var class="optional-license-text">&gt;</var> + <br /> + + Copyright (C) + <var class="optional-license-text">&lt;</var><var class="replacable-license-text">yyyy</var><var class="optional-license-text">&gt;</var> + <var class="optional-license-text">&lt;</var>name of author<var class="optional-license-text">&gt;</var> + </p> + + <p> + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version + 2 of the License, or (at your option) any later version. + </p> + + <p> + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU General Public License for more details. + </p> + + <p> + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<var class="optional-license-text">,</var> + USA. + </p> + + <p> + Also add information on how to + contact you by electronic and paper mail. + </p> + + <p> + If the program is interactive, make it output a short + notice like this when it starts in an interactive mode: + </p> + + <p> + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details + type `show w&apos;. This is free software, and you are welcome to + redistribute it under certain conditions; type `show c&apos; for details. + </p> + + <p> + The hypothetical commands `show w&apos; and `show c&apos; should show the + appropriate parts of the General Public License. Of course, the commands + you use may be called something other than `show w&apos; and `show c&apos;; they + could even be mouse-clicks or menu items--whatever suits your program. + </p> + + <p> + You should also get your employer (if you work as a programmer) + or your school, if any, to sign a &quot;copyright disclaimer&quot; for + the program, if necessary. Here is a sample; alter the names: + </p> + + <p> + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision&apos; (which makes passes at compilers) written by James Hacker. + </p> + + <p> + <var class="optional-license-text">&lt;</var>signature of Ty Coon<var class="optional-license-text">&gt;</var>, + 1 April 1989 Ty Coon, President of Vice + </p> + + </div> + <div class="optional-license-text"> + <p> + This General Public License does not permit incorporating your program into + proprietary programs. If your program is a subroutine library, you may + consider it more useful to permit linking proprietary applications with the + library. If this is what you want to do, use the GNU Lesser General + Public License instead of this License. + </p> + + </div> + + true + Copyright (C) <<var;name="copyright";original="yyyy name of author";match=".+">> + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<<beginOptional>>, <<endOptional>> USA. + + + false + GNU General Public License v2.0 only + <<beginOptional>> GNU GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +<<endOptional>> + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. <<var;name="incComma";original="";match=",|">> + +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<<beginOptional>>, <<endOptional>> USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +<<var;name="termsTitle";original="";match="GNU GENERAL PUBLIC LICENSE|">> TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + <<var;name="bullet";original="0.";match=".{0,20}">> This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + + Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + + <<var;name="bullet";original="1.";match=".{0,20}">> You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + + You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + + <<var;name="bullet";original="2.";match=".{0,20}">> You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + <<var;name="bullet";original="a)";match=".{0,20}">> You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + + <<var;name="bullet";original="b)";match=".{0,20}">> You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + + <<var;name="bullet";original="c)";match=".{0,20}">> If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + + In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + + <<var;name="bullet";original="3.";match=".{0,20}">> You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + + <<var;name="bullet";original="a)";match=".{0,20}">> Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + <<var;name="bullet";original="b)";match=".{0,20}">> Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + <<var;name="bullet";original="c)";match=".{0,20}">> Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + + The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + + If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + + <<var;name="bullet";original="4.";match=".{0,20}">> You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + + <<var;name="bullet";original="5.";match=".{0,20}">> You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + + <<var;name="bullet";original="6.";match=".{0,20}">> Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + + <<var;name="bullet";original="7.";match=".{0,20}">> If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + + If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + + It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + + <<var;name="bullet";original="8.";match=".{0,20}">> If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + + <<var;name="bullet";original="9.";match=".{0,20}">> The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + + <<var;name="bullet";original="10.";match=".{0,20}">> If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + + NO WARRANTY + + <<var;name="bullet";original="11.";match=".{0,20}">> BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + <<var;name="bullet";original="12.";match=".{0,20}">> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.<<beginOptional>> END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + +<<beginOptional>><<<endOptional>>one line to give the program's name and <<var;name="ideaArticle";original="an";match="a brief|an">> idea of what it does.<<beginOptional>>><<endOptional>> + +Copyright (C)<<beginOptional>><<<endOptional>> <<var;name="templateYear";original="yyyy";match="yyyy|year">><<beginOptional>>> <<endOptional>><<beginOptional>> <<<endOptional>>name of author<<beginOptional>>><<endOptional>> + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<<beginOptional>>, <<endOptional>> USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + +Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. + +<<beginOptional>><<<endOptional>>signature of Ty Coon<<beginOptional>> ><<endOptional>>, 1 April 1989 Ty Coon, President of Vice + +<<endOptional>><<beginOptional>> This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. + +<<endOptional>> + + Copyright (C) <var class="replacable-license-text">yyyy name of author</var> + <p> + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2. + </p> + + <p> + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU General Public License for more details. + </p> + + <p> + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301<var class="optional-license-text">,</var> + USA. + </p> + + + + + 1 + 2021-05-20 - 16:58:58 + https://opensource.org/licenses/GPL-2.0 + false + false + true + true + + + + + 0 + 2021-05-20 - 16:58:58 + https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html + true + false + true + true + + + true + GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. + + c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author + + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. + +signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice + + Copyright (C) yyyy name of author + +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + + + + + This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0. + + + + + + + + http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz + + + + + http://justasample.url.com + http://people.apache.org/~andyc/neko/LICENSE + This is tye CyperNeko License + The CyberNeko Software License, Version 1.0 + + +(C) Copyright 2002-2005, Andy Clark. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by Andy Clark." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + +4. The names "CyberNeko" and "NekoHTML" must not be used to endorse + or promote products derived from this software without prior + written permission. For written permission, please contact + andyc@cyberneko.net. + +5. Products derived from this software may not be called "CyberNeko", + nor may "CyberNeko" appear in their name, without prior written + permission of the author. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + CyberNeko License + + + + + GNU LIBRARY GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +Copyright (C) 1991 Free Software Foundation, Inc. +51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. + +This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. + +For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. + +Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. + +Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. + +The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. + +Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. + +However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. + +The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. + +Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". + +A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. + +The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) + +"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. + +1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. + +(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. + +Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. + +This option is useful when you wish to copy part of the code of the Library into a program that is not a library. + +4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. + +If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. + +5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. + +However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. + +When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. + +If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) + +Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. + +6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. + +You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: + + a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. + + d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. + +For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. + +7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. + + b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. + +8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. + +10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. + +14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). + +To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + + one line to give the library's name and an idea of what it does. + Copyright (C) year name of author + + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in +the library `Frob' (a library for tweaking knobs) written +by James Random Hacker. + +signature of Ty Coon, 1 April 1990 +Ty Coon, President of Vice + +That's all there is to it! + LGPL-2.0-only + https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html + false + + Copyright (C) <var class="replacable-license-text">year name of author</var> + <p>This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; version 2.</p> + + <p>This library is distributed + in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the GNU Library General Public License for more details.</p> + + <p>You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + </p> + + + <<beginOptional>> GNU LIBRARY GENERAL PUBLIC LICENSE + +Version 2, June 1991 + +<<endOptional>> <<var;name="copyright";original="Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ";match=".{0,5000}">> + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] + +Preamble + +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. + +This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. + +For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. + +Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. + +Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. + +The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. + +Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. + +However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. + +The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. + +Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + <<var;name="bullet";original="0.";match=".{0,20}">> This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. + + Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. + + <<var;name="bullet";original="1.";match=".{0,20}">> You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. + + You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + + <<var;name="bullet";original="2.";match=".{0,20}">> You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + + <<var;name="bullet";original="a)";match=".{0,20}">> The modified work must itself be a software library. + + <<var;name="bullet";original="b)";match=".{0,20}">> You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. + + <<var;name="bullet";original="c)";match=".{0,20}">> You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. + + <<var;name="bullet";original="d)";match=".{0,20}">> If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. + + (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) + + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + + Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. + + In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + + <<var;name="bullet";original="3.";match=".{0,20}">> You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. + + Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of the Library into a program that is not a library. + + <<var;name="bullet";original="4.";match=".{0,20}">> You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. + + <<var;name="bullet";original="5.";match=".{0,20}">> A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. + + <<var;name="bullet";original="6.";match=".{0,20}">> As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: + + <<var;name="bullet";original="a)";match=".{0,20}">> Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) + + <<var;name="bullet";original="b)";match=".{0,20}">> Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. + + <<var;name="bullet";original="c)";match=".{0,20}">> If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. + + <<var;name="bullet";original="d)";match=".{0,20}">> Verify that the user has already received a copy of these materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + + It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. + + <<var;name="bullet";original="7.";match=".{0,20}">> You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: + + <<var;name="bullet";original="a)";match=".{0,20}">> Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. + + <<var;name="bullet";original="b)";match=".{0,20}">> Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. + + <<var;name="bullet";original="8.";match=".{0,20}">> You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + + <<var;name="bullet";original="9.";match=".{0,20}">> You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. + + <<var;name="bullet";original="10.";match=".{0,20}">> Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + + <<var;name="bullet";original="11.";match=".{0,20}">> If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. + + If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. + + It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + + This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + + <<var;name="bullet";original="12.";match=".{0,20}">> If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + + <<var;name="bullet";original="13.";match=".{0,20}">> The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. + + <<var;name="bullet";original="14.";match=".{0,20}">> If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + + NO WARRANTY + + <<var;name="bullet";original="15.";match=".{0,20}">> BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + <<var;name="bullet";original="16.";match=".{0,20}">> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.<<beginOptional>> END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Libraries + +If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). + +To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + +one line to give the library's name and an idea of what it does. + +Copyright (C) year name of author + +This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in + +the library `Frob' (a library for tweaking knobs) written + +by James Random Hacker. + +signature of Ty Coon, 1 April 1990 + +Ty Coon, President of Vice + +That's all there is to it! + +<<endOptional>> + + <div class="optional-license-text"> + <p> + GNU LIBRARY GENERAL PUBLIC LICENSE + </p> + + <p> + Version 2, June 1991 + </p> + + </div> + <div class="replacable-license-text"> + <p> + Copyright (C) 1991 Free Software Foundation, Inc.<br /> + + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + </p> + + </div> + <p> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + </p> + + <p> + [This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + </p> + + <p> + Preamble + </p> + + <p> + The licenses for most software are designed to take away your + freedom to share and change it. By contrast, the GNU General Public + Licenses are intended to guarantee your freedom to share and change + free software--to make sure the software is free for all its users. + </p> + + <p> + This license, the Library General Public License, applies + to some specially designated Free Software Foundation + software, and to any other libraries whose authors + decide to use it. You can use it for your libraries, too. + </p> + + <p> + When we speak of free software, we are referring to freedom, not price. + Our General Public Licenses are designed to make sure that you have + the freedom to distribute copies of free software (and charge for + this service if you wish), that you receive source code or can get + it if you want it, that you can change the software or use pieces of + it in new free programs; and that you know you can do these things. + </p> + + <p> + To protect your rights, we need to make restrictions that forbid + anyone to deny you these rights or to ask you to surrender the + rights. These restrictions translate to certain responsibilities for + you if you distribute copies of the library, or if you modify it. + </p> + + <p> + For example, if you distribute copies of the library, whether gratis + or for a fee, you must give the recipients all the rights that we + gave you. You must make sure that they, too, receive or can get the + source code. If you link a program with the library, you must provide + complete object files to the recipients so that they can relink them + with the library, after making changes to the library and recompiling + it. And you must show them these terms so they know their rights. + </p> + + <p> + Our method of protecting your rights has two steps: (1) copyright + the library, and (2) offer you this license which gives you + legal permission to copy, distribute and/or modify the library. + </p> + + <p> + Also, for each distributor&apos;s protection, we want to make certain + that everyone understands that there is no warranty for this + free library. If the library is modified by someone else and + passed on, we want its recipients to know that what they have + is not the original version, so that any problems introduced by + others will not reflect on the original authors&apos; reputations. + </p> + + <p> + Finally, any free program is threatened constantly by software + patents. We wish to avoid the danger that companies distributing + free software will individually obtain patent licenses, thus + in effect transforming the program into proprietary software. + To prevent this, we have made it clear that any patent must + be licensed for everyone&apos;s free use or not licensed at all. + </p> + + <p> + Most GNU software, including some libraries, is covered by the + ordinary GNU General Public License, which was designed for utility + programs. This license, the GNU Library General Public License, + applies to certain designated libraries. This license is quite + different from the ordinary one; be sure to read it in full, and don&apos;t + assume that anything in it is the same as in the ordinary license. + </p> + + <p> + The reason we have a separate public license for some libraries is + that they blur the distinction we usually make between modifying + or adding to a program and simply using it. Linking a program with + a library, without changing the library, is in some sense simply + using the library, and is analogous to running a utility program + or application program. However, in a textual and legal sense, the + linked executable is a combined work, a derivative of the original + library, and the ordinary General Public License treats it as such. + </p> + + <p> + Because of this blurred distinction, using the ordinary General + Public License for libraries did not effectively promote software + sharing, because most developers did not use the libraries. We + concluded that weaker conditions might promote sharing better. + </p> + + <p> + However, unrestricted linking of non-free programs would deprive the + users of those programs of all benefit from the free status of the + libraries themselves. This Library General Public License is intended + to permit developers of non-free programs to use free libraries, while + preserving your freedom as a user of such programs to change the free + libraries that are incorporated in them. (We have not seen how to + achieve this as regards changes in header files, but we have achieved + it as regards changes in the actual functions of the Library.) The + hope is that this will lead to faster development of free libraries. + </p> + + <p> + The precise terms and conditions for copying, distribution + and modification follow. Pay close attention to the difference + between a &quot;work based on the library&quot; and a &quot;work that uses + the library&quot;. The former contains code derived from the + library, while the latter only works together with the library. + </p> + + <p> + Note that it is possible for a library to be covered by the + ordinary General Public License rather than by this special one. + </p> + + <p> + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + </p> + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">0.</var> + This License Agreement applies to any software library + which contains a notice placed by the copyright holder or + other authorized party saying it may be distributed under + the terms of this Library General Public License (also + called &quot;this License&quot;). Each licensee is addressed as &quot;you&quot;. + <p> + A &quot;library&quot; means a collection of software functions and/or data + prepared so as to be conveniently linked with application programs + (which use some of those functions and data) to form executables. + </p> + + <p> + The &quot;Library&quot;, below, refers to any such software library or work + which has been distributed under these terms. A &quot;work based on + the Library&quot; means either the Library or any derivative work under + copyright law: that is to say, a work containing the Library or a + portion of it, either verbatim or with modifications and/or translated + straightforwardly into another language. (Hereinafter, translation + is included without limitation in the term &quot;modification&quot;.) + </p> + + <p> + &quot;Source code&quot; for a work means the preferred form of the work + for making modifications to it. For a library, complete source + code means all the source code for all modules it contains, + plus any associated interface definition files, plus the scripts + used to control compilation and installation of the library. + </p> + + <p> + Activities other than copying, distribution and modification are + not covered by this License; they are outside its scope. The act of + running a program using the Library is not restricted, and output + from such a program is covered only if its contents constitute a + work based on the Library (independent of the use of the Library + in a tool for writing it). Whether that is true depends on what + the Library does and what the program that uses the Library does. + </p> + + </li> +<li> + <var class="replacable-license-text">1.</var> + You may copy and distribute verbatim copies of the Library&apos;s complete + source code as you receive it, in any medium, provided that you + conspicuously and appropriately publish on each copy an appropriate + copyright notice and disclaimer of warranty; keep intact all the + notices that refer to this License and to the absence of any warranty; + and distribute a copy of this License along with the Library. + <p> + You may charge a fee for the physical act of + transferring a copy, and you may at your option + offer warranty protection in exchange for a fee. + </p> + + </li> +<li> + <var class="replacable-license-text">2.</var> + You may modify your copy or copies of the Library or any portion + of it, thus forming a work based on the Library, and copy and + distribute such modifications or work under the terms of Section + 1 above, provided that you also meet all of these conditions: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">a)</var> + The modified work must itself be a software library. + </li> +<li> + <var class="replacable-license-text">b)</var> + You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + </li> +<li> + <var class="replacable-license-text">c)</var> + You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + </li> +<li> + <var class="replacable-license-text">d)</var> + If a facility in the modified Library refers to a function + or a table of data to be supplied by an application program + that uses the facility, other than as an argument passed + when the facility is invoked, then you must make a good faith + effort to ensure that, in the event an application does not + supply such function or table, the facility still operates, + and performs whatever part of its purpose remains meaningful. + <p> + (For example, a function in a library to compute square roots + has a purpose that is entirely well-defined independent of + the application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function + must be optional: if the application does not supply it, + the square root function must still compute square roots.) + </p> + + </li> +</ul> + <p> + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the + Library, and can be reasonably considered independent and separate + works in themselves, then this License, and its terms, do not + apply to those sections when you distribute them as separate + works. But when you distribute the same sections as part of a + whole which is a work based on the Library, the distribution + of the whole must be on the terms of this License, whose + permissions for other licensees extend to the entire whole, + and thus to each and every part regardless of who wrote it. + </p> + + <p> + Thus, it is not the intent of this section to claim rights or + contest your rights to work written entirely by you; rather, + the intent is to exercise the right to control the distribution + of derivative or collective works based on the Library. + </p> + + <p> + In addition, mere aggregation of another work not based on + the Library with the Library (or with a work based on the + Library) on a volume of a storage or distribution medium does + not bring the other work under the scope of this License. + </p> + + </li> +<li> + <var class="replacable-license-text">3.</var> + You may opt to apply the terms of the ordinary GNU General + Public License instead of this License to a given copy of the + Library. To do this, you must alter all the notices that refer + to this License, so that they refer to the ordinary GNU General + Public License, version 2, instead of to this License. (If a + newer version than version 2 of the ordinary GNU General Public + License has appeared, then you can specify that version instead + if you wish.) Do not make any other change in these notices. + <p> + Once this change is made in a given copy, it is irreversible for + that copy, so the ordinary GNU General Public License applies to + all subsequent copies and derivative works made from that copy. + </p> + + <p> + This option is useful when you wish to copy part of the + code of the Library into a program that is not a library. + </p> + + </li> +<li> + <var class="replacable-license-text">4.</var> + You may copy and distribute the Library (or a portion or derivative + of it, under Section 2) in object code or executable form under + the terms of Sections 1 and 2 above provided that you accompany + it with the complete corresponding machine-readable source code, + which must be distributed under the terms of Sections 1 and 2 + above on a medium customarily used for software interchange. + <p> + If distribution of object code is made by offering access to copy + from a designated place, then offering equivalent access to copy + the source code from the same place satisfies the requirement + to distribute the source code, even though third parties are + not compelled to copy the source along with the object code. + </p> + + </li> +<li> + <var class="replacable-license-text">5.</var> + A program that contains no derivative of any portion of the + Library, but is designed to work with the Library by being compiled + or linked with it, is called a &quot;work that uses the Library&quot;. + Such a work, in isolation, is not a derivative work of the + Library, and therefore falls outside the scope of this License. + <p> + However, linking a &quot;work that uses the Library&quot; with the Library + creates an executable that is a derivative of the Library (because + it contains portions of the Library), rather than a &quot;work that uses + the library&quot;. The executable is therefore covered by this License. + Section 6 states terms for distribution of such executables. + </p> + + <p> + When a &quot;work that uses the Library&quot; uses material from a header + file that is part of the Library, the object code for the work may + be a derivative work of the Library even though the source code is + not. Whether this is true is especially significant if the work can + be linked without the Library, or if the work is itself a library. + The threshold for this to be true is not precisely defined by law. + </p> + + <p> + If such an object file uses only numerical parameters, data + structure layouts and accessors, and small macros and small inline + functions (ten lines or less in length), then the use of the + object file is unrestricted, regardless of whether it is legally + a derivative work. (Executables containing this object code + plus portions of the Library will still fall under Section 6.) + </p> + + <p> + Otherwise, if the work is a derivative of the Library, you may + distribute the object code for the work under the terms of Section + 6. Any executables containing that work also fall under Section 6, + whether or not they are linked directly with the Library itself. + </p> + + </li> +<li> + <var class="replacable-license-text">6.</var> + As an exception to the Sections above, you may also compile or + link a &quot;work that uses the Library&quot; with the Library to produce + a work containing portions of the Library, and distribute + that work under terms of your choice, provided that the terms + permit modification of the work for the customer&apos;s own use + and reverse engineering for debugging such modifications. + <p> + You must give prominent notice with each copy of the work + that the Library is used in it and that the Library and its + use are covered by this License. You must supply a copy of + this License. If the work during execution displays copyright + notices, you must include the copyright notice for the Library + among them, as well as a reference directing the user to the + copy of this License. Also, you must do one of these things: + </p> + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">a)</var> + Accompany the work with the complete corresponding machine-readable + source code for the Library including whatever changes were used in + the work (which must be distributed under Sections 1 and 2 above); + and, if the work is an executable linked with the Library, with the + complete machine-readable &quot;work that uses the Library&quot;, as object + code and/or source code, so that the user can modify the Library + and then relink to produce a modified executable containing the + modified Library. (It is understood that the user who changes the + contents of definitions files in the Library will not necessarily be + able to recompile the application to use the modified definitions.) + </li> +<li> + <var class="replacable-license-text">b)</var> + Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no + more than the cost of performing this distribution. + </li> +<li> + <var class="replacable-license-text">c)</var> + If distribution of the work is made by offering access to + copy from a designated place, offer equivalent access to + copy the above specified materials from the same place. + </li> +<li> + <var class="replacable-license-text">d)</var> + Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + </li> +</ul> + <p> + For an executable, the required form of the &quot;work that uses + the Library&quot; must include any data and utility programs needed + for reproducing the executable from it. However, as a special + exception, the source code distributed need not include + anything that is normally distributed (in either source or + binary form) with the major components (compiler, kernel, + and so on) of the operating system on which the executable + runs, unless that component itself accompanies the executable. + </p> + + <p> + It may happen that this requirement contradicts the + license restrictions of other proprietary libraries that + do not normally accompany the operating system. Such + a contradiction means you cannot use both them and the + Library together in an executable that you distribute. + </p> + + </li> +<li> + <var class="replacable-license-text">7.</var> + You may place library facilities that are a work based on the + Library side-by-side in a single library together with other library + facilities not covered by this License, and distribute such a + combined library, provided that the separate distribution of the + work based on the Library and of the other library facilities is + otherwise permitted, and provided that you do these two things: + </li> +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">a)</var> + Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities. + This must be distributed under the terms of the Sections above. + </li> +<li> + <var class="replacable-license-text">b)</var> + Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + </li> +</ul> +<li> + <var class="replacable-license-text">8.</var> + You may not copy, modify, sublicense, link with, or distribute the + Library except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense, link with, or distribute + the Library is void, and will automatically terminate your rights + under this License. However, parties who have received copies, or + rights, from you under this License will not have their licenses + terminated so long as such parties remain in full compliance. + </li> +<li> + <var class="replacable-license-text">9.</var> + You are not required to accept this License, since you have + not signed it. However, nothing else grants you permission to + modify or distribute the Library or its derivative works. These + actions are prohibited by law if you do not accept this License. + Therefore, by modifying or distributing the Library (or any + work based on the Library), you indicate your acceptance of this + License to do so, and all its terms and conditions for copying, + distributing or modifying the Library or works based on it. + </li> +<li> + <var class="replacable-license-text">10.</var> + Each time you redistribute the Library (or any work based on + the Library), the recipient automatically receives a license + from the original licensor to copy, distribute, link with or + modify the Library subject to these terms and conditions. You + may not impose any further restrictions on the recipients&apos; + exercise of the rights granted herein. You are not responsible + for enforcing compliance by third parties to this License. + </li> +<li> + <var class="replacable-license-text">11.</var> + If, as a consequence of a court judgment or allegation of patent + infringement or for any other reason (not limited to patent issues), + conditions are imposed on you (whether by court order, agreement + or otherwise) that contradict the conditions of this License, + they do not excuse you from the conditions of this License. If you + cannot distribute so as to satisfy simultaneously your obligations + under this License and any other pertinent obligations, then as a + consequence you may not distribute the Library at all. For example, + if a patent license would not permit royalty-free redistribution of + the Library by all those who receive copies directly or indirectly + through you, then the only way you could satisfy both it and this + License would be to refrain entirely from distribution of the Library. + <p> + If any portion of this section is held invalid or + unenforceable under any particular circumstance, the + balance of the section is intended to apply, and the section + as a whole is intended to apply in other circumstances. + </p> + + <p> + It is not the purpose of this section to induce you to infringe + any patents or other property right claims or to contest + validity of any such claims; this section has the sole purpose + of protecting the integrity of the free software distribution + system which is implemented by public license practices. Many + people have made generous contributions to the wide range of + software distributed through that system in reliance on consistent + application of that system; it is up to the author/donor to + decide if he or she is willing to distribute software through + any other system and a licensee cannot impose that choice. + </p> + + <p> + This section is intended to make thoroughly clear what is + believed to be a consequence of the rest of this License. + </p> + + </li> +<li> + <var class="replacable-license-text">12.</var> + If the distribution and/or use of the Library is restricted in + certain countries either by patents or by copyrighted interfaces, + the original copyright holder who places the Library under this + License may add an explicit geographical distribution limitation + excluding those countries, so that distribution is permitted only + in or among countries not thus excluded. In such case, this License + incorporates the limitation as if written in the body of this License. + </li> +<li> + <var class="replacable-license-text">13.</var> + The Free Software Foundation may publish revised and/or new versions + of the Library General Public License from time to time. Such + new versions will be similar in spirit to the present version, + but may differ in detail to address new problems or concerns. + <p> + Each version is given a distinguishing version number. If + the Library specifies a version number of this License which + applies to it and &quot;any later version&quot;, you have the option of + following the terms and conditions either of that version or of + any later version published by the Free Software Foundation. If + the Library does not specify a license version number, you may + choose any version ever published by the Free Software Foundation. + </p> + + </li> +<li> + <var class="replacable-license-text">14.</var> + If you wish to incorporate parts of the Library into other free programs + whose distribution conditions are incompatible with these, write to + the author to ask for permission. For software which is copyrighted by + the Free Software Foundation, write to the Free Software Foundation; we + sometimes make exceptions for this. Our decision will be guided by the + two goals of preserving the free status of all derivatives of our free + software and of promoting the sharing and reuse of software generally. + <p> + NO WARRANTY + </p> + + </li> +<li> + <var class="replacable-license-text">15.</var> + BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY + FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT + WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER + PARTIES PROVIDE THE LIBRARY &quot;AS IS&quot; WITHOUT WARRANTY OF ANY KIND, + EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF + THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU + ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + </li> +<li> + <var class="replacable-license-text">16.</var> + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR + REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR + DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL + DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY + (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED + INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF + THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER + OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + </li> +</ul> + <div class="optional-license-text"> + <p> + END OF TERMS AND CONDITIONS + </p> + + <p> + How to Apply These Terms to Your New Libraries + </p> + + <p> + If you develop a new library, and you want it to be of the greatest + possible use to the public, we recommend making it free software + that everyone can redistribute and change. You can do so by + permitting redistribution under these terms (or, alternatively, + under the terms of the ordinary General Public License). + </p> + + <p> + To apply these terms, attach the following notices to the + library. It is safest to attach them to the start of each + source file to most effectively convey the exclusion of + warranty; and each file should have at least the &quot;copyright&quot; + line and a pointer to where the full notice is found. + </p> + + <p> + one line to give the library&apos;s name + and an idea of what it does.<br /> + + Copyright (C) year name of author + </p> + + <p> + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + </p> + + <p> + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + the GNU Library General Public License for more details. + </p> + + <p> + You should have received a copy of the GNU Library + General Public License along with this library; if + not, write to the Free Software Foundation, Inc., 51 + Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + </p> + + <p> + Also add information on how to contact you by electronic and paper mail. + </p> + + <p> + You should also get your employer (if you work as a programmer) + or your school, if any, to sign a &quot;copyright disclaimer&quot; for + the library, if necessary. Here is a sample; alter the names: + </p> + + <p> + Yoyodyne, Inc., hereby disclaims all copyright interest in<br /> + + the library `Frob&apos; (a library for tweaking knobs) written<br /> + + by James Random Hacker. + </p> + + <p> + signature of Ty Coon, 1 April 1990<br /> + + Ty Coon, President of Vice + </p> + + <p> + That&apos;s all there is to it! + </p> + + </div> + + true + Copyright (C) year name of author + +This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; version 2. + +This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + + + + + 0 + 2021-05-20 - 16:59:22 + https://www.gnu.org/licenses/old-licenses/lgpl-2.0-standalone.html + true + false + true + true + + + This license was released: June 1991. This license has been superseded by LGPL-2.1. This license identifier refers to the choice to use the code under LGPL-2.0-only, as distinguished from use of code under LGPL-2.0-or-later (i.e., LGPL-2.0 or some later version). The license notice (as seen in the Standard License Header field below) states which of these applies to the code in the file. The example in the exhibit to the license shows the license notice for the "or later" approach. + GNU Library General Public License v2 only + Copyright (C) <<var;name="copyright";original="year name of author";match=".+">> + +This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; version 2. + +This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + + + + + + + + + + 85ed0817af83a24ad8da68c2b5094de69833983c + + + The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change. + + true + 2.11.1 + + + + 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd + + + + + /* + * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + http://ftp.gnu.org/gnu/glibc + glibc + Person: Jane Doe (jane.doe@example.com) + + + + + + This license is used by Jena + Hewlett Packard Inc. + + (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + + + + + + + Apache Software Foundation + + + + 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 + + + + This file belongs to Jena + ./lib-source/jena-2.6.3-sources.jar + + + + + + + + + This is the external ref for Acme + + acmecorp/acmenator/4.1.3-alpha + + + + + + + + + The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually. + Organization: ExampleCodeInspect (contact@example.com) + + + + This package includes the GRDDL parser developed by Hewlett Packard under the following license: +� Copyright 2007 Hewlett-Packard Development Company, LP + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + + + + + 624c1abb3664f4b35547e7c73864ad24 + + + + + Apache Commons Lang +Copyright 2001-2011 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + +This product includes software from the Spring Framework, +under the Apache License 2.0 (see: StringUtils.containsWhitespace()) + + + + + + + + + Apache Software Foundation + + + + c2b4e1c67a2d28fced849ee1bb76e7391b93f125 + + + ./lib-source/commons-lang3-3.1-sources.jar + Copyright 2001-2011 The Apache Software Foundation + This file is used by Jena + + + + + + + + cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:* + + + + + d6a770ba38583ed4bb4525bd96e50461655d2758 + ./package.spdx + + + + + Person: Package Commenter + Package level annotation + + 2011-01-29T18:30:22Z + + + + + + + Saxon + The Saxon package is a collection of tools for processing XML documents. + http://saxon.sourceforge.net/ + 8.8 + Other versions available for a commercial license + + + + 85ed0817af83a24ad8da68c2b5094de69833983c + + + https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download + saxonB-8.8.zip + + + https://opensource.org/licenses/MPL-1.0 + + <p><var class="optional-license-text">&quot;</var>The contents of this file are subject to the Mozilla Public License Version 1.0 (the + &quot;License&quot;); you may not use this file except in compliance with the License. You may obtain + a copy of the License at http://www.mozilla.org/MPL/</p> + + <p>Software distributed under the License is distributed on an &quot;AS IS&quot; basis, WITHOUT WARRANTY OF + ANY KIND, either express or implied. See the License for the specific language governing rights and + limitations under the License.</p> + + <p>The Original Code is + <var class="replacable-license-text">_____</var>. The Initial Developer of the Original Code is + <var class="replacable-license-text">_____</var>. Portions created by + <var class="replacable-license-text">_____</var> are Copyright (C) + <var class="replacable-license-text">_____</var>. All Rights Reserved. Contributor(s): + <var class="replacable-license-text">_____</var>.<var class="optional-license-text">&quot;</var> + </p> + + + MOZILLA PUBLIC LICENSE +Version 1.0 + +1. Definitions. + + 1.1. ``Contributor'' means each entity that creates or contributes to the creation of Modifications. + + 1.2. ``Contributor Version'' means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. + + 1.3. ``Covered Code'' means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. + + 1.4. ``Electronic Distribution Mechanism'' means a mechanism generally accepted in the software development community for the electronic transfer of data. + + 1.5. ``Executable'' means Covered Code in any form other than Source Code. + + 1.6. ``Initial Developer'' means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. + + 1.7. ``Larger Work'' means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. + + 1.8. ``License'' means this document. + + 1.9. ``Modifications'' means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: + + A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or previous Modifications. + + 1.10. ``Original Code'' means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. + + 1.11. ``Source Code'' means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or a list of source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. + + 1.12. ``You'' means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, ``You'' includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, ``control'' means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. +The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: + + (a) to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, or as part of a Larger Work; and + + (b) under patents now or hereafter owned or controlled by Initial Developer, to make, have made, use and sell (``Utilize'') the Original Code (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Original Code (or portions thereof) and not to any greater extent that may be necessary to Utilize further Modifications or combinations. + + 2.2. Contributor Grant. +Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: + + (a) to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code or as part of a Larger Work; and + + (b) under patents now or hereafter owned or controlled by Contributor, to Utilize the Contributor Version (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Contributor Version (or portions thereof), and not to any greater extent that may be necessary to Utilize further Modifications or combinations. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which you contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + + (a) Third Party Claims. + If You have knowledge that a party claims an intellectual property right in particular functionality or code (or its utilization under this License), you must include a text file with the source code distribution titled ``LEGAL'' which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If you obtain such knowledge after You make Your Modification available as described in Section 3.2, You shall promptly modify the LEGAL file in all copies You make available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Your Modification is an application programming interface and You own or control patents which are reasonably necessary to implement that API, you must also include this information in the LEGAL file. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source Code, and this License in any documentation for the Source Code, where You describe recipients' rights relating to Covered Code. If You created one or more Modification(s), You may add your name as a Contributor to the notice described in Exhibit A. If it is not possible to put such notice in a particular Source Code file due to its structure, then you must include such notice in a location (such as a relevant directory file) where a user would be likely to look for such a notice. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. +If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. + +5. Application of this License. +This License applies to code to which the Initial Developer has attached the notice in Exhibit A, and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation (``Netscape'') may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. + + 6.3. Derivative Works. + If you create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), you must (a) rename Your license so that the phrases ``Mozilla'', ``MOZILLAPL'', ``MOZPL'', ``Netscape'', ``NPL'' or any confusingly similar phrase do not appear anywhere in your license and (b) otherwise make it clear that your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) + +7. DISCLAIMER OF WARRANTY. +COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN ``AS IS'' BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. +This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. + +9. LIMITATION OF LIABILITY. +UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. +The Covered Code is a ``commercial item,'' as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of ``commercial computer software'' and ``commercial computer software documentation,'' as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. + +11. MISCELLANEOUS. +This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in, the United States of America: (a) unless otherwise agreed in writing, all disputes relating to this License (excepting any dispute relating to intellectual property rights) shall be subject to final and binding arbitration, with the losing party paying all costs of arbitration; (b) any arbitration relating to this Agreement shall be held in Santa Clara County, California, under the auspices of JAMS/EndDispute; and (c) any litigation relating to this Agreement shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. + +12. RESPONSIBILITY FOR CLAIMS. +Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for damages arising, directly or indirectly, out of Your utilization of rights under this License, based on the number of copies of Covered Code you made available, the revenues you received from utilizing such rights, and other relevant factors. You agree to work with affected parties to distribute responsibility on an equitable basis. + +EXHIBIT A. + +``The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. + +The Original Code is ______________________________________. + +The Initial Developer of the Original Code is ________________________. Portions created by ______________________ are Copyright (C) ______ _______________________. All Rights Reserved. + +Contributor(s): ______________________________________.'' + This license has been superseded by v1.1 + http://www.mozilla.org/MPL/MPL-1.0.html + + <div class="optional-license-text"> + <p>MOZILLA PUBLIC LICENSE + <br /> + +Version 1.0 + </p> + + </div> + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">1.</var> + Definitions. + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">1.1.</var> + &quot;Contributor&quot; means each entity that creates or contributes to the creation of + Modifications. + </li> +<li> + <var class="replacable-license-text">1.2.</var> + &quot;Contributor Version&quot; means the combination of the Original Code, prior + Modifications used by a Contributor, and the Modifications made by that particular + Contributor. + </li> +<li> + <var class="replacable-license-text">1.3.</var> + &quot;Covered Code&quot; means the Original Code or Modifications or the combination of the + Original Code and Modifications, in each case including portions thereof. + </li> +<li> + <var class="replacable-license-text">1.4.</var> + &quot;Electronic Distribution Mechanism&quot; means a mechanism generally accepted in the + software development community for the electronic transfer of data. + </li> +<li> + <var class="replacable-license-text">1.5.</var> + &quot;Executable&quot; means Covered Code in any form other than Source Code. + </li> +<li> + <var class="replacable-license-text">1.6.</var> + &quot;Initial Developer&quot; means the individual or entity identified as the Initial + Developer in the Source Code notice required by Exhibit A. + </li> +<li> + <var class="replacable-license-text">1.7.</var> + &quot;Larger Work&quot; means a work which combines Covered Code or portions thereof with + code not governed by the terms of this License. + </li> +<li> + <var class="replacable-license-text">1.8.</var> + &quot;License&quot; means this document. + </li> +<li> + <var class="replacable-license-text">1.9.</var> + &quot;Modifications&quot; means any addition to or deletion from the substance or structure + of either the Original Code or any previous Modifications. When Covered Code is released + as a series of files, a Modification is: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">A.</var> + Any addition to or deletion from the contents of a file containing Original Code or + previous Modifications. + </li> +<li> + <var class="replacable-license-text">B.</var> + Any new file that contains any part of the Original Code or previous Modifications. + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">1.10.</var> + &quot;Original Code&quot; means Source Code of computer software code which is described in + the Source Code notice required by Exhibit A as Original Code, and which, at the time of + its release under this License is not already Covered Code governed by this License. + </li> +<li> + <var class="replacable-license-text">1.11.</var> + &quot;Source Code&quot; means the preferred form of the Covered Code for making + modifications to it, including all modules it contains, plus any associated interface + definition files, scripts used to control compilation and installation of an Executable, + or a list of source code differential comparisons against either the Original Code or + another well known, available Covered Code of the Contributor&apos;s choice. The Source + Code can be in a compressed or archival form, provided the appropriate decompression or + de-archiving software is widely available for no charge. + </li> +<li> + <var class="replacable-license-text">1.12.</var> + &quot;You&quot; means an individual or a legal entity exercising rights under, and + complying with all of the terms of, this License or a future version of this License + issued under Section 6.1. For legal entities, &quot;You&quot; includes any entity which + controls, is controlled by, or is under common control with You. For purposes of this + definition, &quot;control&quot; means (a) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or otherwise, or (b) ownership + of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such + entity. + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">2.</var> + Source Code License. + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">2.1.</var> + The Initial Developer Grant. + <br /> + + The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive + license, subject to third party intellectual property claims: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">(a)</var> + to use, reproduce, modify, display, perform, sublicense and distribute the Original Code + (or portions thereof) with or without Modifications, or as part of a Larger Work; + and + </li> +<li> + <var class="replacable-license-text">(b)</var> + under patents now or hereafter owned or controlled by Initial Developer, to make, have + made, use and sell (&quot;Utilize&quot;) the Original Code (or portions thereof), + but solely to the extent that any such patent is reasonably necessary to enable You to + Utilize the Original Code (or portions thereof) and not to any greater extent that may + be necessary to Utilize further Modifications or combinations. + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">2.2.</var> + Contributor Grant. + <br /> + + Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, + subject to third party intellectual property claims: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">(a)</var> + to use, reproduce, modify, display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an unmodified basis, with + other Modifications, as Covered Code or as part of a Larger Work; and + </li> +<li> + <var class="replacable-license-text">(b)</var> + under patents now or hereafter owned or controlled by Contributor, to Utilize the + Contributor Version (or portions thereof), but solely to the extent that any such + patent is reasonably necessary to enable You to Utilize the Contributor Version (or + portions thereof), and not to any greater extent that may be necessary to Utilize + further Modifications or combinations. + </li> +</ul> + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">3.</var> + Distribution Obligations. + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">3.1.</var> + Application of License. + <br /> + + The Modifications which You create or to which You contribute are governed by the terms + of this License, including without limitation Section 2.2. The Source Code version + of Covered Code may be distributed only under the terms of this License or a + future version of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You distribute. You may + not offer or impose any terms on any Source Code version that alters or restricts + the applicable version of this License or the recipients&apos; rights hereunder. + However, You may include an additional document offering the additional rights + described in Section 3.5. + + </li> +<li> + <var class="replacable-license-text">3.2.</var> + Availability of Source Code. + <br /> + + Any Modification which You create or to which You contribute must be made available in + Source Code form under the terms of this License either on the same media as an + Executable version or via an accepted Electronic Distribution Mechanism to anyone + to whom you made an Executable version available; and if made available via + Electronic Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six (6) months + after a subsequent version of that particular Modification has been made available + to such recipients. You are responsible for ensuring that the Source Code version + remains available even if the Electronic Distribution Mechanism is maintained by a + third party. + + </li> +<li> + <var class="replacable-license-text">3.3.</var> + Description of Modifications. + <br /> + + You must cause all Covered Code to which you contribute to contain a file documenting + the changes You made to create that Covered Code and the date of any change. You + must include a prominent statement that the Modification is derived, directly or + indirectly, from Original Code provided by the Initial Developer and including the + name of the Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the origin or + ownership of the Covered Code. + + </li> +<li> + <var class="replacable-license-text">3.4.</var> + Intellectual Property Matters + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">(a)</var> + Third Party Claims. + <br /> + + If You have knowledge that a party claims an intellectual property right in + particular functionality or code (or its utilization under this License), you + must include a text file with the source code distribution titled + &quot;LEGAL&quot; which describes the claim and the party making the claim + in sufficient detail that a recipient will know whom to contact. If you obtain + such knowledge after You make Your Modification available as described in + Section 3.2, You shall promptly modify the LEGAL file in all copies You make + available thereafter and shall take other steps (such as notifying appropriate + mailing lists or newsgroups) reasonably calculated to inform those who + received the Covered Code that new knowledge has been obtained. + + </li> +<li> + <var class="replacable-license-text">(b)</var> + Contributor APIs. + <br /> + + If Your Modification is an application programming interface and You own or control + patents which are reasonably necessary to implement that API, you must also + include this information in the LEGAL file. + + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">3.5.</var> + Required Notices. + <br /> + + You must duplicate the notice in Exhibit A in each file of the Source Code, and this + License in any documentation for the Source Code, where You describe + recipients&apos; rights relating to Covered Code. If You created one or more + Modification(s), You may add your name as a Contributor to the notice described in + Exhibit A. If it is not possible to put such notice in a particular Source Code + file due to its structure, then you must include such notice in a location (such + as a relevant directory file) where a user would be likely to look for such a + notice. You may choose to offer, and to charge a fee for, warranty, support, + indemnity or liability obligations to one or more recipients of Covered Code. + However, You may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than any such + warranty, support, indemnity or liability obligation is offered by You alone, and + You hereby agree to indemnify the Initial Developer and every Contributor for any + liability incurred by the Initial Developer or such Contributor as a result of + warranty, support, indemnity or liability terms You offer. + + </li> +<li> + <var class="replacable-license-text">3.6.</var> + Distribution of Executable Versions. + <br /> + + You may distribute Covered Code in Executable form only if the requirements of Section + 3.1-3.5 have been met for that Covered Code, and if You include a notice stating + that the Source Code version of the Covered Code is available under the terms of + this License, including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included in any + notice in an Executable version, related documentation or collateral in which You + describe recipients&apos; rights relating to the Covered Code. You may distribute + the Executable version of Covered Code under a license of Your choice, which may + contain terms different from this License, provided that You are in compliance + with the terms of this License and that the license for the Executable version + does not attempt to limit or alter the recipient&apos;s rights in the Source Code + version from the rights set forth in this License. If You distribute the + Executable version under a different license You must make it absolutely clear + that any terms which differ from this License are offered by You alone, not by the + Initial Developer or any Contributor. You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the Initial + Developer or such Contributor as a result of any such terms You offer. + + </li> +<li> + <var class="replacable-license-text">3.7.</var> + Larger Works. + <br /> + + You may create a Larger Work by combining Covered Code with other code not governed by + the terms of this License and distribute the Larger Work as a single product. In + such a case, You must make sure the requirements of this License are fulfilled for + the Covered Code. + + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">4.</var> + Inability to Comply Due to Statute or Regulation. + <br /> + + If it is impossible for You to comply with any of the terms of this License with respect to + some or all of the Covered Code due to statute or regulation then You must: (a) comply + with the terms of this License to the maximum extent possible; and (b) describe the + limitations and the code they affect. Such description must be included in the LEGAL + file described in Section 3.4 and must be included with all distributions of the + Source Code. Except to the extent prohibited by statute or regulation, such + description must be sufficiently detailed for a recipient of ordinary skill to be able + to understand it. + + </li> +<li> + <var class="replacable-license-text">5.</var> + Application of this License. + <br /> + + This License applies to code to which the Initial Developer has attached the notice in + Exhibit A, and to related Covered Code. + + </li> +<li> + <var class="replacable-license-text">6.</var> + Versions of the License. + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">6.1.</var> + New Versions. + <br /> + + Netscape Communications Corporation (&quot;Netscape&quot;) may publish revised and/or + new versions of the License from time to time. Each version will be given a + distinguishing version number. + + </li> +<li> + <var class="replacable-license-text">6.2.</var> + Effect of New Versions. + <br /> + + Once Covered Code has been published under a particular version of the License, You may + always continue to use it under the terms of that version. You may also choose to + use such Covered Code under the terms of any subsequent version of the License + published by Netscape. No one other than Netscape has the right to modify the + terms applicable to Covered Code created under this License. + + </li> +<li> + <var class="replacable-license-text">6.3.</var> + Derivative Works. + <br /> + + If you create or use a modified version of this License (which you may only do in order + to apply it to code which is not already Covered Code governed by this License), + you must (a) rename Your license so that the phrases &quot;Mozilla&quot;, + &quot;MOZILLAPL&quot;, &quot;MOZPL&quot;, &quot;Netscape&quot;, + &quot;NPL&quot; or any confusingly similar phrase do not appear anywhere in your + license and (b) otherwise make it clear that your version of the license contains + terms which differ from the Mozilla Public License and Netscape Public License. + (Filling in the name of the Initial Developer, Original Code or Contributor in the + notice described in Exhibit A shall not of themselves be deemed to be + modifications of this License.) + + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">7.</var> + DISCLAIMER OF WARRANTY. + <br /> + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN &quot;AS IS&quot; BASIS, WITHOUT + WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, + WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A + PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND + PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE + IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY + CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS + AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + + </li> +<li> + <var class="replacable-license-text">8.</var> + TERMINATION. + <br /> + + This License and the rights granted hereunder will terminate automatically if You fail to + comply with terms herein and fail to cure such breach within 30 days of becoming aware + of the breach. All sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their nature, must + remain in effect beyond the termination of this License shall survive. + + </li> +<li> + <var class="replacable-license-text">9.</var> + LIMITATION OF LIABILITY. + <br /> + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), + CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY + DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU + OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF + ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK + STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR + LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH + DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR + PERSONAL INJURY RESULTING FROM SUCH PARTY&apos;S NEGLIGENCE TO THE EXTENT APPLICABLE + LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR + LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION + MAY NOT APPLY TO YOU. + + </li> +<li> + <var class="replacable-license-text">10.</var> + U.S. GOVERNMENT END USERS. + <br /> + + The Covered Code is a &quot;commercial item,&quot; as that term is defined in 48 C.F.R. + 2.101 (Oct. 1995), consisting of &quot;commercial computer software&quot; and + &quot;commercial computer software documentation,&quot; as such terms are used in 48 + C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 + through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code + with only those rights set forth herein. + + </li> +<li> + <var class="replacable-license-text">11.</var> + MISCELLANEOUS. + <br /> + + This License represents the complete agreement concerning subject matter hereof. If any + provision of this License is held to be unenforceable, such provision shall be + reformed only to the extent necessary to make it enforceable. This License shall be + governed by California law provisions (except to the extent applicable law, if any, + provides otherwise), excluding its conflict-of-law provisions. With respect to + disputes in which at least one party is a citizen of, or an entity chartered or + registered to do business in, the United States of America: (a) unless otherwise + agreed in writing, all disputes relating to this License (excepting any dispute + relating to intellectual property rights) shall be subject to final and binding + arbitration, with the losing party paying all costs of arbitration; (b) any + arbitration relating to this Agreement shall be held in Santa Clara County, + California, under the auspices of JAMS/EndDispute; and (c) any litigation relating to + this Agreement shall be subject to the jurisdiction of the Federal Courts of the + Northern District of California, with venue lying in Santa Clara County, California, + with the losing party responsible for costs, including without limitation, court costs + and reasonable attorneys fees and expenses. The application of the United Nations + Convention on Contracts for the International Sale of Goods is expressly excluded. Any + law or regulation which provides that the language of a contract shall be construed + against the drafter shall not apply to this License. + + </li> +<li> + <var class="replacable-license-text">12.</var> + RESPONSIBILITY FOR CLAIMS. + <br /> + + Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for + damages arising, directly or indirectly, out of Your utilization of rights under this License, based + on the number of copies of Covered Code you made available, the revenues you received from utilizing + such rights, and other relevant factors. You agree to work with affected parties to distribute + responsibility on an equitable basis. + </li> +</ul> + <div class="optional-license-text"> + <p>EXHIBIT A.</p> + + <p><var class="optional-license-text">&quot;</var>The contents of this file are subject to the Mozilla Public License Version 1.0 (the + &quot;License&quot;); you may not use this file except in compliance with the License. You may obtain + a copy of the License at http://www.mozilla.org/MPL/</p> + + <p>Software distributed under the License is distributed on an &quot;AS IS&quot; basis, WITHOUT WARRANTY OF + ANY KIND, either express or implied. See the License for the specific language governing rights and + limitations under the License.</p> + + <p>The Original Code is + <var class="replacable-license-text">_____</var>. The Initial Developer of the Original Code is + <var class="replacable-license-text">_____</var>. Portions created by + <var class="replacable-license-text">_____</var> are Copyright (C) + <var class="replacable-license-text">_____</var>. All Rights Reserved. Contributor(s): + <var class="replacable-license-text">_____</var>.<var class="optional-license-text">&quot;</var> + </p> + + </div> + + + + 0 + 2021-05-20 - 16:53:35 + http://www.mozilla.org/MPL/MPL-1.0.html + true + false + true + true + + + Mozilla Public License 1.0 + "The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. + +The Original Code is _____ . The Initial Developer of the Original Code is _____ . Portions created by _____ are Copyright (C) _____ . All Rights Reserved. Contributor(s): _____ ." + + + <<beginOptional>>"<<endOptional>>The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. + +The Original Code is <<var;name="code";original="_____";match=".+">> . The Initial Developer of the Original Code is <<var;name="InitialDeveloper";original="_____";match=".+">> . Portions created by <<var;name="createdby";original="_____";match=".+">> are Copyright (C) <<var;name="copyright";original="_____";match=".+">> . All Rights Reserved. Contributor(s): <<var;name="contributor";original="_____";match=".+">> .<<beginOptional>>"<<endOptional>> + + + true + <<beginOptional>> MOZILLA PUBLIC LICENSE + +Version 1.0 + +<<endOptional>> + + <<var;name="bullet";original="1.";match=".{0,20}">> Definitions. + + <<var;name="bullet";original="1.1.";match=".{0,20}">> "Contributor" means each entity that creates or contributes to the creation of Modifications. + + <<var;name="bullet";original="1.2.";match=".{0,20}">> "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. + + <<var;name="bullet";original="1.3.";match=".{0,20}">> "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. + + <<var;name="bullet";original="1.4.";match=".{0,20}">> "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. + + <<var;name="bullet";original="1.5.";match=".{0,20}">> "Executable" means Covered Code in any form other than Source Code. + + <<var;name="bullet";original="1.6.";match=".{0,20}">> "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. + + <<var;name="bullet";original="1.7.";match=".{0,20}">> "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. + + <<var;name="bullet";original="1.8.";match=".{0,20}">> "License" means this document. + + <<var;name="bullet";original="1.9.";match=".{0,20}">> "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: + + <<var;name="bullet";original="A.";match=".{0,20}">> Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. + + <<var;name="bullet";original="B.";match=".{0,20}">> Any new file that contains any part of the Original Code or previous Modifications. + + <<var;name="bullet";original="1.10.";match=".{0,20}">> "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. + + <<var;name="bullet";original="1.11.";match=".{0,20}">> "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or a list of source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. + + <<var;name="bullet";original="1.12.";match=".{0,20}">> "You" means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity. + + <<var;name="bullet";original="2.";match=".{0,20}">> Source Code License. + + <<var;name="bullet";original="2.1.";match=".{0,20}">> The Initial Developer Grant. + + The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: + + <<var;name="bullet";original="(a)";match=".{0,20}">> to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, or as part of a Larger Work; and + + <<var;name="bullet";original="(b)";match=".{0,20}">> under patents now or hereafter owned or controlled by Initial Developer, to make, have made, use and sell ("Utilize") the Original Code (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Original Code (or portions thereof) and not to any greater extent that may be necessary to Utilize further Modifications or combinations. + + <<var;name="bullet";original="2.2.";match=".{0,20}">> Contributor Grant. + + Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: + + <<var;name="bullet";original="(a)";match=".{0,20}">> to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code or as part of a Larger Work; and + + <<var;name="bullet";original="(b)";match=".{0,20}">> under patents now or hereafter owned or controlled by Contributor, to Utilize the Contributor Version (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Contributor Version (or portions thereof), and not to any greater extent that may be necessary to Utilize further Modifications or combinations. + + <<var;name="bullet";original="3.";match=".{0,20}">> Distribution Obligations. + + <<var;name="bullet";original="3.1.";match=".{0,20}">> Application of License. + + The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. + + <<var;name="bullet";original="3.2.";match=".{0,20}">> Availability of Source Code. + + Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. + + <<var;name="bullet";original="3.3.";match=".{0,20}">> Description of Modifications. + + You must cause all Covered Code to which you contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. + + <<var;name="bullet";original="3.4.";match=".{0,20}">> Intellectual Property Matters + + <<var;name="bullet";original="(a)";match=".{0,20}">> Third Party Claims. + + If You have knowledge that a party claims an intellectual property right in particular functionality or code (or its utilization under this License), you must include a text file with the source code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If you obtain such knowledge after You make Your Modification available as described in Section 3.2, You shall promptly modify the LEGAL file in all copies You make available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. + + <<var;name="bullet";original="(b)";match=".{0,20}">> Contributor APIs. + + If Your Modification is an application programming interface and You own or control patents which are reasonably necessary to implement that API, you must also include this information in the LEGAL file. + + <<var;name="bullet";original="3.5.";match=".{0,20}">> Required Notices. + + You must duplicate the notice in Exhibit A in each file of the Source Code, and this License in any documentation for the Source Code, where You describe recipients' rights relating to Covered Code. If You created one or more Modification(s), You may add your name as a Contributor to the notice described in Exhibit A. If it is not possible to put such notice in a particular Source Code file due to its structure, then you must include such notice in a location (such as a relevant directory file) where a user would be likely to look for such a notice. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. + + <<var;name="bullet";original="3.6.";match=".{0,20}">> Distribution of Executable Versions. + + You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. + + <<var;name="bullet";original="3.7.";match=".{0,20}">> Larger Works. + + You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. + + <<var;name="bullet";original="4.";match=".{0,20}">> Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. + + <<var;name="bullet";original="5.";match=".{0,20}">> Application of this License. + + This License applies to code to which the Initial Developer has attached the notice in Exhibit A, and to related Covered Code. + + <<var;name="bullet";original="6.";match=".{0,20}">> Versions of the License. + + <<var;name="bullet";original="6.1.";match=".{0,20}">> New Versions. + + Netscape Communications Corporation ("Netscape") may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. + + <<var;name="bullet";original="6.2.";match=".{0,20}">> Effect of New Versions. + + Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. + + <<var;name="bullet";original="6.3.";match=".{0,20}">> Derivative Works. + + If you create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), you must (a) rename Your license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "NPL" or any confusingly similar phrase do not appear anywhere in your license and (b) otherwise make it clear that your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) + + <<var;name="bullet";original="7.";match=".{0,20}">> DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + + <<var;name="bullet";original="8.";match=".{0,20}">> TERMINATION. + + This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. + + <<var;name="bullet";original="9.";match=".{0,20}">> LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + + <<var;name="bullet";original="10.";match=".{0,20}">> U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. + + <<var;name="bullet";original="11.";match=".{0,20}">> MISCELLANEOUS. + + This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in, the United States of America: (a) unless otherwise agreed in writing, all disputes relating to this License (excepting any dispute relating to intellectual property rights) shall be subject to final and binding arbitration, with the losing party paying all costs of arbitration; (b) any arbitration relating to this Agreement shall be held in Santa Clara County, California, under the auspices of JAMS/EndDispute; and (c) any litigation relating to this Agreement shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. + + <<var;name="bullet";original="12.";match=".{0,20}">> RESPONSIBILITY FOR CLAIMS. + + Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for damages arising, directly or indirectly, out of Your utilization of rights under this License, based on the number of copies of Covered Code you made available, the revenues you received from utilizing such rights, and other relevant factors. You agree to work with affected parties to distribute responsibility on an equitable basis.<<beginOptional>> EXHIBIT A. + +<<beginOptional>>"<<endOptional>>The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. + +The Original Code is <<var;name="code";original="_____";match=".+">> . The Initial Developer of the Original Code is <<var;name="InitialDeveloper";original="_____";match=".+">> . Portions created by <<var;name="createdby";original="_____";match=".+">> are Copyright (C) <<var;name="copyright";original="_____";match=".+">> . All Rights Reserved. Contributor(s): <<var;name="contributor";original="_____";match=".+">> .<<beginOptional>>"<<endOptional>> + +<<endOptional>> + + + 1 + 2021-05-20 - 16:53:36 + https://opensource.org/licenses/MPL-1.0 + true + false + true + true + + + false + MPL-1.0 + + + false + Copyright Saxonica Ltd + + + + + + + uses glibc-2_11-branch from git://sourceware.org/git/glibc.git. + glibc-2.11.1.tar.gz + GNU C library. + Copyright 2008-2010 John Smith + The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems. + + + + + + + + + + ./package/foo.c + The concluded license was taken from the package level that the file was included in. + + + + + 624c1abb3664f4b35547e7c73864ad24 + + + + + + d6a770ba38583ed4bb4525bd96e50461655d2758 + + + + Copyright 2008-2010 John Smith + The Regents of the University of California + Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the �Software�), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED �AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + + + + + + + pkg:maven/org.apache.jena/apache-jena@3.12.0 + + + + + Jena + 3.12.0 + https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz + http://www.openjena.org/ + false + NOASSERTION + + + + + + + + Person: File Commenter + File level annotation + + 2011-01-29T18:30:22Z + + + Modified by Paul Mundt lethal@linux-sh.org + + + + + + + + IBM Corporation + The concluded license was taken from the package level that the file was included in. +This information was found in the COPYING.txt file in the xyz directory. + + + + + + + + This package has been shipped in source and binary form. +The binaries were created with gcc 4.5.1 and expect to link to +compatible system run time libraries. + 2010-01-29T18:30:22Z + Person: Jane Doe () + Organization: ExampleCodeInspect () + Tool: LicenseFind-1.0 + 3.9 + + + SPDX-2.2 + + + false + true + false + + + 0 + 2021-05-20 - 16:55:09 + https://creativecommons.org/publicdomain/zero/1.0/legalcode + false + false + true + true + + + + <div class="optional-license-text"> + <div class="optional-license-text"> + <p>Creative Commons<var class="optional-license-text"> Legal Code</var></p> + + </div> + <p>CC0 1.0 Universal</p> + + </div> + <div class="optional-license-text"> + <p>CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS + DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION + ON AN &quot;AS-IS&quot; BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT + OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE + USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.</p> + + </div> + + <p>Statement of Purpose</p> + + <p>The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related + Rights (defined below) upon the creator and subsequent owner(s) (each and all, an &quot;owner&quot;) + of an original work of authorship and/or a database (each, a &quot;Work&quot;).</p> + + <p>Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a + commons of creative, cultural and scientific works (&quot;Commons&quot;) that the public can reliably + and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse + and redistribute as freely as possible in any form whatsoever and for any purposes, including without + limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a + free culture and the further production of creative, cultural and scientific works, or to gain + reputation or greater distribution for their Work in part through the use and efforts of others.</p> + + <p>For these and/or other purposes and motivations, and without any expectation of additional consideration + or compensation, the person associating CC0 with a Work (the &quot;Affirmer&quot;), to the extent that + he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to + the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and + Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.</p> + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">1.</var> + Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and + related or neighboring rights (&quot;Copyright and Related Rights&quot;). Copyright and + Related Rights include, but are not limited to, the following: + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">i.</var> + the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; + </li> +<li> + <var class="replacable-license-text">ii.</var> + moral rights retained by the original author(s) and/or performer(s); + </li> +<li> + <var class="replacable-license-text">iii.</var> + publicity and privacy rights pertaining to a person&apos;s image or likeness depicted in a Work; + </li> +<li> + <var class="replacable-license-text">iv.</var> + rights protecting against unfair competition in regards to a Work, subject to the limitations + in paragraph 4(a), below; + </li> +<li> + <var class="replacable-license-text">v.</var> + rights protecting the extraction, dissemination, use and reuse of data in a Work; + </li> +<li> + <var class="replacable-license-text">vi.</var> + database rights (such as those arising under Directive 96/9/EC of the European Parliament and + of the Council of 11 March 1996 on the legal protection of databases, and under any + national implementation thereof, including any amended or successor version of such + directive); and + </li> +<li> + <var class="replacable-license-text">vii.</var> + other similar, equivalent or corresponding rights throughout the world based on applicable + law or treaty, and any national implementations thereof. + </li> +</ul> + </li> +<li> + <var class="replacable-license-text">2.</var> + Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, + Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, + and surrenders all of Affirmer&apos;s Copyright and Related Rights and associated claims and + causes of action, whether now known or unknown (including existing as well as future claims + and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum + duration provided by applicable law or treaty (including future time extensions), (iii) in any + current or future medium and for any number of copies, and (iv) for any purpose whatsoever, + including without limitation commercial, advertising or promotional purposes (the + &quot;Waiver&quot;). Affirmer makes the Waiver for the benefit of each member of the public at + large and to the detriment of Affirmer&apos;s heirs and successors, fully intending that such + Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other + legal or equitable action to disrupt the quiet enjoyment of the Work by the public as + contemplated by Affirmer&apos;s express Statement of Purpose. + </li> +<li> + <var class="replacable-license-text">3.</var> + Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid + or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent + permitted taking into account Affirmer&apos;s express Statement of Purpose. In addition, to + the extent the Waiver is so judged Affirmer hereby grants to each affected person a + royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and + unconditional license to exercise Affirmer&apos;s Copyright and Related Rights in the Work (i) + in all territories worldwide, (ii) for the maximum duration provided by applicable law or + treaty (including future time extensions), (iii) in any current or future medium and for any + number of copies, and (iv) for any purpose whatsoever, including without limitation + commercial, advertising or promotional purposes (the &quot;License&quot;). The License shall + be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of + the License for any reason be judged legally invalid or ineffective under applicable law, such + partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and + in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her + remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and + causes of action with respect to the Work, in either case contrary to Affirmer&apos;s express + Statement of Purpose. + </li> +<li> + <var class="replacable-license-text">4.</var> + Limitations and Disclaimers. + +<ul style="list-style:none"> +<li> + <var class="replacable-license-text">a.</var> + No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed + or otherwise affected by this document. + </li> +<li> + <var class="replacable-license-text">b.</var> + Affirmer offers the Work as-is and makes no representations or warranties of any kind + concerning the Work, express, implied, statutory or otherwise, including without + limitation warranties of title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or the present or + absence of errors, whether or not discoverable, all to the greatest extent permissible + under applicable law. + </li> +<li> + <var class="replacable-license-text">c.</var> + Affirmer disclaims responsibility for clearing rights of other persons that may apply to the + Work or any use thereof, including without limitation any person&apos;s Copyright and + Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any + necessary consents, permissions or other rights required for any use of the Work. + </li> +<li> + <var class="replacable-license-text">d.</var> + Affirmer understands and acknowledges that Creative Commons is not a party to this document + and has no duty or obligation with respect to this CC0 or use of the Work. + </li> +</ul> + </li> +</ul> + <var class="optional-license-text"><var class="replacable-license-text"></var></var> + + <<beginOptional>> <<beginOptional>> Creative Commons<<beginOptional>> Legal Code<<endOptional>> + +<<endOptional>> + +CC0 1.0 Universal + +<<endOptional>><<beginOptional>> CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. + +<<endOptional>> + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. + + <<var;name="bullet";original="1.";match=".{0,20}">> Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: + + <<var;name="bullet";original="i.";match=".{0,20}">> the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; + + <<var;name="bullet";original="ii.";match=".{0,20}">> moral rights retained by the original author(s) and/or performer(s); + + <<var;name="bullet";original="iii.";match=".{0,20}">> publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; + + <<var;name="bullet";original="iv.";match=".{0,20}">> rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; + + <<var;name="bullet";original="v.";match=".{0,20}">> rights protecting the extraction, dissemination, use and reuse of data in a Work; + + <<var;name="bullet";original="vi.";match=".{0,20}">> database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and + + <<var;name="bullet";original="vii.";match=".{0,20}">> other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. + + <<var;name="bullet";original="2.";match=".{0,20}">> Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. + + <<var;name="bullet";original="3.";match=".{0,20}">> Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. + + <<var;name="bullet";original="4.";match=".{0,20}">> Limitations and Disclaimers. + + <<var;name="bullet";original="a.";match=".{0,20}">> No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. + + <<var;name="bullet";original="b.";match=".{0,20}">> Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. + + <<var;name="bullet";original="c.";match=".{0,20}">> Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. + + <<var;name="bullet";original="d.";match=".{0,20}">> Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.<<beginOptional>> <<var;name="upstreamLink";original="";match="For more information, please see <http://creativecommons.org/publicdomain/zero/1.0/>">><<endOptional>> + Creative Commons Zero v1.0 Universal + CC0-1.0 + Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. + + https://creativecommons.org/publicdomain/zero/1.0/legalcode + + + + + + http://people.freebsd.org/~phk/ + The beerware license has a couple of other standard variants. + "THE BEER-WARE LICENSE" (Revision 42): +phk@FreeBSD.ORG wrote this file. As long as you retain this notice you +can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp + Beer-Ware License (Version 42) + + + + + Person: Joe Reviewer + This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses + + 2010-02-10T00:00:00Z + + + + + + + + + d6a770ba38583ed4bb4525bd96e50461655d2759 + + + + + + + /* + * (c) Copyright 2009 University of Bristol + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + + + + + + + + This document was created using SPDX 2.0 using licenses from the web site. + + + + + + + + + Person: Suzanne Reviewer + Another example reviewer. + + 2011-03-13T00:00:00Z + + + SPDX-Tools-v2.0 + + + Person: Jane Doe () + Document level annotation + + 2010-01-29T18:30:22Z + + + + + + http://commons.apache.org/proper/commons-lang/ + NOASSERTION + + NOASSERTION + Apache Commons Lang + + false + + diff --git a/tests/spdx/parser/rdf/data/file_to_test_rdf_parser.rdf.xml b/tests/spdx/parser/rdf/data/file_to_test_rdf_parser.rdf.xml index 2cd671ee9..2320ff440 100644 --- a/tests/spdx/parser/rdf/data/file_to_test_rdf_parser.rdf.xml +++ b/tests/spdx/parser/rdf/data/file_to_test_rdf_parser.rdf.xml @@ -149,6 +149,14 @@ + + + https://see.also + extractedText + licenseComment + another license + + diff --git a/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py b/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py index 46eacfe96..c57f1aada 100644 --- a/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py @@ -3,21 +3,51 @@ # SPDX-License-Identifier: Apache-2.0 import os +import pytest from rdflib import RDF, Graph from spdx.parser.rdf.extracted_licensing_info_parser import parse_extracted_licensing_info from spdx.rdfschema.namespace import SPDX_NAMESPACE -def test_parse_extracted_licensing_info(): +@pytest.mark.parametrize( + "license_id, extracted_text, comment, license_name, cross_references", + [ + ( + "LicenseRef-1", + "extractedText", + "licenseComment", + "licenseName", + ["https://see.also"], + ), + ( + "LicenseRef-2", + "extractedText", + "licenseComment", + "another license", + ["https://see.also"], + ), + ], +) +# In rdf, as a short form, the explicit node for licenseId can be omitted, since the ID is also encoded in the URIRef +# of the ExtractedLicensingInfo node. The first test case has an explicit licenseId node whereas the second test case +# does not. This behaviour is similar to the externalDocumentRefId, see the discussion here: +# https://github.com/spdx/spdx-spec/issues/816 +def test_parse_extracted_licensing_info(license_id, extracted_text, comment, license_name, cross_references): graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) - doc_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.SpdxDocument) - extracted_licensing_info_node = graph.value(subject=doc_node, predicate=SPDX_NAMESPACE.hasExtractedLicensingInfo) + doc_namespace = "https://some.namespace" + extracted_licensing_info_node = get_extracted_licensing_info_node_by_license_id(graph, license_id) - extracted_licensing_info = parse_extracted_licensing_info(extracted_licensing_info_node, graph) + extracted_licensing_info = parse_extracted_licensing_info(extracted_licensing_info_node, graph, doc_namespace) - assert extracted_licensing_info.license_id == "LicenseRef-1" - assert extracted_licensing_info.extracted_text == "extractedText" - assert extracted_licensing_info.comment == "licenseComment" - assert extracted_licensing_info.license_name == "licenseName" - assert extracted_licensing_info.cross_references == ["https://see.also"] + assert extracted_licensing_info.license_id == license_id + assert extracted_licensing_info.extracted_text == extracted_text + assert extracted_licensing_info.comment == comment + assert extracted_licensing_info.license_name == license_name + assert extracted_licensing_info.cross_references == cross_references + + +def get_extracted_licensing_info_node_by_license_id(graph, license_id): + for extracted_licensing_info_node, _, _ in graph.triples((None, RDF.type, SPDX_NAMESPACE.ExtractedLicensingInfo)): + if extracted_licensing_info_node.fragment == license_id: + return extracted_licensing_info_node diff --git a/tests/spdx/parser/rdf/test_rdf_parser.py b/tests/spdx/parser/rdf/test_rdf_parser.py index 754c9ae1f..1faf0dcd0 100644 --- a/tests/spdx/parser/rdf/test_rdf_parser.py +++ b/tests/spdx/parser/rdf/test_rdf_parser.py @@ -7,6 +7,7 @@ from spdx.model.document import Document from spdx.parser.rdf import rdf_parser +from spdx.validation.document_validator import validate_full_spdx_document def test_rdf_parser_file_not_found(): @@ -19,7 +20,9 @@ def test_rdf_parser_with_2_3_example(): doc = rdf_parser.parse_from_file( os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXRdfExample-v2.3.spdx.rdf.xml") ) + validation_messages = validate_full_spdx_document(doc) + assert validation_messages == [] assert type(doc) == Document assert len(doc.snippets) == 1 assert len(doc.files) == 5 @@ -27,3 +30,19 @@ def test_rdf_parser_with_2_3_example(): assert len(doc.packages) == 4 assert len(doc.relationships) == 13 assert len(doc.extracted_licensing_info) == 5 + + +def test_rdf_parser_with_2_2_example(): + doc = rdf_parser.parse_from_file( + os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXRdfExample-v2.2.spdx.rdf.xml") + ) + validation_messages = validate_full_spdx_document(doc) + + assert validation_messages == [] + assert type(doc) == Document + assert len(doc.snippets) == 1 + assert len(doc.files) == 4 + assert len(doc.annotations) == 5 + assert len(doc.packages) == 4 + assert len(doc.relationships) == 9 + assert len(doc.extracted_licensing_info) == 5 From a0197f980a8732be18c41ce093b3f450df59a657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 30 Mar 2023 17:17:51 +0200 Subject: [PATCH 036/354] update the readme to point at the correct branch for v0.7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 998dce902..ec96ac440 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ CI status (Linux, macOS and Windows): [![Install and Test][1]][2] This repository was subject to a major refactoring recently to get ready for the upcoming SPDX v3.0 release. Therefore, we'd like to encourage you to post any and all issues you find at https://github.com/spdx/tools-python/issues. If you are looking for the source code of the [current PyPI release](https://pypi.python.org/pypi/spdx-tools), check out -the [v0.7.1 branch](https://github.com/spdx/tools-python/tree/release/v0.7.1). +the [v0.7 branch](https://github.com/spdx/tools-python/tree/version/v0.7). Note, though, that this will only receive bug fixes but no new features. We encourage you to use the new, refactored version (on the main branch) if you From 69b9a1d720d6b0bafdb7143c4c010caca86b897b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Fri, 31 Mar 2023 15:00:21 +0200 Subject: [PATCH 037/354] shorten line lengths in README, so they can be read on GitHub main page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ec96ac440..a56cc8f3e 100644 --- a/README.md +++ b/README.md @@ -114,22 +114,26 @@ document.creation_info.name = "new document name" # define a file and a DESCRIBES relationship between the file and the document checksum = Checksum(ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c") -file = File(name="./fileName.py", spdx_id="SPDXRef-File", checksums=[checksum], file_types=[FileType.TEXT], +file = File(name="./fileName.py", spdx_id="SPDXRef-File", checksums=[checksum], + file_types=[FileType.TEXT], license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"), license_comment="licenseComment", copyright_text="copyrightText") relationship = Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-File") -# add the file and the relationship to the document (note that we do not use "document.files.append(file)" as that would circumvent the type checking) +# add the file and the relationship to the document +# (note that we do not use "document.files.append(file)" as that would circumvent the type checking) document.files = document.files + [file] document.relationships = document.relationships + [relationship] -# validate the edited document and log the validation messages (depending on your use case, you might also want to utilize the provided validation_message.context) +# validate the edited document and log the validation messages +# (depending on your use case, you might also want to utilize the validation_message.context) validation_messages = validate_full_spdx_document(document) for validation_message in validation_messages: logging.warning(validation_message.validation_message) -# if there are no validation messages, the document is valid and we can safely serialize it without validating again +# if there are no validation messages, the document is valid +# and we can safely serialize it without validating again if not validation_messages: write_file(document, "new_spdx_document.rdf", validate=False) ``` From ac9e62fd970ad40aba8fb7fd2988691b35e54b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 3 Apr 2023 12:02:18 +0200 Subject: [PATCH 038/354] add missing license identifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx/casing_tools.py | 2 +- src/spdx/datetime_conversions.py | 2 +- src/spdx/document_utils.py | 2 +- src/spdx/formats.py | 2 +- src/spdx/jsonschema/annotation_converter.py | 2 +- src/spdx/jsonschema/annotation_properties.py | 2 +- src/spdx/jsonschema/checksum_converter.py | 2 +- src/spdx/jsonschema/checksum_properties.py | 2 +- src/spdx/jsonschema/converter.py | 2 +- src/spdx/jsonschema/creation_info_converter.py | 2 +- src/spdx/jsonschema/creation_info_properties.py | 2 +- src/spdx/jsonschema/document_converter.py | 2 +- src/spdx/jsonschema/document_properties.py | 2 +- .../jsonschema/external_document_ref_converter.py | 2 +- .../jsonschema/external_document_ref_properties.py | 2 +- .../jsonschema/external_package_ref_converter.py | 2 +- .../jsonschema/external_package_ref_properties.py | 2 +- .../extracted_licensing_info_converter.py | 2 +- .../extracted_licensing_info_properties.py | 2 +- src/spdx/jsonschema/file_converter.py | 2 +- src/spdx/jsonschema/file_properties.py | 2 +- src/spdx/jsonschema/json_property.py | 2 +- src/spdx/jsonschema/optional_utils.py | 2 +- src/spdx/jsonschema/package_converter.py | 2 +- src/spdx/jsonschema/package_properties.py | 2 +- .../package_verification_code_converter.py | 2 +- .../package_verification_code_properties.py | 2 +- src/spdx/jsonschema/relationship_converter.py | 2 +- src/spdx/jsonschema/relationship_properties.py | 2 +- src/spdx/jsonschema/snippet_converter.py | 2 +- src/spdx/jsonschema/snippet_properties.py | 2 +- src/spdx/model/actor.py | 2 +- src/spdx/model/annotation.py | 2 +- src/spdx/model/checksum.py | 2 +- src/spdx/model/document.py | 2 +- src/spdx/model/external_document_ref.py | 2 +- src/spdx/model/extracted_licensing_info.py | 2 +- src/spdx/model/file.py | 2 +- src/spdx/model/package.py | 2 +- src/spdx/model/relationship.py | 2 +- src/spdx/model/relationship_filters.py | 2 +- src/spdx/model/snippet.py | 2 +- src/spdx/model/spdx_no_assertion.py | 2 +- src/spdx/model/spdx_none.py | 2 +- src/spdx/model/version.py | 2 +- src/spdx/parser/actor_parser.py | 2 +- src/spdx/parser/error.py | 2 +- src/spdx/parser/json/json_parser.py | 2 +- src/spdx/parser/jsonlikedict/annotation_parser.py | 2 +- src/spdx/parser/jsonlikedict/checksum_parser.py | 2 +- .../parser/jsonlikedict/creation_info_parser.py | 2 +- .../parser/jsonlikedict/dict_parsing_functions.py | 2 +- .../jsonlikedict/extracted_licensing_info_parser.py | 2 +- src/spdx/parser/jsonlikedict/file_parser.py | 2 +- .../parser/jsonlikedict/json_like_dict_parser.py | 2 +- .../jsonlikedict/license_expression_parser.py | 2 +- src/spdx/parser/jsonlikedict/package_parser.py | 2 +- src/spdx/parser/jsonlikedict/relationship_parser.py | 2 +- src/spdx/parser/jsonlikedict/snippet_parser.py | 2 +- src/spdx/parser/logger.py | 2 +- src/spdx/parser/parsing_functions.py | 2 +- src/spdx/parser/rdf/annotation_parser.py | 2 +- src/spdx/parser/rdf/checksum_parser.py | 2 +- src/spdx/parser/rdf/creation_info_parser.py | 2 +- .../parser/rdf/extracted_licensing_info_parser.py | 2 +- src/spdx/parser/rdf/file_parser.py | 2 +- src/spdx/parser/rdf/graph_parsing_functions.py | 2 +- src/spdx/parser/rdf/license_expression_parser.py | 2 +- src/spdx/parser/rdf/package_parser.py | 2 +- src/spdx/parser/rdf/rdf_parser.py | 2 +- src/spdx/parser/rdf/relationship_parser.py | 2 +- src/spdx/parser/rdf/snippet_parser.py | 2 +- src/spdx/parser/tagvalue/helper_methods.py | 2 +- src/spdx/parser/tagvalue/tagvalue_parser.py | 2 +- src/spdx/parser/xml/xml_parser.py | 2 +- src/spdx/parser/yaml/yaml_parser.py | 2 +- src/spdx/rdfschema/namespace.py | 2 +- src/spdx/validation/actor_validator.py | 2 +- src/spdx/validation/annotation_validator.py | 2 +- src/spdx/validation/checksum_validator.py | 2 +- src/spdx/validation/creation_info_validator.py | 2 +- src/spdx/validation/document_validator.py | 2 +- .../validation/external_document_ref_validator.py | 2 +- .../validation/external_package_ref_validator.py | 2 +- .../extracted_licensing_info_validator.py | 2 +- src/spdx/validation/file_validator.py | 2 +- src/spdx/validation/license_expression_validator.py | 2 +- src/spdx/validation/package_validator.py | 2 +- .../package_verification_code_validator.py | 2 +- src/spdx/validation/relationship_validator.py | 2 +- src/spdx/validation/snippet_validator.py | 2 +- src/spdx/validation/spdx_id_validators.py | 2 +- src/spdx/validation/uri_validators.py | 2 +- src/spdx/validation/validation_message.py | 2 +- src/spdx/writer/json/json_writer.py | 2 +- src/spdx/writer/rdf/annotation_writer.py | 2 +- src/spdx/writer/rdf/checksum_writer.py | 2 +- src/spdx/writer/rdf/creation_info_writer.py | 2 +- src/spdx/writer/rdf/external_document_ref_writer.py | 2 +- .../writer/rdf/extracted_licensing_info_writer.py | 2 +- src/spdx/writer/rdf/file_writer.py | 2 +- src/spdx/writer/rdf/license_expression_writer.py | 2 +- src/spdx/writer/rdf/package_writer.py | 2 +- src/spdx/writer/rdf/rdf_writer.py | 2 +- src/spdx/writer/rdf/relationship_writer.py | 2 +- src/spdx/writer/rdf/snippet_writer.py | 2 +- src/spdx/writer/rdf/writer_utils.py | 2 +- src/spdx/writer/write_anything.py | 2 +- src/spdx/writer/xml/xml_writer.py | 2 +- src/spdx/writer/yaml/yaml_writer.py | 2 +- tests/spdx/fixtures.py | 2 +- tests/spdx/jsonschema/test_annotation_converter.py | 2 +- tests/spdx/jsonschema/test_checksum_converter.py | 2 +- tests/spdx/jsonschema/test_converter.py | 2 +- .../spdx/jsonschema/test_creation_info_converter.py | 2 +- tests/spdx/jsonschema/test_document_converter.py | 2 +- .../test_external_document_ref_converter.py | 2 +- .../test_external_package_ref_converter.py | 2 +- .../test_extracted_licensing_info_converter.py | 2 +- tests/spdx/jsonschema/test_file_converter.py | 2 +- tests/spdx/jsonschema/test_package_converter.py | 2 +- .../test_package_verification_code_converter.py | 2 +- .../spdx/jsonschema/test_relationship_converter.py | 2 +- tests/spdx/jsonschema/test_snippet_converter.py | 2 +- tests/spdx/mock_utils.py | 2 +- tests/spdx/model/test_actor.py | 4 ++++ tests/spdx/model/test_annotation.py | 4 ++++ tests/spdx/model/test_checksum.py | 4 ++++ tests/spdx/model/test_creation_info.py | 4 ++++ tests/spdx/model/test_document.py | 4 ++++ tests/spdx/model/test_external_document_ref.py | 4 ++++ tests/spdx/model/test_external_package_reference.py | 4 ++++ tests/spdx/model/test_extracted_licensing_info.py | 4 ++++ tests/spdx/model/test_file.py | 4 ++++ tests/spdx/model/test_package.py | 4 ++++ tests/spdx/model/test_package_verification_code.py | 4 ++++ tests/spdx/model/test_relationship.py | 4 ++++ tests/spdx/model/test_snippet.py | 4 ++++ tests/spdx/model/test_version.py | 3 +-- tests/spdx/parser/json/test_json_parser.py | 2 +- .../parser/jsonlikedict/test_annotation_parser.py | 2 +- .../parser/jsonlikedict/test_checksum_parser.py | 2 +- .../jsonlikedict/test_creation_info_parser.py | 2 +- .../jsonlikedict/test_dict_parsing_functions.py | 13 +++---------- .../test_extracted_licensing_info_parser.py | 2 +- tests/spdx/parser/jsonlikedict/test_file_parser.py | 2 +- .../jsonlikedict/test_license_expression_parser.py | 2 +- .../spdx/parser/jsonlikedict/test_package_parser.py | 2 +- .../parser/jsonlikedict/test_relationship_parser.py | 2 +- .../spdx/parser/jsonlikedict/test_snippet_parser.py | 2 +- tests/spdx/parser/rdf/test_annotation_parser.py | 2 +- tests/spdx/parser/rdf/test_checksum_parser.py | 2 +- tests/spdx/parser/rdf/test_creation_info_parser.py | 2 +- .../rdf/test_extracted_licensing_info_parser.py | 2 +- tests/spdx/parser/rdf/test_file_parser.py | 2 +- .../spdx/parser/rdf/test_graph_parsing_function.py | 2 +- .../parser/rdf/test_license_expression_parser.py | 2 +- tests/spdx/parser/rdf/test_package_parser.py | 2 +- tests/spdx/parser/rdf/test_rdf_parser.py | 2 +- tests/spdx/parser/rdf/test_relationship_parser.py | 2 +- tests/spdx/parser/rdf/test_snippet_parser.py | 2 +- .../spdx/parser/tagvalue/test_annotation_parser.py | 2 +- .../parser/tagvalue/test_creation_info_parser.py | 2 +- .../test_extracted_licensing_info_parser.py | 2 +- tests/spdx/parser/tagvalue/test_file_parser.py | 2 +- tests/spdx/parser/tagvalue/test_helper_methods.py | 2 +- tests/spdx/parser/tagvalue/test_package_parser.py | 2 +- .../parser/tagvalue/test_relationship_parser.py | 2 +- tests/spdx/parser/tagvalue/test_snippet_parser.py | 2 +- tests/spdx/parser/tagvalue/test_tag_value_lexer.py | 2 +- tests/spdx/parser/tagvalue/test_tag_value_parser.py | 2 +- tests/spdx/test_actor_parser.py | 2 +- tests/spdx/test_casing_tools.py | 2 +- tests/spdx/test_datetime_conversions.py | 2 +- tests/spdx/test_document_utils.py | 4 ++-- tests/spdx/validation/test_actor_validator.py | 2 +- tests/spdx/validation/test_annotation_validator.py | 2 +- tests/spdx/validation/test_checksum_validator.py | 2 +- .../spdx/validation/test_creation_info_validator.py | 2 +- tests/spdx/validation/test_document_validator.py | 2 +- .../test_external_document_ref_validator.py | 2 +- .../test_external_package_ref_validator.py | 2 +- .../test_extracted_licensing_info_validator.py | 2 +- tests/spdx/validation/test_file_validator.py | 2 +- .../validation/test_license_expression_validator.py | 2 +- tests/spdx/validation/test_package_validator.py | 2 +- .../test_package_verification_code_validator.py | 2 +- .../spdx/validation/test_relationship_validator.py | 2 +- tests/spdx/validation/test_snippet_validator.py | 2 +- tests/spdx/validation/test_spdx_id_validators.py | 2 +- tests/spdx/validation/test_uri_validators.py | 2 +- tests/spdx/writer/json/test_json_writer.py | 2 +- tests/spdx/writer/rdf/test_annotation_writer.py | 2 +- tests/spdx/writer/rdf/test_checksum_writer.py | 2 +- tests/spdx/writer/rdf/test_creation_info_writer.py | 2 +- .../writer/rdf/test_external_document_ref_writer.py | 2 +- .../rdf/test_extracted_licensing_info_writer.py | 2 +- tests/spdx/writer/rdf/test_file_writer.py | 2 +- .../writer/rdf/test_license_expression_writer.py | 2 +- tests/spdx/writer/rdf/test_package_writer.py | 2 +- tests/spdx/writer/rdf/test_rdf_writer.py | 2 +- tests/spdx/writer/rdf/test_relationship_writer.py | 2 +- tests/spdx/writer/rdf/test_snippet_writer.py | 2 +- tests/spdx/writer/rdf/test_writer_utils.py | 2 +- tests/spdx/writer/tagvalue/test_package_writer.py | 13 +++---------- tests/spdx/writer/tagvalue/test_tagvalue_writer.py | 13 +++---------- .../test_tagvalue_writer_helper_functions.py | 13 +++---------- 207 files changed, 255 insertions(+), 232 deletions(-) diff --git a/src/spdx/casing_tools.py b/src/spdx/casing_tools.py index d77ba9222..c143cfd45 100644 --- a/src/spdx/casing_tools.py +++ b/src/spdx/casing_tools.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from re import sub diff --git a/src/spdx/datetime_conversions.py b/src/spdx/datetime_conversions.py index e74e09474..58ac88324 100644 --- a/src/spdx/datetime_conversions.py +++ b/src/spdx/datetime_conversions.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime diff --git a/src/spdx/document_utils.py b/src/spdx/document_utils.py index d3bf3ddcc..73c603feb 100644 --- a/src/spdx/document_utils.py +++ b/src/spdx/document_utils.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Union diff --git a/src/spdx/formats.py b/src/spdx/formats.py index eefd51369..0500088a6 100644 --- a/src/spdx/formats.py +++ b/src/spdx/formats.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto diff --git a/src/spdx/jsonschema/annotation_converter.py b/src/spdx/jsonschema/annotation_converter.py index 7688d81cb..86aaafc32 100644 --- a/src/spdx/jsonschema/annotation_converter.py +++ b/src/spdx/jsonschema/annotation_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type diff --git a/src/spdx/jsonschema/annotation_properties.py b/src/spdx/jsonschema/annotation_properties.py index 688eb9530..659e222aa 100644 --- a/src/spdx/jsonschema/annotation_properties.py +++ b/src/spdx/jsonschema/annotation_properties.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto diff --git a/src/spdx/jsonschema/checksum_converter.py b/src/spdx/jsonschema/checksum_converter.py index cd430c274..2cbdcf2b1 100644 --- a/src/spdx/jsonschema/checksum_converter.py +++ b/src/spdx/jsonschema/checksum_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Type diff --git a/src/spdx/jsonschema/checksum_properties.py b/src/spdx/jsonschema/checksum_properties.py index 9ab691bee..adac99357 100644 --- a/src/spdx/jsonschema/checksum_properties.py +++ b/src/spdx/jsonschema/checksum_properties.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto diff --git a/src/spdx/jsonschema/converter.py b/src/spdx/jsonschema/converter.py index 484777898..8607f4a91 100644 --- a/src/spdx/jsonschema/converter.py +++ b/src/spdx/jsonschema/converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from abc import ABC, abstractmethod from typing import Any, Dict, Generic, Type, TypeVar diff --git a/src/spdx/jsonschema/creation_info_converter.py b/src/spdx/jsonschema/creation_info_converter.py index 70e0b3e29..c9e5d0f97 100644 --- a/src/spdx/jsonschema/creation_info_converter.py +++ b/src/spdx/jsonschema/creation_info_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type diff --git a/src/spdx/jsonschema/creation_info_properties.py b/src/spdx/jsonschema/creation_info_properties.py index 79aa266ae..d5a16eb2e 100644 --- a/src/spdx/jsonschema/creation_info_properties.py +++ b/src/spdx/jsonschema/creation_info_properties.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto diff --git a/src/spdx/jsonschema/document_converter.py b/src/spdx/jsonschema/document_converter.py index 3a1675745..56bba2872 100644 --- a/src/spdx/jsonschema/document_converter.py +++ b/src/spdx/jsonschema/document_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type diff --git a/src/spdx/jsonschema/document_properties.py b/src/spdx/jsonschema/document_properties.py index a1413d004..6fc244a8b 100644 --- a/src/spdx/jsonschema/document_properties.py +++ b/src/spdx/jsonschema/document_properties.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto diff --git a/src/spdx/jsonschema/external_document_ref_converter.py b/src/spdx/jsonschema/external_document_ref_converter.py index 196fac7de..cc3d28bfc 100644 --- a/src/spdx/jsonschema/external_document_ref_converter.py +++ b/src/spdx/jsonschema/external_document_ref_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type diff --git a/src/spdx/jsonschema/external_document_ref_properties.py b/src/spdx/jsonschema/external_document_ref_properties.py index d80990c2d..16f1c33b8 100644 --- a/src/spdx/jsonschema/external_document_ref_properties.py +++ b/src/spdx/jsonschema/external_document_ref_properties.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto diff --git a/src/spdx/jsonschema/external_package_ref_converter.py b/src/spdx/jsonschema/external_package_ref_converter.py index 91e1104c3..3df3215ca 100644 --- a/src/spdx/jsonschema/external_package_ref_converter.py +++ b/src/spdx/jsonschema/external_package_ref_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type diff --git a/src/spdx/jsonschema/external_package_ref_properties.py b/src/spdx/jsonschema/external_package_ref_properties.py index f922e95d5..153b37118 100644 --- a/src/spdx/jsonschema/external_package_ref_properties.py +++ b/src/spdx/jsonschema/external_package_ref_properties.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto diff --git a/src/spdx/jsonschema/extracted_licensing_info_converter.py b/src/spdx/jsonschema/extracted_licensing_info_converter.py index 0af7469df..10c11b27d 100644 --- a/src/spdx/jsonschema/extracted_licensing_info_converter.py +++ b/src/spdx/jsonschema/extracted_licensing_info_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type diff --git a/src/spdx/jsonschema/extracted_licensing_info_properties.py b/src/spdx/jsonschema/extracted_licensing_info_properties.py index 46b6b6290..f7d735079 100644 --- a/src/spdx/jsonschema/extracted_licensing_info_properties.py +++ b/src/spdx/jsonschema/extracted_licensing_info_properties.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto diff --git a/src/spdx/jsonschema/file_converter.py b/src/spdx/jsonschema/file_converter.py index 518de6719..841c4e4b4 100644 --- a/src/spdx/jsonschema/file_converter.py +++ b/src/spdx/jsonschema/file_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type diff --git a/src/spdx/jsonschema/file_properties.py b/src/spdx/jsonschema/file_properties.py index 7b308134a..d0179b353 100644 --- a/src/spdx/jsonschema/file_properties.py +++ b/src/spdx/jsonschema/file_properties.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto diff --git a/src/spdx/jsonschema/json_property.py b/src/spdx/jsonschema/json_property.py index 7e7cd27f3..9bdbe1265 100644 --- a/src/spdx/jsonschema/json_property.py +++ b/src/spdx/jsonschema/json_property.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum diff --git a/src/spdx/jsonschema/optional_utils.py b/src/spdx/jsonschema/optional_utils.py index a204015ad..4f9d74074 100644 --- a/src/spdx/jsonschema/optional_utils.py +++ b/src/spdx/jsonschema/optional_utils.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Callable, Optional, TypeVar diff --git a/src/spdx/jsonschema/package_converter.py b/src/spdx/jsonschema/package_converter.py index 86ea5aeb4..0141289bc 100644 --- a/src/spdx/jsonschema/package_converter.py +++ b/src/spdx/jsonschema/package_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type diff --git a/src/spdx/jsonschema/package_properties.py b/src/spdx/jsonschema/package_properties.py index f62ce2fbb..5b3b42eb3 100644 --- a/src/spdx/jsonschema/package_properties.py +++ b/src/spdx/jsonschema/package_properties.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto diff --git a/src/spdx/jsonschema/package_verification_code_converter.py b/src/spdx/jsonschema/package_verification_code_converter.py index 13959ace3..6eb48674c 100644 --- a/src/spdx/jsonschema/package_verification_code_converter.py +++ b/src/spdx/jsonschema/package_verification_code_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type diff --git a/src/spdx/jsonschema/package_verification_code_properties.py b/src/spdx/jsonschema/package_verification_code_properties.py index 7499c5acd..0ffa2391c 100644 --- a/src/spdx/jsonschema/package_verification_code_properties.py +++ b/src/spdx/jsonschema/package_verification_code_properties.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto diff --git a/src/spdx/jsonschema/relationship_converter.py b/src/spdx/jsonschema/relationship_converter.py index 5527f2551..bc3b06bda 100644 --- a/src/spdx/jsonschema/relationship_converter.py +++ b/src/spdx/jsonschema/relationship_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type diff --git a/src/spdx/jsonschema/relationship_properties.py b/src/spdx/jsonschema/relationship_properties.py index a96d1f287..bfb2031c8 100644 --- a/src/spdx/jsonschema/relationship_properties.py +++ b/src/spdx/jsonschema/relationship_properties.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto diff --git a/src/spdx/jsonschema/snippet_converter.py b/src/spdx/jsonschema/snippet_converter.py index b80907e9a..e3fcd2b83 100644 --- a/src/spdx/jsonschema/snippet_converter.py +++ b/src/spdx/jsonschema/snippet_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Dict, Tuple, Type diff --git a/src/spdx/jsonschema/snippet_properties.py b/src/spdx/jsonschema/snippet_properties.py index 0ee8ba324..f485d59d0 100644 --- a/src/spdx/jsonschema/snippet_properties.py +++ b/src/spdx/jsonschema/snippet_properties.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto diff --git a/src/spdx/model/actor.py b/src/spdx/model/actor.py index 66e38bd83..9160581e0 100644 --- a/src/spdx/model/actor.py +++ b/src/spdx/model/actor.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import Optional diff --git a/src/spdx/model/annotation.py b/src/spdx/model/annotation.py index 0718191b6..0e07f98fa 100644 --- a/src/spdx/model/annotation.py +++ b/src/spdx/model/annotation.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from enum import Enum, auto diff --git a/src/spdx/model/checksum.py b/src/spdx/model/checksum.py index e4f121086..5ec824fc1 100644 --- a/src/spdx/model/checksum.py +++ b/src/spdx/model/checksum.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto diff --git a/src/spdx/model/document.py b/src/spdx/model/document.py index e083cd4fa..0f2802a59 100644 --- a/src/spdx/model/document.py +++ b/src/spdx/model/document.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from datetime import datetime diff --git a/src/spdx/model/external_document_ref.py b/src/spdx/model/external_document_ref.py index 35c045f2a..afcb8450f 100644 --- a/src/spdx/model/external_document_ref.py +++ b/src/spdx/model/external_document_ref.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx/model/extracted_licensing_info.py b/src/spdx/model/extracted_licensing_info.py index 3133f9e5f..4b83dae20 100644 --- a/src/spdx/model/extracted_licensing_info.py +++ b/src/spdx/model/extracted_licensing_info.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from typing import List, Optional, Union diff --git a/src/spdx/model/file.py b/src/spdx/model/file.py index db51ab511..6df5ba3f3 100644 --- a/src/spdx/model/file.py +++ b/src/spdx/model/file.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from enum import Enum, auto diff --git a/src/spdx/model/package.py b/src/spdx/model/package.py index b468d576c..196c44236 100644 --- a/src/spdx/model/package.py +++ b/src/spdx/model/package.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from datetime import datetime diff --git a/src/spdx/model/relationship.py b/src/spdx/model/relationship.py index 565de3f74..fdf0a8d7d 100644 --- a/src/spdx/model/relationship.py +++ b/src/spdx/model/relationship.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import Optional, Union diff --git a/src/spdx/model/relationship_filters.py b/src/spdx/model/relationship_filters.py index f2e8a856a..3cc5dc5a6 100644 --- a/src/spdx/model/relationship_filters.py +++ b/src/spdx/model/relationship_filters.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/model/snippet.py b/src/spdx/model/snippet.py index 6b39cbae0..fc9fa0353 100644 --- a/src/spdx/model/snippet.py +++ b/src/spdx/model/snippet.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from typing import List, Optional, Tuple, Union diff --git a/src/spdx/model/spdx_no_assertion.py b/src/spdx/model/spdx_no_assertion.py index 3f02d10b9..1255dba35 100644 --- a/src/spdx/model/spdx_no_assertion.py +++ b/src/spdx/model/spdx_no_assertion.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 SPDX_NO_ASSERTION_STRING = "NOASSERTION" diff --git a/src/spdx/model/spdx_none.py b/src/spdx/model/spdx_none.py index b44b705b3..25f63099f 100644 --- a/src/spdx/model/spdx_none.py +++ b/src/spdx/model/spdx_none.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 SPDX_NONE_STRING = "NONE" diff --git a/src/spdx/model/version.py b/src/spdx/model/version.py index c045ef8ae..c3874246b 100644 --- a/src/spdx/model/version.py +++ b/src/spdx/model/version.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 diff --git a/src/spdx/parser/actor_parser.py b/src/spdx/parser/actor_parser.py index 3266a51b0..007a7c575 100644 --- a/src/spdx/parser/actor_parser.py +++ b/src/spdx/parser/actor_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import re from typing import Match, Optional, Pattern diff --git a/src/spdx/parser/error.py b/src/spdx/parser/error.py index a0e7678e3..f3aaca7d0 100644 --- a/src/spdx/parser/error.py +++ b/src/spdx/parser/error.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/parser/json/json_parser.py b/src/spdx/parser/json/json_parser.py index 24f10a5ca..3d100afbb 100644 --- a/src/spdx/parser/json/json_parser.py +++ b/src/spdx/parser/json/json_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import json from typing import Dict diff --git a/src/spdx/parser/jsonlikedict/annotation_parser.py b/src/spdx/parser/jsonlikedict/annotation_parser.py index 2ac696d09..9d1d275ea 100644 --- a/src/spdx/parser/jsonlikedict/annotation_parser.py +++ b/src/spdx/parser/jsonlikedict/annotation_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Dict, List, Optional diff --git a/src/spdx/parser/jsonlikedict/checksum_parser.py b/src/spdx/parser/jsonlikedict/checksum_parser.py index bf2070727..3b61a2ee8 100644 --- a/src/spdx/parser/jsonlikedict/checksum_parser.py +++ b/src/spdx/parser/jsonlikedict/checksum_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict, Optional diff --git a/src/spdx/parser/jsonlikedict/creation_info_parser.py b/src/spdx/parser/jsonlikedict/creation_info_parser.py index bb7a2935b..0f518e9f5 100644 --- a/src/spdx/parser/jsonlikedict/creation_info_parser.py +++ b/src/spdx/parser/jsonlikedict/creation_info_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Dict, List, Optional diff --git a/src/spdx/parser/jsonlikedict/dict_parsing_functions.py b/src/spdx/parser/jsonlikedict/dict_parsing_functions.py index 57cdd710f..be2c632fd 100644 --- a/src/spdx/parser/jsonlikedict/dict_parsing_functions.py +++ b/src/spdx/parser/jsonlikedict/dict_parsing_functions.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Callable, Dict, List, Optional diff --git a/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py b/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py index 6190d38bd..1ffd772a4 100644 --- a/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py +++ b/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict, List, Optional, Union diff --git a/src/spdx/parser/jsonlikedict/file_parser.py b/src/spdx/parser/jsonlikedict/file_parser.py index f671ccb36..eb59fcc52 100644 --- a/src/spdx/parser/jsonlikedict/file_parser.py +++ b/src/spdx/parser/jsonlikedict/file_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict, List, Optional, Union diff --git a/src/spdx/parser/jsonlikedict/json_like_dict_parser.py b/src/spdx/parser/jsonlikedict/json_like_dict_parser.py index 1073fb57b..65732de75 100644 --- a/src/spdx/parser/jsonlikedict/json_like_dict_parser.py +++ b/src/spdx/parser/jsonlikedict/json_like_dict_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict diff --git a/src/spdx/parser/jsonlikedict/license_expression_parser.py b/src/spdx/parser/jsonlikedict/license_expression_parser.py index 73e0b4ba3..70cac7aec 100644 --- a/src/spdx/parser/jsonlikedict/license_expression_parser.py +++ b/src/spdx/parser/jsonlikedict/license_expression_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Union diff --git a/src/spdx/parser/jsonlikedict/package_parser.py b/src/spdx/parser/jsonlikedict/package_parser.py index afb12dc7f..c79fd1145 100644 --- a/src/spdx/parser/jsonlikedict/package_parser.py +++ b/src/spdx/parser/jsonlikedict/package_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Dict, List, Optional, Union diff --git a/src/spdx/parser/jsonlikedict/relationship_parser.py b/src/spdx/parser/jsonlikedict/relationship_parser.py index d1d0ae8a8..3471fb51d 100644 --- a/src/spdx/parser/jsonlikedict/relationship_parser.py +++ b/src/spdx/parser/jsonlikedict/relationship_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict, List, Optional diff --git a/src/spdx/parser/jsonlikedict/snippet_parser.py b/src/spdx/parser/jsonlikedict/snippet_parser.py index 0a6fbcbb9..52d2194ba 100644 --- a/src/spdx/parser/jsonlikedict/snippet_parser.py +++ b/src/spdx/parser/jsonlikedict/snippet_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import Dict, List, Optional, Tuple, Union diff --git a/src/spdx/parser/logger.py b/src/spdx/parser/logger.py index 4ebc1479d..8a90453d8 100644 --- a/src/spdx/parser/logger.py +++ b/src/spdx/parser/logger.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/parser/parsing_functions.py b/src/spdx/parser/parsing_functions.py index 32d2f3184..594bf3871 100644 --- a/src/spdx/parser/parsing_functions.py +++ b/src/spdx/parser/parsing_functions.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Dict diff --git a/src/spdx/parser/rdf/annotation_parser.py b/src/spdx/parser/rdf/annotation_parser.py index 6f6a0a39f..e75aa7b80 100644 --- a/src/spdx/parser/rdf/annotation_parser.py +++ b/src/spdx/parser/rdf/annotation_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef diff --git a/src/spdx/parser/rdf/checksum_parser.py b/src/spdx/parser/rdf/checksum_parser.py index 57dd247f2..456e709cb 100644 --- a/src/spdx/parser/rdf/checksum_parser.py +++ b/src/spdx/parser/rdf/checksum_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import Graph, URIRef diff --git a/src/spdx/parser/rdf/creation_info_parser.py b/src/spdx/parser/rdf/creation_info_parser.py index 938becb6e..eeb1e1d31 100644 --- a/src/spdx/parser/rdf/creation_info_parser.py +++ b/src/spdx/parser/rdf/creation_info_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import logging import sys diff --git a/src/spdx/parser/rdf/extracted_licensing_info_parser.py b/src/spdx/parser/rdf/extracted_licensing_info_parser.py index 1763eb214..6a713ddfd 100644 --- a/src/spdx/parser/rdf/extracted_licensing_info_parser.py +++ b/src/spdx/parser/rdf/extracted_licensing_info_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef diff --git a/src/spdx/parser/rdf/file_parser.py b/src/spdx/parser/rdf/file_parser.py index c42b6d1e5..2dec391d4 100644 --- a/src/spdx/parser/rdf/file_parser.py +++ b/src/spdx/parser/rdf/file_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef diff --git a/src/spdx/parser/rdf/graph_parsing_functions.py b/src/spdx/parser/rdf/graph_parsing_functions.py index 5accd10d9..72b107c7f 100644 --- a/src/spdx/parser/rdf/graph_parsing_functions.py +++ b/src/spdx/parser/rdf/graph_parsing_functions.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum from typing import Any, Callable, Optional, Type diff --git a/src/spdx/parser/rdf/license_expression_parser.py b/src/spdx/parser/rdf/license_expression_parser.py index 629b3fe9c..7f6017854 100644 --- a/src/spdx/parser/rdf/license_expression_parser.py +++ b/src/spdx/parser/rdf/license_expression_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Union diff --git a/src/spdx/parser/rdf/package_parser.py b/src/spdx/parser/rdf/package_parser.py index b4be7fdae..866af16a4 100644 --- a/src/spdx/parser/rdf/package_parser.py +++ b/src/spdx/parser/rdf/package_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Optional diff --git a/src/spdx/parser/rdf/rdf_parser.py b/src/spdx/parser/rdf/rdf_parser.py index 09b2173e0..d3726f436 100644 --- a/src/spdx/parser/rdf/rdf_parser.py +++ b/src/spdx/parser/rdf/rdf_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, Graph diff --git a/src/spdx/parser/rdf/relationship_parser.py b/src/spdx/parser/rdf/relationship_parser.py index 44d840e95..956b19177 100644 --- a/src/spdx/parser/rdf/relationship_parser.py +++ b/src/spdx/parser/rdf/relationship_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef diff --git a/src/spdx/parser/rdf/snippet_parser.py b/src/spdx/parser/rdf/snippet_parser.py index 284e1328a..446b0fc73 100644 --- a/src/spdx/parser/rdf/snippet_parser.py +++ b/src/spdx/parser/rdf/snippet_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict, Optional, Tuple diff --git a/src/spdx/parser/tagvalue/helper_methods.py b/src/spdx/parser/tagvalue/helper_methods.py index ef904cfa3..d5faef6b1 100644 --- a/src/spdx/parser/tagvalue/helper_methods.py +++ b/src/spdx/parser/tagvalue/helper_methods.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import re from typing import Any, Callable, Dict, Optional diff --git a/src/spdx/parser/tagvalue/tagvalue_parser.py b/src/spdx/parser/tagvalue/tagvalue_parser.py index 948c97e78..6fb54a28c 100644 --- a/src/spdx/parser/tagvalue/tagvalue_parser.py +++ b/src/spdx/parser/tagvalue/tagvalue_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from spdx.model.document import Document from spdx.parser.tagvalue.parser import Parser diff --git a/src/spdx/parser/xml/xml_parser.py b/src/spdx/parser/xml/xml_parser.py index 61c24edaa..4d0fa14a8 100644 --- a/src/spdx/parser/xml/xml_parser.py +++ b/src/spdx/parser/xml/xml_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Any, Dict diff --git a/src/spdx/parser/yaml/yaml_parser.py b/src/spdx/parser/yaml/yaml_parser.py index 4cfa9e5bf..7e413b66d 100644 --- a/src/spdx/parser/yaml/yaml_parser.py +++ b/src/spdx/parser/yaml/yaml_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict diff --git a/src/spdx/rdfschema/namespace.py b/src/spdx/rdfschema/namespace.py index 822872c54..5f330fb82 100644 --- a/src/spdx/rdfschema/namespace.py +++ b/src/spdx/rdfschema/namespace.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import Namespace diff --git a/src/spdx/validation/actor_validator.py b/src/spdx/validation/actor_validator.py index a1c3fecea..d65472d82 100644 --- a/src/spdx/validation/actor_validator.py +++ b/src/spdx/validation/actor_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/validation/annotation_validator.py b/src/spdx/validation/annotation_validator.py index 6e7774658..92f470953 100644 --- a/src/spdx/validation/annotation_validator.py +++ b/src/spdx/validation/annotation_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/validation/checksum_validator.py b/src/spdx/validation/checksum_validator.py index c5221598a..17b562587 100644 --- a/src/spdx/validation/checksum_validator.py +++ b/src/spdx/validation/checksum_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import re diff --git a/src/spdx/validation/creation_info_validator.py b/src/spdx/validation/creation_info_validator.py index 5650d9945..00e4a279e 100644 --- a/src/spdx/validation/creation_info_validator.py +++ b/src/spdx/validation/creation_info_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/validation/document_validator.py b/src/spdx/validation/document_validator.py index 0db5ef98a..f32be8f64 100644 --- a/src/spdx/validation/document_validator.py +++ b/src/spdx/validation/document_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/validation/external_document_ref_validator.py b/src/spdx/validation/external_document_ref_validator.py index 3089bb0f2..1f5746398 100644 --- a/src/spdx/validation/external_document_ref_validator.py +++ b/src/spdx/validation/external_document_ref_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/validation/external_package_ref_validator.py b/src/spdx/validation/external_package_ref_validator.py index 429caf422..5d3a732c5 100644 --- a/src/spdx/validation/external_package_ref_validator.py +++ b/src/spdx/validation/external_package_ref_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import re from typing import Dict, List diff --git a/src/spdx/validation/extracted_licensing_info_validator.py b/src/spdx/validation/extracted_licensing_info_validator.py index bb8f76281..11aee1bab 100644 --- a/src/spdx/validation/extracted_licensing_info_validator.py +++ b/src/spdx/validation/extracted_licensing_info_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import re diff --git a/src/spdx/validation/file_validator.py b/src/spdx/validation/file_validator.py index 1f9e666c9..45711050c 100644 --- a/src/spdx/validation/file_validator.py +++ b/src/spdx/validation/file_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx/validation/license_expression_validator.py b/src/spdx/validation/license_expression_validator.py index e4af4ee5e..f29f59441 100644 --- a/src/spdx/validation/license_expression_validator.py +++ b/src/spdx/validation/license_expression_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional, Union diff --git a/src/spdx/validation/package_validator.py b/src/spdx/validation/package_validator.py index ed22dbe83..d52be0884 100644 --- a/src/spdx/validation/package_validator.py +++ b/src/spdx/validation/package_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx/validation/package_verification_code_validator.py b/src/spdx/validation/package_verification_code_validator.py index 3ca65249f..1c910d8bb 100644 --- a/src/spdx/validation/package_verification_code_validator.py +++ b/src/spdx/validation/package_verification_code_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import re diff --git a/src/spdx/validation/relationship_validator.py b/src/spdx/validation/relationship_validator.py index bad94f78f..45e7845a9 100644 --- a/src/spdx/validation/relationship_validator.py +++ b/src/spdx/validation/relationship_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/validation/snippet_validator.py b/src/spdx/validation/snippet_validator.py index f312308f3..1248e6cc2 100644 --- a/src/spdx/validation/snippet_validator.py +++ b/src/spdx/validation/snippet_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx/validation/spdx_id_validators.py b/src/spdx/validation/spdx_id_validators.py index 00c80f11d..c8f031e1a 100644 --- a/src/spdx/validation/spdx_id_validators.py +++ b/src/spdx/validation/spdx_id_validators.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import re diff --git a/src/spdx/validation/uri_validators.py b/src/spdx/validation/uri_validators.py index 68bbed6dc..5b30f6b7d 100644 --- a/src/spdx/validation/uri_validators.py +++ b/src/spdx/validation/uri_validators.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import re diff --git a/src/spdx/validation/validation_message.py b/src/spdx/validation/validation_message.py index 21af28cb4..7b4178703 100644 --- a/src/spdx/validation/validation_message.py +++ b/src/spdx/validation/validation_message.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from dataclasses import dataclass diff --git a/src/spdx/writer/json/json_writer.py b/src/spdx/writer/json/json_writer.py index 97a29d598..68f435cd8 100644 --- a/src/spdx/writer/json/json_writer.py +++ b/src/spdx/writer/json/json_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import json from typing import List diff --git a/src/spdx/writer/rdf/annotation_writer.py b/src/spdx/writer/rdf/annotation_writer.py index 4b288b9ad..490d68cfe 100644 --- a/src/spdx/writer/rdf/annotation_writer.py +++ b/src/spdx/writer/rdf/annotation_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict diff --git a/src/spdx/writer/rdf/checksum_writer.py b/src/spdx/writer/rdf/checksum_writer.py index 1cc9ab6b5..12bfe214e 100644 --- a/src/spdx/writer/rdf/checksum_writer.py +++ b/src/spdx/writer/rdf/checksum_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, BNode, Graph, Literal, URIRef diff --git a/src/spdx/writer/rdf/creation_info_writer.py b/src/spdx/writer/rdf/creation_info_writer.py index 0e792ece1..87999bf7c 100644 --- a/src/spdx/writer/rdf/creation_info_writer.py +++ b/src/spdx/writer/rdf/creation_info_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef diff --git a/src/spdx/writer/rdf/external_document_ref_writer.py b/src/spdx/writer/rdf/external_document_ref_writer.py index f652ff552..d84c3d224 100644 --- a/src/spdx/writer/rdf/external_document_ref_writer.py +++ b/src/spdx/writer/rdf/external_document_ref_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, Graph, URIRef diff --git a/src/spdx/writer/rdf/extracted_licensing_info_writer.py b/src/spdx/writer/rdf/extracted_licensing_info_writer.py index d6af55f9c..15a603d0c 100644 --- a/src/spdx/writer/rdf/extracted_licensing_info_writer.py +++ b/src/spdx/writer/rdf/extracted_licensing_info_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef diff --git a/src/spdx/writer/rdf/file_writer.py b/src/spdx/writer/rdf/file_writer.py index 6bbcf637f..76d84a549 100644 --- a/src/spdx/writer/rdf/file_writer.py +++ b/src/spdx/writer/rdf/file_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict diff --git a/src/spdx/writer/rdf/license_expression_writer.py b/src/spdx/writer/rdf/license_expression_writer.py index a6e230a41..d12c992b8 100644 --- a/src/spdx/writer/rdf/license_expression_writer.py +++ b/src/spdx/writer/rdf/license_expression_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Union diff --git a/src/spdx/writer/rdf/package_writer.py b/src/spdx/writer/rdf/package_writer.py index 83db8e11a..914201ea5 100644 --- a/src/spdx/writer/rdf/package_writer.py +++ b/src/spdx/writer/rdf/package_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict diff --git a/src/spdx/writer/rdf/rdf_writer.py b/src/spdx/writer/rdf/rdf_writer.py index fb6aeed1d..0e07a5818 100644 --- a/src/spdx/writer/rdf/rdf_writer.py +++ b/src/spdx/writer/rdf/rdf_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict, List diff --git a/src/spdx/writer/rdf/relationship_writer.py b/src/spdx/writer/rdf/relationship_writer.py index 9435ee433..585ccdfcc 100644 --- a/src/spdx/writer/rdf/relationship_writer.py +++ b/src/spdx/writer/rdf/relationship_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict diff --git a/src/spdx/writer/rdf/snippet_writer.py b/src/spdx/writer/rdf/snippet_writer.py index d4c8e7024..c15304254 100644 --- a/src/spdx/writer/rdf/snippet_writer.py +++ b/src/spdx/writer/rdf/snippet_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict, Optional, Tuple diff --git a/src/spdx/writer/rdf/writer_utils.py b/src/spdx/writer/rdf/writer_utils.py index 6e18ccf44..f80173fbb 100644 --- a/src/spdx/writer/rdf/writer_utils.py +++ b/src/spdx/writer/rdf/writer_utils.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import logging from datetime import datetime diff --git a/src/spdx/writer/write_anything.py b/src/spdx/writer/write_anything.py index 7e97654eb..06ca4aa11 100644 --- a/src/spdx/writer/write_anything.py +++ b/src/spdx/writer/write_anything.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from spdx.formats import FileFormat, file_name_to_format from spdx.model.document import Document diff --git a/src/spdx/writer/xml/xml_writer.py b/src/spdx/writer/xml/xml_writer.py index 0bc6a47aa..678010183 100644 --- a/src/spdx/writer/xml/xml_writer.py +++ b/src/spdx/writer/xml/xml_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx/writer/yaml/yaml_writer.py b/src/spdx/writer/yaml/yaml_writer.py index 7a9536816..de3e27571 100644 --- a/src/spdx/writer/yaml/yaml_writer.py +++ b/src/spdx/writer/yaml/yaml_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/fixtures.py b/tests/spdx/fixtures.py index d8588214e..7800221e7 100644 --- a/tests/spdx/fixtures.py +++ b/tests/spdx/fixtures.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime diff --git a/tests/spdx/jsonschema/test_annotation_converter.py b/tests/spdx/jsonschema/test_annotation_converter.py index 61facc040..885e1e07b 100644 --- a/tests/spdx/jsonschema/test_annotation_converter.py +++ b/tests/spdx/jsonschema/test_annotation_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime diff --git a/tests/spdx/jsonschema/test_checksum_converter.py b/tests/spdx/jsonschema/test_checksum_converter.py index 5808a0682..320082582 100644 --- a/tests/spdx/jsonschema/test_checksum_converter.py +++ b/tests/spdx/jsonschema/test_checksum_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/jsonschema/test_converter.py b/tests/spdx/jsonschema/test_converter.py index f5bae70a4..d5edeb647 100644 --- a/tests/spdx/jsonschema/test_converter.py +++ b/tests/spdx/jsonschema/test_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import auto from typing import Any, Type diff --git a/tests/spdx/jsonschema/test_creation_info_converter.py b/tests/spdx/jsonschema/test_creation_info_converter.py index 5921d911f..673a4c871 100644 --- a/tests/spdx/jsonschema/test_creation_info_converter.py +++ b/tests/spdx/jsonschema/test_creation_info_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime diff --git a/tests/spdx/jsonschema/test_document_converter.py b/tests/spdx/jsonschema/test_document_converter.py index 7bb1d5ac5..149eca9ac 100644 --- a/tests/spdx/jsonschema/test_document_converter.py +++ b/tests/spdx/jsonschema/test_document_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Union diff --git a/tests/spdx/jsonschema/test_external_document_ref_converter.py b/tests/spdx/jsonschema/test_external_document_ref_converter.py index a6437d604..f3a1d3743 100644 --- a/tests/spdx/jsonschema/test_external_document_ref_converter.py +++ b/tests/spdx/jsonschema/test_external_document_ref_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock from unittest.mock import MagicMock diff --git a/tests/spdx/jsonschema/test_external_package_ref_converter.py b/tests/spdx/jsonschema/test_external_package_ref_converter.py index 016aa75c4..7f9e6cb4f 100644 --- a/tests/spdx/jsonschema/test_external_package_ref_converter.py +++ b/tests/spdx/jsonschema/test_external_package_ref_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py index 19324e961..518ad2ab5 100644 --- a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py +++ b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/jsonschema/test_file_converter.py b/tests/spdx/jsonschema/test_file_converter.py index 076ecdd90..12cd3c22c 100644 --- a/tests/spdx/jsonschema/test_file_converter.py +++ b/tests/spdx/jsonschema/test_file_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Union diff --git a/tests/spdx/jsonschema/test_package_converter.py b/tests/spdx/jsonschema/test_package_converter.py index bff476822..cb8466ed8 100644 --- a/tests/spdx/jsonschema/test_package_converter.py +++ b/tests/spdx/jsonschema/test_package_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Union diff --git a/tests/spdx/jsonschema/test_package_verification_code_converter.py b/tests/spdx/jsonschema/test_package_verification_code_converter.py index e506676a6..c63b6829a 100644 --- a/tests/spdx/jsonschema/test_package_verification_code_converter.py +++ b/tests/spdx/jsonschema/test_package_verification_code_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/jsonschema/test_relationship_converter.py b/tests/spdx/jsonschema/test_relationship_converter.py index 2b78bf9e4..9b71fac27 100644 --- a/tests/spdx/jsonschema/test_relationship_converter.py +++ b/tests/spdx/jsonschema/test_relationship_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/jsonschema/test_snippet_converter.py b/tests/spdx/jsonschema/test_snippet_converter.py index baceeffbd..ca59e201b 100644 --- a/tests/spdx/jsonschema/test_snippet_converter.py +++ b/tests/spdx/jsonschema/test_snippet_converter.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import Union diff --git a/tests/spdx/mock_utils.py b/tests/spdx/mock_utils.py index 075b51117..6bea46ffa 100644 --- a/tests/spdx/mock_utils.py +++ b/tests/spdx/mock_utils.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest.mock import NonCallableMagicMock diff --git a/tests/spdx/model/test_actor.py b/tests/spdx/model/test_actor.py index ff8398ebf..431e1434f 100644 --- a/tests/spdx/model/test_actor.py +++ b/tests/spdx/model/test_actor.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + import pytest from spdx.model.actor import Actor, ActorType diff --git a/tests/spdx/model/test_annotation.py b/tests/spdx/model/test_annotation.py index 1caab2ccb..6b2410968 100644 --- a/tests/spdx/model/test_annotation.py +++ b/tests/spdx/model/test_annotation.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + from datetime import datetime from unittest import mock diff --git a/tests/spdx/model/test_checksum.py b/tests/spdx/model/test_checksum.py index 8b1c3e43b..d555180c5 100644 --- a/tests/spdx/model/test_checksum.py +++ b/tests/spdx/model/test_checksum.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + import pytest from spdx.model.checksum import Checksum, ChecksumAlgorithm diff --git a/tests/spdx/model/test_creation_info.py b/tests/spdx/model/test_creation_info.py index 0d7213135..4d544de11 100644 --- a/tests/spdx/model/test_creation_info.py +++ b/tests/spdx/model/test_creation_info.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + from datetime import datetime from unittest import mock diff --git a/tests/spdx/model/test_document.py b/tests/spdx/model/test_document.py index 35fa3f176..8043ab3cf 100644 --- a/tests/spdx/model/test_document.py +++ b/tests/spdx/model/test_document.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + from unittest import mock import pytest diff --git a/tests/spdx/model/test_external_document_ref.py b/tests/spdx/model/test_external_document_ref.py index 28c2829cf..befd2d95b 100644 --- a/tests/spdx/model/test_external_document_ref.py +++ b/tests/spdx/model/test_external_document_ref.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + from unittest import mock import pytest diff --git a/tests/spdx/model/test_external_package_reference.py b/tests/spdx/model/test_external_package_reference.py index 74027bd9f..adfb2b356 100644 --- a/tests/spdx/model/test_external_package_reference.py +++ b/tests/spdx/model/test_external_package_reference.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + import pytest from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory diff --git a/tests/spdx/model/test_extracted_licensing_info.py b/tests/spdx/model/test_extracted_licensing_info.py index cefba997a..72f2cf76d 100644 --- a/tests/spdx/model/test_extracted_licensing_info.py +++ b/tests/spdx/model/test_extracted_licensing_info.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + import pytest from spdx.model.extracted_licensing_info import ExtractedLicensingInfo diff --git a/tests/spdx/model/test_file.py b/tests/spdx/model/test_file.py index d6ea58e74..c8fd79520 100644 --- a/tests/spdx/model/test_file.py +++ b/tests/spdx/model/test_file.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + from unittest import mock import pytest diff --git a/tests/spdx/model/test_package.py b/tests/spdx/model/test_package.py index 193924df2..e6a5eeec7 100644 --- a/tests/spdx/model/test_package.py +++ b/tests/spdx/model/test_package.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + from datetime import datetime from unittest import mock diff --git a/tests/spdx/model/test_package_verification_code.py b/tests/spdx/model/test_package_verification_code.py index 2afe5c434..8f81152b4 100644 --- a/tests/spdx/model/test_package_verification_code.py +++ b/tests/spdx/model/test_package_verification_code.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + import pytest from spdx.model.package import PackageVerificationCode diff --git a/tests/spdx/model/test_relationship.py b/tests/spdx/model/test_relationship.py index 0413729ed..7fa813631 100644 --- a/tests/spdx/model/test_relationship.py +++ b/tests/spdx/model/test_relationship.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + import pytest from spdx.model.relationship import Relationship, RelationshipType diff --git a/tests/spdx/model/test_snippet.py b/tests/spdx/model/test_snippet.py index 8b5d3b556..8f6bd8483 100644 --- a/tests/spdx/model/test_snippet.py +++ b/tests/spdx/model/test_snippet.py @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + import pytest from spdx.model.snippet import Snippet diff --git a/tests/spdx/model/test_version.py b/tests/spdx/model/test_version.py index ab6a719d1..310dcf7fd 100644 --- a/tests/spdx/model/test_version.py +++ b/tests/spdx/model/test_version.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 - import pytest from spdx.model.version import Version diff --git a/tests/spdx/parser/json/test_json_parser.py b/tests/spdx/parser/json/test_json_parser.py index e14fb510c..ac3fb684b 100644 --- a/tests/spdx/parser/json/test_json_parser.py +++ b/tests/spdx/parser/json/test_json_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os diff --git a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py index ed7af5334..13ed71ca9 100644 --- a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import datetime from unittest import TestCase diff --git a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py index a64289b48..bdb0de3e9 100644 --- a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import TestCase diff --git a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py index aab81b3cc..e60d9ff3e 100644 --- a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from unittest import TestCase diff --git a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py index 66babca5d..7fe85d33a 100644 --- a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py +++ b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 from unittest import TestCase import pytest diff --git a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py index 71d25f325..859f1bf04 100644 --- a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import TestCase diff --git a/tests/spdx/parser/jsonlikedict/test_file_parser.py b/tests/spdx/parser/jsonlikedict/test_file_parser.py index b784d096a..e99c039ed 100644 --- a/tests/spdx/parser/jsonlikedict/test_file_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_file_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import TestCase diff --git a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py index 2bb9a7899..26dbbc21b 100644 --- a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import TestCase diff --git a/tests/spdx/parser/jsonlikedict/test_package_parser.py b/tests/spdx/parser/jsonlikedict/test_package_parser.py index d2b41ffde..00cecbdb4 100644 --- a/tests/spdx/parser/jsonlikedict/test_package_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_package_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from unittest import TestCase diff --git a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py index 464c39f02..8a77e64b5 100644 --- a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import TestCase diff --git a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py index cdf96de14..10b0fb232 100644 --- a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import TestCase diff --git a/tests/spdx/parser/rdf/test_annotation_parser.py b/tests/spdx/parser/rdf/test_annotation_parser.py index de8a956bb..ed9978394 100644 --- a/tests/spdx/parser/rdf/test_annotation_parser.py +++ b/tests/spdx/parser/rdf/test_annotation_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os from datetime import datetime diff --git a/tests/spdx/parser/rdf/test_checksum_parser.py b/tests/spdx/parser/rdf/test_checksum_parser.py index add7e4155..028b3f20c 100644 --- a/tests/spdx/parser/rdf/test_checksum_parser.py +++ b/tests/spdx/parser/rdf/test_checksum_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os diff --git a/tests/spdx/parser/rdf/test_creation_info_parser.py b/tests/spdx/parser/rdf/test_creation_info_parser.py index 696dd7c06..04ac5e801 100644 --- a/tests/spdx/parser/rdf/test_creation_info_parser.py +++ b/tests/spdx/parser/rdf/test_creation_info_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os from datetime import datetime diff --git a/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py b/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py index c57f1aada..8b3977868 100644 --- a/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py index acc40aea4..6e962bc3d 100644 --- a/tests/spdx/parser/rdf/test_file_parser.py +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os from unittest import TestCase diff --git a/tests/spdx/parser/rdf/test_graph_parsing_function.py b/tests/spdx/parser/rdf/test_graph_parsing_function.py index db9fa1d69..61326fa0d 100644 --- a/tests/spdx/parser/rdf/test_graph_parsing_function.py +++ b/tests/spdx/parser/rdf/test_graph_parsing_function.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest from rdflib import Graph, Namespace, URIRef diff --git a/tests/spdx/parser/rdf/test_license_expression_parser.py b/tests/spdx/parser/rdf/test_license_expression_parser.py index 6124d3bfe..74875eefb 100644 --- a/tests/spdx/parser/rdf/test_license_expression_parser.py +++ b/tests/spdx/parser/rdf/test_license_expression_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os from unittest import TestCase diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index 2410c15d9..dacdce56b 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os from unittest import TestCase diff --git a/tests/spdx/parser/rdf/test_rdf_parser.py b/tests/spdx/parser/rdf/test_rdf_parser.py index 1faf0dcd0..9c75c68d4 100644 --- a/tests/spdx/parser/rdf/test_rdf_parser.py +++ b/tests/spdx/parser/rdf/test_rdf_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os diff --git a/tests/spdx/parser/rdf/test_relationship_parser.py b/tests/spdx/parser/rdf/test_relationship_parser.py index e3a7ae2ed..5be3ae88a 100644 --- a/tests/spdx/parser/rdf/test_relationship_parser.py +++ b/tests/spdx/parser/rdf/test_relationship_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index 2f33d22b1..5c975798c 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os from unittest import TestCase diff --git a/tests/spdx/parser/tagvalue/test_annotation_parser.py b/tests/spdx/parser/tagvalue/test_annotation_parser.py index 91bf81497..2a0392295 100644 --- a/tests/spdx/parser/tagvalue/test_annotation_parser.py +++ b/tests/spdx/parser/tagvalue/test_annotation_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime diff --git a/tests/spdx/parser/tagvalue/test_creation_info_parser.py b/tests/spdx/parser/tagvalue/test_creation_info_parser.py index bab2e5e11..4fb1993fa 100644 --- a/tests/spdx/parser/tagvalue/test_creation_info_parser.py +++ b/tests/spdx/parser/tagvalue/test_creation_info_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from unittest import TestCase diff --git a/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py b/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py index 617ecbae5..e272a2992 100644 --- a/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import TestCase diff --git a/tests/spdx/parser/tagvalue/test_file_parser.py b/tests/spdx/parser/tagvalue/test_file_parser.py index eeffaf6dd..18b0c5091 100644 --- a/tests/spdx/parser/tagvalue/test_file_parser.py +++ b/tests/spdx/parser/tagvalue/test_file_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest from license_expression import get_spdx_licensing diff --git a/tests/spdx/parser/tagvalue/test_helper_methods.py b/tests/spdx/parser/tagvalue/test_helper_methods.py index 9d384e8f7..27e7ea7c8 100644 --- a/tests/spdx/parser/tagvalue/test_helper_methods.py +++ b/tests/spdx/parser/tagvalue/test_helper_methods.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/parser/tagvalue/test_package_parser.py b/tests/spdx/parser/tagvalue/test_package_parser.py index fd4518b3d..dea9851d7 100644 --- a/tests/spdx/parser/tagvalue/test_package_parser.py +++ b/tests/spdx/parser/tagvalue/test_package_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from unittest import TestCase diff --git a/tests/spdx/parser/tagvalue/test_relationship_parser.py b/tests/spdx/parser/tagvalue/test_relationship_parser.py index 857166ed5..83a3d19d5 100644 --- a/tests/spdx/parser/tagvalue/test_relationship_parser.py +++ b/tests/spdx/parser/tagvalue/test_relationship_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/parser/tagvalue/test_snippet_parser.py b/tests/spdx/parser/tagvalue/test_snippet_parser.py index 271ebead9..de4af17a9 100644 --- a/tests/spdx/parser/tagvalue/test_snippet_parser.py +++ b/tests/spdx/parser/tagvalue/test_snippet_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import TestCase diff --git a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py index 6792316fd..6170062c5 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py @@ -1,6 +1,6 @@ # Copyright (c) 2014 Ahmed H. Ismail # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/parser/tagvalue/test_tag_value_parser.py b/tests/spdx/parser/tagvalue/test_tag_value_parser.py index d9c50c901..47778d2df 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_parser.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_parser.py @@ -1,6 +1,6 @@ # Copyright (c) 2014 Ahmed H. Ismail # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os diff --git a/tests/spdx/test_actor_parser.py b/tests/spdx/test_actor_parser.py index 0dfe56081..fda13d4ba 100644 --- a/tests/spdx/test_actor_parser.py +++ b/tests/spdx/test_actor_parser.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import TestCase diff --git a/tests/spdx/test_casing_tools.py b/tests/spdx/test_casing_tools.py index 77c19f977..78da1a9cb 100644 --- a/tests/spdx/test_casing_tools.py +++ b/tests/spdx/test_casing_tools.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/test_datetime_conversions.py b/tests/spdx/test_datetime_conversions.py index db1df249e..184ef8ab1 100644 --- a/tests/spdx/test_datetime_conversions.py +++ b/tests/spdx/test_datetime_conversions.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime diff --git a/tests/spdx/test_document_utils.py b/tests/spdx/test_document_utils.py index 4c69f229d..873af1a1a 100644 --- a/tests/spdx/test_document_utils.py +++ b/tests/spdx/test_document_utils.py @@ -1,6 +1,6 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors +# SPDX-FileCopyrightText: 2023 spdx contributors # -# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 from unittest import TestCase import pytest diff --git a/tests/spdx/validation/test_actor_validator.py b/tests/spdx/validation/test_actor_validator.py index 78227da70..313efa809 100644 --- a/tests/spdx/validation/test_actor_validator.py +++ b/tests/spdx/validation/test_actor_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_annotation_validator.py b/tests/spdx/validation/test_annotation_validator.py index d04c7d1c2..eeb473264 100644 --- a/tests/spdx/validation/test_annotation_validator.py +++ b/tests/spdx/validation/test_annotation_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_checksum_validator.py b/tests/spdx/validation/test_checksum_validator.py index 6217f859a..1112774b2 100644 --- a/tests/spdx/validation/test_checksum_validator.py +++ b/tests/spdx/validation/test_checksum_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_creation_info_validator.py b/tests/spdx/validation/test_creation_info_validator.py index a67ca5c45..2b4a65d5f 100644 --- a/tests/spdx/validation/test_creation_info_validator.py +++ b/tests/spdx/validation/test_creation_info_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_document_validator.py b/tests/spdx/validation/test_document_validator.py index d242a52c6..6d829db79 100644 --- a/tests/spdx/validation/test_document_validator.py +++ b/tests/spdx/validation/test_document_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/tests/spdx/validation/test_external_document_ref_validator.py b/tests/spdx/validation/test_external_document_ref_validator.py index 8402c070d..2e31beeb3 100644 --- a/tests/spdx/validation/test_external_document_ref_validator.py +++ b/tests/spdx/validation/test_external_document_ref_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_external_package_ref_validator.py b/tests/spdx/validation/test_external_package_ref_validator.py index 2e509c603..644496ffa 100644 --- a/tests/spdx/validation/test_external_package_ref_validator.py +++ b/tests/spdx/validation/test_external_package_ref_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_extracted_licensing_info_validator.py b/tests/spdx/validation/test_extracted_licensing_info_validator.py index 19fb0875f..f0057fbf3 100644 --- a/tests/spdx/validation/test_extracted_licensing_info_validator.py +++ b/tests/spdx/validation/test_extracted_licensing_info_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_file_validator.py b/tests/spdx/validation/test_file_validator.py index 210b23987..954b0285a 100644 --- a/tests/spdx/validation/test_file_validator.py +++ b/tests/spdx/validation/test_file_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_license_expression_validator.py b/tests/spdx/validation/test_license_expression_validator.py index 48cb1f31a..071d49d59 100644 --- a/tests/spdx/validation/test_license_expression_validator.py +++ b/tests/spdx/validation/test_license_expression_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_package_validator.py b/tests/spdx/validation/test_package_validator.py index aeee350c9..5ebca4672 100644 --- a/tests/spdx/validation/test_package_validator.py +++ b/tests/spdx/validation/test_package_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_package_verification_code_validator.py b/tests/spdx/validation/test_package_verification_code_validator.py index ca59c074a..a19415b14 100644 --- a/tests/spdx/validation/test_package_verification_code_validator.py +++ b/tests/spdx/validation/test_package_verification_code_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/validation/test_relationship_validator.py b/tests/spdx/validation/test_relationship_validator.py index a208be609..1d5a493c7 100644 --- a/tests/spdx/validation/test_relationship_validator.py +++ b/tests/spdx/validation/test_relationship_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_snippet_validator.py b/tests/spdx/validation/test_snippet_validator.py index 8b25d01ee..b13f6f011 100644 --- a/tests/spdx/validation/test_snippet_validator.py +++ b/tests/spdx/validation/test_snippet_validator.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/tests/spdx/validation/test_spdx_id_validators.py b/tests/spdx/validation/test_spdx_id_validators.py index a32e46acd..12696a4de 100644 --- a/tests/spdx/validation/test_spdx_id_validators.py +++ b/tests/spdx/validation/test_spdx_id_validators.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import TestCase diff --git a/tests/spdx/validation/test_uri_validators.py b/tests/spdx/validation/test_uri_validators.py index 119be756a..3aaf75475 100644 --- a/tests/spdx/validation/test_uri_validators.py +++ b/tests/spdx/validation/test_uri_validators.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/writer/json/test_json_writer.py b/tests/spdx/writer/json/test_json_writer.py index 432498abd..d17484e04 100644 --- a/tests/spdx/writer/json/test_json_writer.py +++ b/tests/spdx/writer/json/test_json_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2022 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import json import os diff --git a/tests/spdx/writer/rdf/test_annotation_writer.py b/tests/spdx/writer/rdf/test_annotation_writer.py index 6ac4e2f15..fc0238761 100644 --- a/tests/spdx/writer/rdf/test_annotation_writer.py +++ b/tests/spdx/writer/rdf/test_annotation_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, Graph, Literal, URIRef diff --git a/tests/spdx/writer/rdf/test_checksum_writer.py b/tests/spdx/writer/rdf/test_checksum_writer.py index 38451242c..b768cf19c 100644 --- a/tests/spdx/writer/rdf/test_checksum_writer.py +++ b/tests/spdx/writer/rdf/test_checksum_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest from rdflib import RDF, Graph, Literal, URIRef diff --git a/tests/spdx/writer/rdf/test_creation_info_writer.py b/tests/spdx/writer/rdf/test_creation_info_writer.py index 310903677..2ad508e34 100644 --- a/tests/spdx/writer/rdf/test_creation_info_writer.py +++ b/tests/spdx/writer/rdf/test_creation_info_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, Graph, Literal, URIRef diff --git a/tests/spdx/writer/rdf/test_external_document_ref_writer.py b/tests/spdx/writer/rdf/test_external_document_ref_writer.py index 6a8ddc4e7..718de8483 100644 --- a/tests/spdx/writer/rdf/test_external_document_ref_writer.py +++ b/tests/spdx/writer/rdf/test_external_document_ref_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, Graph, URIRef diff --git a/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py b/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py index 0dd2df95c..c763bcec4 100644 --- a/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py +++ b/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, Graph, Literal, URIRef diff --git a/tests/spdx/writer/rdf/test_file_writer.py b/tests/spdx/writer/rdf/test_file_writer.py index 17092c457..bb05e8656 100644 --- a/tests/spdx/writer/rdf/test_file_writer.py +++ b/tests/spdx/writer/rdf/test_file_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, Graph, Literal, URIRef diff --git a/tests/spdx/writer/rdf/test_license_expression_writer.py b/tests/spdx/writer/rdf/test_license_expression_writer.py index f90022cb1..ff9b7bd71 100644 --- a/tests/spdx/writer/rdf/test_license_expression_writer.py +++ b/tests/spdx/writer/rdf/test_license_expression_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest from license_expression import get_spdx_licensing diff --git a/tests/spdx/writer/rdf/test_package_writer.py b/tests/spdx/writer/rdf/test_package_writer.py index 6fd86351b..856b38906 100644 --- a/tests/spdx/writer/rdf/test_package_writer.py +++ b/tests/spdx/writer/rdf/test_package_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest from rdflib import DOAP, RDF, RDFS, XSD, Graph, Literal, URIRef diff --git a/tests/spdx/writer/rdf/test_rdf_writer.py b/tests/spdx/writer/rdf/test_rdf_writer.py index d3fb42380..45cc7dc45 100644 --- a/tests/spdx/writer/rdf/test_rdf_writer.py +++ b/tests/spdx/writer/rdf/test_rdf_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import os diff --git a/tests/spdx/writer/rdf/test_relationship_writer.py b/tests/spdx/writer/rdf/test_relationship_writer.py index 3c208b7c3..483f0cbca 100644 --- a/tests/spdx/writer/rdf/test_relationship_writer.py +++ b/tests/spdx/writer/rdf/test_relationship_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, Literal, URIRef diff --git a/tests/spdx/writer/rdf/test_snippet_writer.py b/tests/spdx/writer/rdf/test_snippet_writer.py index 9f6343876..1fad0e46e 100644 --- a/tests/spdx/writer/rdf/test_snippet_writer.py +++ b/tests/spdx/writer/rdf/test_snippet_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest from rdflib import RDF, RDFS, Graph, Literal, URIRef diff --git a/tests/spdx/writer/rdf/test_writer_utils.py b/tests/spdx/writer/rdf/test_writer_utils.py index dd9978b3f..f26f56eee 100644 --- a/tests/spdx/writer/rdf/test_writer_utils.py +++ b/tests/spdx/writer/rdf/test_writer_utils.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx/writer/tagvalue/test_package_writer.py b/tests/spdx/writer/tagvalue/test_package_writer.py index ec5366617..8cb492b34 100644 --- a/tests/spdx/writer/tagvalue/test_package_writer.py +++ b/tests/spdx/writer/tagvalue/test_package_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 from unittest.mock import MagicMock, call, mock_open, patch from spdx.writer.tagvalue.package_writer import write_package diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py index bdb442303..b6d3b4ece 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 import os diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py index a1bb05f9d..b6b36a81a 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 from spdx.model.relationship import RelationshipType from spdx.writer.tagvalue.tagvalue_writer_helper_functions import scan_relationships from tests.spdx.fixtures import file_fixture, package_fixture, relationship_fixture From 0e2220479573b99d27d648c31213a2e8b2b4aedc Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 4 Apr 2023 10:16:43 +0200 Subject: [PATCH 039/354] [issue-561] fix rdf parser: add logic to parse implicit "hasFiles" and "describesPackage" relationships Signed-off-by: Meret Behrens --- src/spdx/parser/rdf/rdf_parser.py | 22 ++++++++- src/spdx/parser/rdf/relationship_parser.py | 20 ++++++++ .../rdf/data/file_to_test_rdf_parser.rdf.xml | 49 ++++++++++--------- tests/spdx/parser/rdf/test_rdf_parser.py | 2 +- .../parser/rdf/test_relationship_parser.py | 36 +++++++++++++- 5 files changed, 102 insertions(+), 27 deletions(-) diff --git a/src/spdx/parser/rdf/rdf_parser.py b/src/spdx/parser/rdf/rdf_parser.py index d3726f436..cbd77b255 100644 --- a/src/spdx/parser/rdf/rdf_parser.py +++ b/src/spdx/parser/rdf/rdf_parser.py @@ -1,9 +1,12 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from typing import Any, Dict + from rdflib import RDF, Graph from spdx.model.document import Document +from spdx.model.relationship import RelationshipType from spdx.parser.error import SPDXParsingError from spdx.parser.logger import Logger from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages @@ -12,7 +15,7 @@ from spdx.parser.rdf.extracted_licensing_info_parser import parse_extracted_licensing_info from spdx.parser.rdf.file_parser import parse_file from spdx.parser.rdf.package_parser import parse_package -from spdx.parser.rdf.relationship_parser import parse_relationship +from spdx.parser.rdf.relationship_parser import parse_implicit_relationship, parse_relationship from spdx.parser.rdf.snippet_parser import parse_snippet from spdx.rdfschema.namespace import SPDX_NAMESPACE @@ -27,7 +30,7 @@ def parse_from_file(file_name: str) -> Document: def translate_graph_to_document(graph: Graph) -> Document: - parsed_fields = dict() + parsed_fields: Dict[str, Any] = dict() logger = Logger() try: creation_info, doc_node = parse_creation_info(graph) @@ -62,6 +65,21 @@ def translate_graph_to_document(graph: Graph) -> Document: logger.extend(err.get_messages()) parsed_fields[element] = elements + for triple, relationship_type in [ + ((None, SPDX_NAMESPACE.hasFile, None), RelationshipType.CONTAINS), + ((None, SPDX_NAMESPACE.describesPackage, None), RelationshipType.DESCRIBES), + ]: + for parent_node, _, element_node in graph.triples(triple): + try: + relationship = parse_implicit_relationship( + parent_node, relationship_type, element_node, graph, creation_info.document_namespace + ) + if relationship not in parsed_fields["relationships"]: + parsed_fields["relationships"].append(relationship) + + except SPDXParsingError as err: + logger.extend(err.get_messages()) + extracted_licensing_infos = [] for _, _, extracted_licensing_info_node in graph.triples((None, SPDX_NAMESPACE.hasExtractedLicensingInfo, None)): try: diff --git a/src/spdx/parser/rdf/relationship_parser.py b/src/spdx/parser/rdf/relationship_parser.py index 956b19177..cdd61e5ee 100644 --- a/src/spdx/parser/rdf/relationship_parser.py +++ b/src/spdx/parser/rdf/relationship_parser.py @@ -49,3 +49,23 @@ def parse_relationship( ) return relationship + + +def parse_implicit_relationship( + spdx_element_node: URIRef, + relationship_type: RelationshipType, + related_spdx_element_node: URIRef, + graph: Graph, + doc_namespace: str, +) -> Relationship: + spdx_element_id = parse_spdx_id(spdx_element_node, doc_namespace, graph) + related_spdx_element_id = parse_spdx_id(related_spdx_element_node, doc_namespace, graph) + relationship = construct_or_raise_parsing_error( + Relationship, + dict( + spdx_element_id=spdx_element_id, + relationship_type=relationship_type, + related_spdx_element_id=related_spdx_element_id, + ), + ) + return relationship diff --git a/tests/spdx/parser/rdf/data/file_to_test_rdf_parser.rdf.xml b/tests/spdx/parser/rdf/data/file_to_test_rdf_parser.rdf.xml index 2320ff440..b8843af02 100644 --- a/tests/spdx/parser/rdf/data/file_to_test_rdf_parser.rdf.xml +++ b/tests/spdx/parser/rdf/data/file_to_test_rdf_parser.rdf.xml @@ -80,8 +80,8 @@ - - + + @@ -137,27 +137,32 @@ externalPackageRefComment + - - packageName - http://differentdownload.com - - - - This is the external ref for Acme - acmecorp/acmenator/4.1.3-alpha - - - - - - https://see.also - extractedText - licenseComment - another license - - - + + + + packageName + http://differentdownload.com + + + + This is the external ref for Acme + acmecorp/acmenator/4.1.3-alpha + + + + + + https://see.also + extractedText + licenseComment + another license + + + + + diff --git a/tests/spdx/parser/rdf/test_rdf_parser.py b/tests/spdx/parser/rdf/test_rdf_parser.py index 9c75c68d4..ca1233c15 100644 --- a/tests/spdx/parser/rdf/test_rdf_parser.py +++ b/tests/spdx/parser/rdf/test_rdf_parser.py @@ -44,5 +44,5 @@ def test_rdf_parser_with_2_2_example(): assert len(doc.files) == 4 assert len(doc.annotations) == 5 assert len(doc.packages) == 4 - assert len(doc.relationships) == 9 + assert len(doc.relationships) == 11 assert len(doc.extracted_licensing_info) == 5 diff --git a/tests/spdx/parser/rdf/test_relationship_parser.py b/tests/spdx/parser/rdf/test_relationship_parser.py index 5be3ae88a..53935f06d 100644 --- a/tests/spdx/parser/rdf/test_relationship_parser.py +++ b/tests/spdx/parser/rdf/test_relationship_parser.py @@ -3,10 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 import os -from rdflib import RDF, Graph +import pytest +from rdflib import RDF, Graph, URIRef from spdx.model.relationship import RelationshipType -from spdx.parser.rdf.relationship_parser import parse_relationship +from spdx.parser.rdf.relationship_parser import parse_implicit_relationship, parse_relationship from spdx.rdfschema.namespace import SPDX_NAMESPACE @@ -22,3 +23,34 @@ def test_relationship_parser(): assert relationship.relationship_type == RelationshipType.DESCRIBES assert relationship.related_spdx_element_id == "SPDXRef-File" assert relationship.comment == "relationshipComment" + + +@pytest.mark.parametrize( + "parent_node, predicate, spdx_element_id, relationship_type, related_spdx_element_id", + [ + ( + SPDX_NAMESPACE.SpdxDocument, + SPDX_NAMESPACE.describesPackage, + "SPDXRef-DOCUMENT", + RelationshipType.DESCRIBES, + "SPDXRef-Package", + ), + (SPDX_NAMESPACE.Package, SPDX_NAMESPACE.hasFile, "SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File"), + ], +) +def test_parse_implicit_relationship( + parent_node, predicate, spdx_element_id, relationship_type, related_spdx_element_id +): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) + parent_node = graph.value(predicate=RDF.type, object=parent_node) + relationship_node = graph.value(subject=parent_node, predicate=predicate) + assert isinstance(relationship_node, URIRef) + assert isinstance(parent_node, URIRef) + + doc_namespace = "https://some.namespace" + + relationship = parse_implicit_relationship(parent_node, relationship_type, relationship_node, graph, doc_namespace) + + assert relationship.spdx_element_id == spdx_element_id + assert relationship.relationship_type == relationship_type + assert relationship.related_spdx_element_id == related_spdx_element_id From 9d824c8066d4f1bcb8cb35501d7f72e7cc279662 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 5 Apr 2023 09:07:06 +0200 Subject: [PATCH 040/354] add wrapper methods to ensure correct types in rdf parser Signed-off-by: Meret Behrens --- src/spdx/parser/rdf/annotation_parser.py | 4 +- src/spdx/parser/rdf/checksum_parser.py | 4 +- src/spdx/parser/rdf/creation_info_parser.py | 19 +++++-- .../rdf/extracted_licensing_info_parser.py | 10 +++- src/spdx/parser/rdf/file_parser.py | 17 +++++-- .../parser/rdf/graph_parsing_functions.py | 49 +++++++++++++++++-- .../parser/rdf/license_expression_parser.py | 26 ++++++---- src/spdx/parser/rdf/package_parser.py | 23 ++++++--- src/spdx/parser/rdf/rdf_parser.py | 9 ++-- src/spdx/parser/rdf/relationship_parser.py | 5 +- src/spdx/parser/rdf/snippet_parser.py | 28 +++++++---- .../spdx/parser/rdf/test_annotation_parser.py | 3 +- tests/spdx/parser/rdf/test_checksum_parser.py | 3 +- .../parser/rdf/test_creation_info_parser.py | 1 + tests/spdx/parser/rdf/test_file_parser.py | 3 +- tests/spdx/parser/rdf/test_package_parser.py | 4 +- .../parser/rdf/test_relationship_parser.py | 1 + tests/spdx/parser/rdf/test_snippet_parser.py | 15 ++++-- 18 files changed, 165 insertions(+), 59 deletions(-) diff --git a/src/spdx/parser/rdf/annotation_parser.py b/src/spdx/parser/rdf/annotation_parser.py index e75aa7b80..26544de3f 100644 --- a/src/spdx/parser/rdf/annotation_parser.py +++ b/src/spdx/parser/rdf/annotation_parser.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from rdflib import RDFS, Graph, URIRef +from rdflib import RDFS, BNode, Graph, URIRef from spdx.datetime_conversions import datetime_from_str from spdx.model.annotation import Annotation, AnnotationType @@ -12,7 +12,7 @@ from spdx.rdfschema.namespace import SPDX_NAMESPACE -def parse_annotation(annotation_node: URIRef, graph: Graph, parent_node: URIRef, doc_namespace: str) -> Annotation: +def parse_annotation(annotation_node: BNode, graph: Graph, parent_node: URIRef, doc_namespace: str) -> Annotation: logger = Logger() spdx_id = parse_spdx_id(parent_node, doc_namespace, graph) annotator = parse_literal( diff --git a/src/spdx/parser/rdf/checksum_parser.py b/src/spdx/parser/rdf/checksum_parser.py index 456e709cb..d2bad6e7d 100644 --- a/src/spdx/parser/rdf/checksum_parser.py +++ b/src/spdx/parser/rdf/checksum_parser.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from rdflib import Graph, URIRef +from rdflib import BNode, Graph from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.parser.error import SPDXParsingError @@ -11,7 +11,7 @@ from spdx.rdfschema.namespace import SPDX_NAMESPACE -def parse_checksum(parent_node: URIRef, graph: Graph) -> Checksum: +def parse_checksum(parent_node: BNode, graph: Graph) -> Checksum: logger = Logger() algorithm = parse_literal( logger, graph, parent_node, SPDX_NAMESPACE.algorithm, parsing_method=convert_rdf_to_algorithm diff --git a/src/spdx/parser/rdf/creation_info_parser.py b/src/spdx/parser/rdf/creation_info_parser.py index eeb1e1d31..3e11589fa 100644 --- a/src/spdx/parser/rdf/creation_info_parser.py +++ b/src/spdx/parser/rdf/creation_info_parser.py @@ -19,7 +19,12 @@ from spdx.parser.logger import Logger from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages from spdx.parser.rdf.checksum_parser import parse_checksum -from spdx.parser.rdf.graph_parsing_functions import parse_literal, parse_spdx_id, remove_prefix +from spdx.parser.rdf.graph_parsing_functions import ( + get_correctly_typed_triples, + parse_literal, + parse_spdx_id, + remove_prefix, +) from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE @@ -50,10 +55,14 @@ def parse_creation_info(graph: Graph) -> Tuple[CreationInfo, URIRef]: ) creator_comment = parse_literal(logger, graph, creation_info_node, RDFS.comment) creators = [] - for _, _, creator_literal in graph.triples((creation_info_node, SPDX_NAMESPACE.creator, None)): - creators.append(ActorParser.parse_actor(creator_literal)) + for _, _, creator_literal in get_correctly_typed_triples( + logger, graph, creation_info_node, SPDX_NAMESPACE.creator + ): + creators.append(ActorParser.parse_actor(creator_literal.toPython())) external_document_refs = [] - for _, _, external_document_node in graph.triples((doc_node, SPDX_NAMESPACE.externalDocumentRef, None)): + for _, _, external_document_node in get_correctly_typed_triples( + logger, graph, doc_node, SPDX_NAMESPACE.externalDocumentRef + ): external_document_refs.append(parse_external_document_refs(external_document_node, graph, namespace)) raise_parsing_error_if_logger_has_messages(logger, "CreationInfo") @@ -93,7 +102,7 @@ def parse_namespace_and_spdx_id(graph: Graph) -> (str, str): ) sys.exit(1) - namespace, spdx_id = urldefrag(subject) + namespace, spdx_id = urldefrag(str(subject)) if not namespace: logging.error( diff --git a/src/spdx/parser/rdf/extracted_licensing_info_parser.py b/src/spdx/parser/rdf/extracted_licensing_info_parser.py index 6a713ddfd..eae155cc4 100644 --- a/src/spdx/parser/rdf/extracted_licensing_info_parser.py +++ b/src/spdx/parser/rdf/extracted_licensing_info_parser.py @@ -6,7 +6,11 @@ from spdx.model.extracted_licensing_info import ExtractedLicensingInfo from spdx.parser.logger import Logger from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.rdf.graph_parsing_functions import parse_literal, parse_literal_or_no_assertion_or_none +from spdx.parser.rdf.graph_parsing_functions import ( + get_correctly_typed_triples, + parse_literal, + parse_literal_or_no_assertion_or_none, +) from spdx.rdfschema.namespace import SPDX_NAMESPACE @@ -28,7 +32,9 @@ def parse_extracted_licensing_info( logger, graph, extracted_licensing_info_node, SPDX_NAMESPACE.name ) cross_references = [] - for _, _, cross_reference_node in graph.triples((extracted_licensing_info_node, RDFS.seeAlso, None)): + for _, _, cross_reference_node in get_correctly_typed_triples( + logger, graph, extracted_licensing_info_node, RDFS.seeAlso + ): cross_references.append(cross_reference_node.toPython()) raise_parsing_error_if_logger_has_messages(logger, "ExtractedLicensingInfo") extracted_licensing_info = construct_or_raise_parsing_error( diff --git a/src/spdx/parser/rdf/file_parser.py b/src/spdx/parser/rdf/file_parser.py index 2dec391d4..649d29879 100644 --- a/src/spdx/parser/rdf/file_parser.py +++ b/src/spdx/parser/rdf/file_parser.py @@ -9,6 +9,7 @@ from spdx.parser.rdf.checksum_parser import parse_checksum from spdx.parser.rdf.graph_parsing_functions import ( apply_parsing_method_or_log_error, + get_correctly_typed_triples, get_correctly_typed_value, parse_enum_value, parse_literal, @@ -24,7 +25,7 @@ def parse_file(file_node: URIRef, graph: Graph, doc_namespace: str) -> File: spdx_id = parse_spdx_id(file_node, doc_namespace, graph) name = parse_literal(logger, graph, file_node, SPDX_NAMESPACE.fileName) checksums = [] - for _, _, checksum_node in graph.triples((file_node, SPDX_NAMESPACE.checksum, None)): + for _, _, checksum_node in get_correctly_typed_triples(logger, graph, file_node, SPDX_NAMESPACE.checksum): checksums.append(parse_checksum(checksum_node, graph)) file_types = [] @@ -39,25 +40,31 @@ def parse_file(file_node: URIRef, graph: Graph, doc_namespace: str) -> File: graph, file_node, SPDX_NAMESPACE.licenseConcluded, - parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace), + parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace, logger), ) license_info_in_file = [] for _, _, license_info_from_files_node in graph.triples((file_node, SPDX_NAMESPACE.licenseInfoInFile, None)): license_info_in_file.append( get_correctly_typed_value( - logger, license_info_from_files_node, lambda x: parse_license_expression(x, graph, doc_namespace) + logger, + license_info_from_files_node, + lambda x: parse_license_expression(x, graph, doc_namespace, logger), ) ) license_comment = parse_literal(logger, graph, file_node, SPDX_NAMESPACE.licenseComments) copyright_text = parse_literal_or_no_assertion_or_none(logger, graph, file_node, SPDX_NAMESPACE.copyrightText) file_contributors = [] - for _, _, file_contributor in graph.triples((file_node, SPDX_NAMESPACE.fileContributor, None)): + for _, _, file_contributor in get_correctly_typed_triples( + logger, graph, file_node, SPDX_NAMESPACE.fileContributor, None + ): file_contributors.append(file_contributor.toPython()) notice_text = parse_literal(logger, graph, file_node, SPDX_NAMESPACE.noticeText) comment = parse_literal(logger, graph, file_node, RDFS.comment) attribution_texts = [] - for _, _, attribution_text_literal in graph.triples((file_node, SPDX_NAMESPACE.attributionText, None)): + for _, _, attribution_text_literal in get_correctly_typed_triples( + logger, graph, file_node, SPDX_NAMESPACE.attributionText, None + ): attribution_texts.append(attribution_text_literal.toPython()) raise_parsing_error_if_logger_has_messages(logger, "File") file = construct_or_raise_parsing_error( diff --git a/src/spdx/parser/rdf/graph_parsing_functions.py b/src/spdx/parser/rdf/graph_parsing_functions.py index 72b107c7f..15a0ff8cf 100644 --- a/src/spdx/parser/rdf/graph_parsing_functions.py +++ b/src/spdx/parser/rdf/graph_parsing_functions.py @@ -2,12 +2,12 @@ # # SPDX-License-Identifier: Apache-2.0 from enum import Enum -from typing import Any, Callable, Optional, Type +from typing import Any, Callable, Optional, Tuple, Type, Union -from rdflib import Graph, URIRef +from rdflib import RDF, Graph, URIRef from rdflib.exceptions import UniquenessError from rdflib.namespace import NamespaceManager -from rdflib.term import Node +from rdflib.term import BNode, Literal, Node from spdx.casing_tools import camel_case_to_snake_case from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion @@ -102,3 +102,46 @@ def remove_prefix(string: str, prefix: str) -> str: if string.startswith(prefix): return string[len(prefix) :] return string + + +def get_correctly_typed_triples( + logger: Logger, + graph: Graph, + subject: Optional[Node] = None, + predicate: Optional[Node] = None, + _object: Optional[Node] = None, +) -> Tuple[Union[BNode, URIRef], Node, Union[BNode, Literal, URIRef]]: + # this is a helper method to cast some rdf types from graph.triples() to be compatible with the + # code that follows + for s, p, o in graph.triples((subject, predicate, _object)): + if not isinstance(s, (BNode, URIRef)): + logger.append( + f"Warning: Subject {s} should be of type BNode or URIRef, but is {type(s).__name__}. " + f"This might lead to a failure." + ) + if not isinstance(o, (BNode, Literal, URIRef)): + logger.append( + f"Warning: Object {o} should be of type BNode, Literal or URIRef, but is {type(o).__name__}. " + f"This might lead to a failure." + ) + yield s, p, o + + +def get_value_from_graph( + logger: Logger, + graph: Graph, + subject: Optional[Node] = None, + predicate: Optional[Node] = RDF.value, + _object: Optional[Node] = None, + default: Optional[Any] = None, + _any: Optional[bool] = True, +) -> Optional[Union[URIRef, Literal, BNode]]: + # this is a helper method to cast some rdf types from graph.value() to be compatible with the + # code that follows + value = graph.value(subject=subject, predicate=predicate, object=_object, default=default, any=_any) + if value and not isinstance(value, (URIRef, Literal, BNode)): + logger.append( + f"Warning: Node {value} should be of type BNode, Literal or URIRef, but is {type(value).__name__}. " + f"This might lead to a failure." + ) + return value diff --git a/src/spdx/parser/rdf/license_expression_parser.py b/src/spdx/parser/rdf/license_expression_parser.py index 7f6017854..b6ccc3bd8 100644 --- a/src/spdx/parser/rdf/license_expression_parser.py +++ b/src/spdx/parser/rdf/license_expression_parser.py @@ -1,19 +1,25 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Union +from typing import Optional, Union from license_expression import LicenseExpression, get_spdx_licensing from rdflib import RDF, Graph from rdflib.term import BNode, Identifier, Node, URIRef -from spdx.parser.rdf.graph_parsing_functions import remove_prefix +from spdx.parser.logger import Logger +from spdx.parser.rdf.graph_parsing_functions import get_value_from_graph, remove_prefix from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE def parse_license_expression( - license_expression_node: Union[URIRef, BNode, Node], graph: Graph, doc_namespace: str + license_expression_node: Union[URIRef, BNode, Node], + graph: Graph, + doc_namespace: str, + logger: Optional[Logger] = None, ) -> LicenseExpression: + if not logger: + logger = Logger() spdx_licensing = get_spdx_licensing() expression = "" if license_expression_node.startswith(LICENSE_NAMESPACE): @@ -27,28 +33,30 @@ def parse_license_expression( if node_type == SPDX_NAMESPACE.ConjunctiveLicenseSet: members = [] for _, _, member_node in graph.triples((license_expression_node, SPDX_NAMESPACE.member, None)): - members.append(parse_license_expression(member_node, graph, doc_namespace)) + members.append(parse_license_expression(member_node, graph, doc_namespace, logger)) expression = " AND ".join([str(member) for member in members]) if node_type == SPDX_NAMESPACE.DisjunctiveLicenseSet: members = [] for _, _, member_node in graph.triples((license_expression_node, SPDX_NAMESPACE.member, None)): - members.append(parse_license_expression(member_node, graph, doc_namespace)) + members.append(parse_license_expression(member_node, graph, doc_namespace, logger)) expression = " OR ".join([str(member) for member in members]) if node_type == SPDX_NAMESPACE.WithExceptionOperator: license_expression = parse_license_expression( - graph.value(license_expression_node, SPDX_NAMESPACE.member), graph, doc_namespace + graph.value(license_expression_node, SPDX_NAMESPACE.member), graph, doc_namespace, logger ) exception = parse_license_exception( - graph.value(license_expression_node, SPDX_NAMESPACE.licenseException), graph + get_value_from_graph(logger, graph, license_expression_node, SPDX_NAMESPACE.licenseException), + graph, + logger, ) expression = f"{license_expression} WITH {exception}" return spdx_licensing.parse(expression) -def parse_license_exception(exception_node: Identifier, graph: Graph) -> str: +def parse_license_exception(exception_node: Identifier, graph: Graph, logger) -> str: if exception_node.startswith(LICENSE_NAMESPACE): exception = remove_prefix(exception_node, LICENSE_NAMESPACE) else: - exception = graph.value(exception_node, SPDX_NAMESPACE.licenseExceptionId).toPython() + exception = get_value_from_graph(logger, graph, exception_node, SPDX_NAMESPACE.licenseExceptionId).toPython() return exception diff --git a/src/spdx/parser/rdf/package_parser.py b/src/spdx/parser/rdf/package_parser.py index 866af16a4..e4ba4b02b 100644 --- a/src/spdx/parser/rdf/package_parser.py +++ b/src/spdx/parser/rdf/package_parser.py @@ -4,6 +4,7 @@ from typing import Optional from rdflib import DOAP, RDFS, Graph, URIRef +from rdflib.term import BNode from spdx.datetime_conversions import datetime_from_str from spdx.model.package import ( @@ -18,7 +19,9 @@ from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages from spdx.parser.rdf.checksum_parser import parse_checksum from spdx.parser.rdf.graph_parsing_functions import ( + get_correctly_typed_triples, get_correctly_typed_value, + get_value_from_graph, parse_enum_value, parse_literal, parse_literal_or_no_assertion_or_none, @@ -36,7 +39,7 @@ def parse_package(package_node: URIRef, graph: Graph, doc_namespace: str) -> Pac logger, graph, package_node, SPDX_NAMESPACE.downloadLocation ) checksums = [] - for _, _, checksum_node in graph.triples((package_node, SPDX_NAMESPACE.checksum, None)): + for _, _, checksum_node in get_correctly_typed_triples(logger, graph, package_node, SPDX_NAMESPACE.checksum): checksums.append(parse_checksum(checksum_node, graph)) version_info = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.versionInfo) @@ -57,28 +60,34 @@ def parse_package(package_node: URIRef, graph: Graph, doc_namespace: str) -> Pac ) external_package_refs = [] - for _, _, external_package_ref_node in graph.triples((package_node, SPDX_NAMESPACE.externalRef, None)): + for _, _, external_package_ref_node in get_correctly_typed_triples( + logger, graph, package_node, SPDX_NAMESPACE.externalRef + ): external_package_refs.append(parse_external_package_ref(external_package_ref_node, graph, doc_namespace)) - files_analyzed = bool(graph.value(package_node, SPDX_NAMESPACE.filesAnalyzed, default=True)) + files_analyzed = bool( + get_value_from_graph(logger, graph, package_node, SPDX_NAMESPACE.filesAnalyzed, default=True) + ) license_concluded = parse_literal_or_no_assertion_or_none( logger, graph, package_node, SPDX_NAMESPACE.licenseConcluded, - parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace), + parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace, logger), ) license_declared = parse_literal_or_no_assertion_or_none( logger, graph, package_node, SPDX_NAMESPACE.licenseDeclared, - parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace), + parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace, logger), ) license_info_from_files = [] for _, _, license_info_from_files_node in graph.triples((package_node, SPDX_NAMESPACE.licenseInfoFromFiles, None)): license_info_from_files.append( get_correctly_typed_value( - logger, license_info_from_files_node, lambda x: parse_license_expression(x, graph, doc_namespace) + logger, + license_info_from_files_node, + lambda x: parse_license_expression(x, graph, doc_namespace, logger), ) ) license_comment = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.licenseComments) @@ -161,7 +170,7 @@ def parse_package_verification_code( return package_verification_code -def parse_external_package_ref(external_package_ref_node: URIRef, graph: Graph, doc_namespace) -> ExternalPackageRef: +def parse_external_package_ref(external_package_ref_node: BNode, graph: Graph, doc_namespace) -> ExternalPackageRef: logger = Logger() ref_locator = parse_literal(logger, graph, external_package_ref_node, SPDX_NAMESPACE.referenceLocator) ref_category = parse_literal( diff --git a/src/spdx/parser/rdf/rdf_parser.py b/src/spdx/parser/rdf/rdf_parser.py index cbd77b255..e05de8b64 100644 --- a/src/spdx/parser/rdf/rdf_parser.py +++ b/src/spdx/parser/rdf/rdf_parser.py @@ -14,6 +14,7 @@ from spdx.parser.rdf.creation_info_parser import parse_creation_info from spdx.parser.rdf.extracted_licensing_info_parser import parse_extracted_licensing_info from spdx.parser.rdf.file_parser import parse_file +from spdx.parser.rdf.graph_parsing_functions import get_correctly_typed_triples from spdx.parser.rdf.package_parser import parse_package from spdx.parser.rdf.relationship_parser import parse_implicit_relationship, parse_relationship from spdx.parser.rdf.snippet_parser import parse_snippet @@ -46,7 +47,7 @@ def translate_graph_to_document(graph: Graph) -> Document: ("snippets", (None, RDF.type, SPDX_NAMESPACE.Snippet), parse_snippet), ]: elements = [] - for element_node, _, _ in graph.triples(triple): + for element_node, _, _ in get_correctly_typed_triples(logger, graph, *triple): try: elements.append(parsing_method(element_node, graph, creation_info.document_namespace)) except SPDXParsingError as err: @@ -69,7 +70,7 @@ def translate_graph_to_document(graph: Graph) -> Document: ((None, SPDX_NAMESPACE.hasFile, None), RelationshipType.CONTAINS), ((None, SPDX_NAMESPACE.describesPackage, None), RelationshipType.DESCRIBES), ]: - for parent_node, _, element_node in graph.triples(triple): + for parent_node, _, element_node in get_correctly_typed_triples(logger, graph, *triple): try: relationship = parse_implicit_relationship( parent_node, relationship_type, element_node, graph, creation_info.document_namespace @@ -81,7 +82,9 @@ def translate_graph_to_document(graph: Graph) -> Document: logger.extend(err.get_messages()) extracted_licensing_infos = [] - for _, _, extracted_licensing_info_node in graph.triples((None, SPDX_NAMESPACE.hasExtractedLicensingInfo, None)): + for _, _, extracted_licensing_info_node in get_correctly_typed_triples( + logger, graph, None, SPDX_NAMESPACE.hasExtractedLicensingInfo + ): try: extracted_licensing_infos.append( parse_extracted_licensing_info(extracted_licensing_info_node, graph, creation_info.document_namespace) diff --git a/src/spdx/parser/rdf/relationship_parser.py b/src/spdx/parser/rdf/relationship_parser.py index cdd61e5ee..d08ddf54d 100644 --- a/src/spdx/parser/rdf/relationship_parser.py +++ b/src/spdx/parser/rdf/relationship_parser.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef +from rdflib.term import Node from spdx.model.relationship import Relationship, RelationshipType from spdx.parser.logger import Logger @@ -15,9 +16,7 @@ from spdx.rdfschema.namespace import SPDX_NAMESPACE -def parse_relationship( - relationship_node: URIRef, graph: Graph, parent_node: URIRef, doc_namespace: str -) -> Relationship: +def parse_relationship(relationship_node: Node, graph: Graph, parent_node: URIRef, doc_namespace: str) -> Relationship: logger = Logger() spdx_element_id = parse_spdx_id(parent_node, doc_namespace, graph) diff --git a/src/spdx/parser/rdf/snippet_parser.py b/src/spdx/parser/rdf/snippet_parser.py index 446b0fc73..23f746be5 100644 --- a/src/spdx/parser/rdf/snippet_parser.py +++ b/src/spdx/parser/rdf/snippet_parser.py @@ -5,7 +5,7 @@ from rdflib import RDF, RDFS, Graph from rdflib.exceptions import UniquenessError -from rdflib.term import Node, URIRef +from rdflib.term import BNode, Node, URIRef from spdx.model.snippet import Snippet from spdx.parser.error import SPDXParsingError @@ -13,7 +13,9 @@ from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages from spdx.parser.rdf.graph_parsing_functions import ( apply_parsing_method_or_log_error, + get_correctly_typed_triples, get_correctly_typed_value, + get_value_from_graph, parse_literal, parse_literal_or_no_assertion_or_none, parse_spdx_id, @@ -25,7 +27,9 @@ def parse_snippet(snippet_node: URIRef, graph: Graph, doc_namespace: str) -> Snippet: logger = Logger() spdx_id = parse_spdx_id(snippet_node, doc_namespace, graph) - file_spdx_id_uri = graph.value(subject=snippet_node, predicate=SPDX_NAMESPACE.snippetFromFile) + file_spdx_id_uri = get_value_from_graph( + logger, graph, subject=snippet_node, predicate=SPDX_NAMESPACE.snippetFromFile + ) file_spdx_id = parse_spdx_id(file_spdx_id_uri, doc_namespace, graph) byte_range = None line_range = None @@ -40,13 +44,15 @@ def parse_snippet(snippet_node: URIRef, graph: Graph, doc_namespace: str) -> Sni graph, snippet_node, SPDX_NAMESPACE.licenseConcluded, - parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace), + parsing_method=lambda x: parse_license_expression(x, graph, doc_namespace, logger), ) license_info_in_snippet = [] for _, _, license_info_in_snippet_node in graph.triples((snippet_node, SPDX_NAMESPACE.licenseInfoInSnippet, None)): license_info_in_snippet.append( get_correctly_typed_value( - logger, license_info_in_snippet_node, lambda x: parse_license_expression(x, graph, doc_namespace) + logger, + license_info_in_snippet_node, + lambda x: parse_license_expression(x, graph, doc_namespace, logger), ) ) license_comment = parse_literal(logger, graph, snippet_node, SPDX_NAMESPACE.licenseComments) @@ -54,7 +60,9 @@ def parse_snippet(snippet_node: URIRef, graph: Graph, doc_namespace: str) -> Sni comment = parse_literal(logger, graph, snippet_node, RDFS.comment) name = parse_literal(logger, graph, snippet_node, SPDX_NAMESPACE.name) attribution_texts = [] - for _, _, attribution_text_literal in graph.triples((snippet_node, SPDX_NAMESPACE.attributionText, None)): + for _, _, attribution_text_literal in get_correctly_typed_triples( + logger, graph, snippet_node, SPDX_NAMESPACE.attributionText, None + ): attribution_texts.append(attribution_text_literal.toPython()) raise_parsing_error_if_logger_has_messages(logger, "Snippet") @@ -96,7 +104,7 @@ def set_range_or_log_error( return byte_range, line_range -def parse_ranges(start_end_pointer: URIRef, graph: Graph) -> Dict[str, Tuple[int, int]]: +def parse_ranges(start_end_pointer: BNode, graph: Graph) -> Dict[str, Tuple[int, int]]: range_values = dict() start_pointer_type, start_pointer_node = get_pointer_type(graph, POINTER_NAMESPACE.startPointer, start_end_pointer) end_pointer_type, end_pointer_node = get_pointer_type(graph, POINTER_NAMESPACE.endPointer, start_end_pointer) @@ -110,14 +118,14 @@ def parse_ranges(start_end_pointer: URIRef, graph: Graph) -> Dict[str, Tuple[int return {str(start_pointer_type.fragment): (range_values["startPointer"], range_values["endPointer"])} -def get_pointer_type(graph: Graph, pointer: URIRef, start_end_pointer: URIRef) -> Tuple[URIRef, URIRef]: +def get_pointer_type(graph: Graph, pointer: URIRef, start_end_pointer: BNode) -> Tuple[URIRef, Node]: try: pointer_node = graph.value(start_end_pointer, pointer, any=False) except UniquenessError: raise SPDXParsingError([f"Multiple values for {pointer.fragment}"]) if not pointer_node: raise SPDXParsingError([f"Couldn't find pointer of type {pointer.fragment}."]) - pointer_type = graph.value(pointer_node, RDF.type) + pointer_type = get_value_from_graph(Logger(), graph, pointer_node, RDF.type) return pointer_type, pointer_node @@ -129,9 +137,9 @@ def get_pointer_type(graph: Graph, pointer: URIRef, start_end_pointer: URIRef) - def parse_range_value(graph: Graph, pointer_node: Node, predicate: URIRef) -> Optional[int]: try: - value = graph.value(pointer_node, predicate, any=False) + value = get_value_from_graph(Logger(), graph, pointer_node, predicate, _any=False) except UniquenessError: raise SPDXParsingError([f"Multiple values for {predicate.fragment} found."]) if value: - value = int(value) + value = int(value.toPython()) return value diff --git a/tests/spdx/parser/rdf/test_annotation_parser.py b/tests/spdx/parser/rdf/test_annotation_parser.py index ed9978394..c98c34675 100644 --- a/tests/spdx/parser/rdf/test_annotation_parser.py +++ b/tests/spdx/parser/rdf/test_annotation_parser.py @@ -4,7 +4,7 @@ import os from datetime import datetime -from rdflib import Graph, URIRef +from rdflib import BNode, Graph, URIRef from spdx.model.actor import Actor, ActorType from spdx.model.annotation import AnnotationType @@ -17,6 +17,7 @@ def test_parse_annotation(): doc_namespace = "https://some.namespace" file_node = URIRef(f"{doc_namespace}#SPDXRef-File") annotation_node = graph.value(subject=file_node, predicate=SPDX_NAMESPACE.annotation) + assert isinstance(annotation_node, BNode) annotation = parse_annotation(annotation_node, graph, file_node, doc_namespace) diff --git a/tests/spdx/parser/rdf/test_checksum_parser.py b/tests/spdx/parser/rdf/test_checksum_parser.py index 028b3f20c..575d1f3cc 100644 --- a/tests/spdx/parser/rdf/test_checksum_parser.py +++ b/tests/spdx/parser/rdf/test_checksum_parser.py @@ -4,7 +4,7 @@ import os import pytest -from rdflib import Graph, URIRef +from rdflib import BNode, Graph, URIRef from spdx.model.checksum import ChecksumAlgorithm from spdx.parser.error import SPDXParsingError @@ -17,6 +17,7 @@ def test_parse_checksum(): checksum_node = graph.value( subject=URIRef("https://some.namespace#DocumentRef-external"), predicate=SPDX_NAMESPACE.checksum ) + assert isinstance(checksum_node, BNode) checksum = parse_checksum(checksum_node, graph) diff --git a/tests/spdx/parser/rdf/test_creation_info_parser.py b/tests/spdx/parser/rdf/test_creation_info_parser.py index 04ac5e801..e5f17877c 100644 --- a/tests/spdx/parser/rdf/test_creation_info_parser.py +++ b/tests/spdx/parser/rdf/test_creation_info_parser.py @@ -82,6 +82,7 @@ def test_parse_external_document_refs(): external_doc_ref_node = graph.value( subject=URIRef(f"{doc_namespace}#SPDXRef-DOCUMENT"), predicate=SPDX_NAMESPACE.externalDocumentRef ) + assert isinstance(external_doc_ref_node, URIRef) external_document_ref = parse_external_document_refs(external_doc_ref_node, graph, doc_namespace) diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py index 6e962bc3d..17b0edeef 100644 --- a/tests/spdx/parser/rdf/test_file_parser.py +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -5,7 +5,7 @@ from unittest import TestCase from license_expression import get_spdx_licensing -from rdflib import RDF, Graph +from rdflib import RDF, Graph, URIRef from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.model.file import FileType @@ -18,6 +18,7 @@ def test_parse_file(): graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) file_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.File) doc_namespace = "https://some.namespace" + assert isinstance(file_node, URIRef) file = parse_file(file_node, graph, doc_namespace) diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index dacdce56b..d48797a14 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -6,7 +6,7 @@ import pytest from license_expression import get_spdx_licensing -from rdflib import RDF, Graph, Literal +from rdflib import RDF, BNode, Graph, Literal, URIRef from spdx.model.actor import Actor, ActorType from spdx.model.checksum import Checksum, ChecksumAlgorithm @@ -21,6 +21,7 @@ def test_package_parser(): # we have two packages in the test file, graph.value() will return the first package package_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Package) doc_namespace = "https://some.namespace" + assert isinstance(package_node, URIRef) package = parse_package(package_node, graph, doc_namespace) @@ -80,6 +81,7 @@ def test_external_package_ref_parser(download_location, category, locator, type, # in the test file we have two different external package refs depending on the package package_node = graph.value(predicate=SPDX_NAMESPACE.downloadLocation, object=Literal(download_location)) external_package_ref_node = graph.value(package_node, SPDX_NAMESPACE.externalRef) + assert isinstance(external_package_ref_node, BNode) external_package_ref = parse_external_package_ref(external_package_ref_node, graph, doc_namespace) diff --git a/tests/spdx/parser/rdf/test_relationship_parser.py b/tests/spdx/parser/rdf/test_relationship_parser.py index 53935f06d..cf2a8b7df 100644 --- a/tests/spdx/parser/rdf/test_relationship_parser.py +++ b/tests/spdx/parser/rdf/test_relationship_parser.py @@ -16,6 +16,7 @@ def test_relationship_parser(): parent_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.SpdxDocument) relationship_node = graph.value(subject=parent_node, predicate=SPDX_NAMESPACE.relationship) doc_namespace = "https://some.namespace" + assert isinstance(parent_node, URIRef) relationship = parse_relationship(relationship_node, graph, parent_node, doc_namespace) diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index 5c975798c..13dcf5fdc 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -6,7 +6,7 @@ import pytest from license_expression import get_spdx_licensing -from rdflib import RDF, BNode, Graph, Literal +from rdflib import RDF, BNode, Graph, Literal, URIRef from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.parser.error import SPDXParsingError @@ -18,6 +18,7 @@ def test_parse_snippet(): graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) snippet_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Snippet) doc_namespace = "https://some.namespace" + assert isinstance(snippet_node, URIRef) snippet = parse_snippet(snippet_node, graph, doc_namespace) @@ -60,7 +61,9 @@ def test_parse_ranges(predicate_value_class_member): add_range_to_graph_helper(graph, predicate_value_class_member) - range_dict = parse_ranges(graph.value(predicate=RDF.type, object=POINTER_NAMESPACE.StartEndPointer), graph) + range_node = graph.value(predicate=RDF.type, object=POINTER_NAMESPACE.StartEndPointer) + assert isinstance(range_node, BNode) + range_dict = parse_ranges(range_node, graph) assert pointer_class.fragment in range_dict.keys() assert range_dict[pointer_class.fragment][0] == predicate_value_class_member[0][1] @@ -90,7 +93,9 @@ def test_parse_ranges_wrong_pair_of_pointer_classes(predicate_value_class_member add_range_to_graph_helper(graph, predicate_value_class_member) - range_dict = parse_ranges(graph.value(predicate=RDF.type, object=POINTER_NAMESPACE.StartEndPointer), graph) + range_node = graph.value(predicate=RDF.type, object=POINTER_NAMESPACE.StartEndPointer) + assert isinstance(range_node, BNode) + range_dict = parse_ranges(range_node, graph) assert pointer_class.fragment in range_dict.keys() assert range_dict[pointer_class.fragment][0] is None @@ -141,7 +146,9 @@ def test_parse_ranges_error(predicate_value_class_member, expected_message): add_range_to_graph_helper(graph, predicate_value_class_member) with pytest.raises(SPDXParsingError, match=expected_message): - parse_ranges(graph.value(predicate=RDF.type, object=POINTER_NAMESPACE.StartEndPointer), graph) + range_node = graph.value(predicate=RDF.type, object=POINTER_NAMESPACE.StartEndPointer) + assert isinstance(range_node, BNode) + parse_ranges(range_node, graph) def add_range_to_graph_helper(graph, predicate_value_class_member): From 0e1df0ac9a18de43ffe4e330606aed1422360ba7 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 5 Apr 2023 15:20:44 +0200 Subject: [PATCH 041/354] [issue-564] add constant for "SPDXRef-DOCUMENT" Signed-off-by: Meret Behrens --- src/spdx/constants.py | 4 +++ src/spdx/parser/rdf/creation_info_parser.py | 6 ++-- .../validation/creation_info_validator.py | 5 +-- tests/spdx/fixtures.py | 5 +-- .../jsonlikedict/test_annotation_parser.py | 9 +++--- .../jsonlikedict/test_creation_info_parser.py | 9 +++--- .../jsonlikedict/test_relationship_parser.py | 31 ++++++++++--------- .../parser/rdf/test_creation_info_parser.py | 7 +++-- .../parser/rdf/test_relationship_parser.py | 5 +-- .../parser/tagvalue/test_annotation_parser.py | 7 +++-- .../tagvalue/test_creation_info_parser.py | 9 +++--- .../parser/tagvalue/test_package_parser.py | 3 +- .../tagvalue/test_relationship_parser.py | 9 +++--- .../parser/tagvalue/test_tag_value_lexer.py | 13 ++++---- .../parser/tagvalue/test_tag_value_parser.py | 3 +- tests/spdx/validation/test_actor_validator.py | 5 +-- .../test_creation_info_validator.py | 7 +++-- .../validation/test_document_validator.py | 15 ++++----- .../spdx/validation/test_package_validator.py | 3 +- .../validation/test_relationship_validator.py | 9 +++--- .../validation/test_spdx_id_validators.py | 9 +++--- .../writer/rdf/test_relationship_writer.py | 3 +- .../tagvalue/test_creation_info_writer.py | 7 +++-- 23 files changed, 104 insertions(+), 79 deletions(-) create mode 100644 src/spdx/constants.py diff --git a/src/spdx/constants.py b/src/spdx/constants.py new file mode 100644 index 000000000..167f98951 --- /dev/null +++ b/src/spdx/constants.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +DOCUMENT_SPDX_ID = "SPDXRef-DOCUMENT" diff --git a/src/spdx/parser/rdf/creation_info_parser.py b/src/spdx/parser/rdf/creation_info_parser.py index 3e11589fa..5254d3a10 100644 --- a/src/spdx/parser/rdf/creation_info_parser.py +++ b/src/spdx/parser/rdf/creation_info_parser.py @@ -10,6 +10,7 @@ from rdflib.exceptions import UniquenessError from rdflib.term import URIRef +from spdx.constants import DOCUMENT_SPDX_ID from spdx.datetime_conversions import datetime_from_str from spdx.model.document import CreationInfo from spdx.model.external_document_ref import ExternalDocumentRef @@ -98,7 +99,7 @@ def parse_namespace_and_spdx_id(graph: Graph) -> (str, str): if "#" not in subject: logging.error( "No '#' found in the URI of SpdxDocument, " - "the URI for the SpdxDocument should be the namespace appended by '#SPDXRef-DOCUMENT." + f"the URI for the SpdxDocument should be the namespace appended by '#{DOCUMENT_SPDX_ID}." ) sys.exit(1) @@ -106,7 +107,8 @@ def parse_namespace_and_spdx_id(graph: Graph) -> (str, str): if not namespace: logging.error( - "No namespace found, the URI for the SpdxDocument should be the namespace appended by '#SPDXRef-DOCUMENT." + f"No namespace found, the URI for the SpdxDocument should be the namespace appended by " + f"'#{DOCUMENT_SPDX_ID}." ) sys.exit(1) diff --git a/src/spdx/validation/creation_info_validator.py b/src/spdx/validation/creation_info_validator.py index 00e4a279e..9cb4e1259 100644 --- a/src/spdx/validation/creation_info_validator.py +++ b/src/spdx/validation/creation_info_validator.py @@ -4,6 +4,7 @@ from typing import List +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.document import CreationInfo from spdx.validation.actor_validator import validate_actors from spdx.validation.external_document_ref_validator import validate_external_document_refs @@ -16,9 +17,9 @@ def validate_creation_info(creation_info: CreationInfo, spdx_version: str) -> Li context = ValidationContext(spdx_id=creation_info.spdx_id, element_type=SpdxElementType.DOCUMENT) - if creation_info.spdx_id != "SPDXRef-DOCUMENT": + if creation_info.spdx_id != DOCUMENT_SPDX_ID: validation_messages.append( - ValidationMessage(f'spdx_id must be "SPDXRef-DOCUMENT", but is: {creation_info.spdx_id}', context) + ValidationMessage(f"spdx_id must be {DOCUMENT_SPDX_ID}, but is: {creation_info.spdx_id}", context) ) if creation_info.data_license != "CC0-1.0": diff --git a/tests/spdx/fixtures.py b/tests/spdx/fixtures.py index 7800221e7..5d58b9fbf 100644 --- a/tests/spdx/fixtures.py +++ b/tests/spdx/fixtures.py @@ -5,6 +5,7 @@ from license_expression import get_spdx_licensing +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.actor import Actor, ActorType from spdx.model.annotation import Annotation, AnnotationType from spdx.model.checksum import Checksum, ChecksumAlgorithm @@ -46,7 +47,7 @@ def package_verification_code_fixture( def creation_info_fixture( spdx_version="SPDX-2.3", - spdx_id="SPDXRef-DOCUMENT", + spdx_id=DOCUMENT_SPDX_ID, name="documentName", document_namespace="https://some.namespace", creators=None, @@ -264,7 +265,7 @@ def extracted_licensing_info_fixture( def relationship_fixture( - spdx_element_id="SPDXRef-DOCUMENT", + spdx_element_id=DOCUMENT_SPDX_ID, relationship_type=RelationshipType.DESCRIBES, related_spdx_element_id="SPDXRef-File", comment="relationshipComment", diff --git a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py index 13ed71ca9..1b6297eaf 100644 --- a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py @@ -6,6 +6,7 @@ import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.actor import Actor, ActorType from spdx.model.annotation import Annotation, AnnotationType from spdx.parser.error import SPDXParsingError @@ -21,19 +22,19 @@ def test_parse_annotation(): "comment": "Document level annotation", } - annotation = annotation_parser.parse_annotation(annotation_dict, spdx_id="SPDXRef-DOCUMENT") + annotation = annotation_parser.parse_annotation(annotation_dict, spdx_id=DOCUMENT_SPDX_ID) assert annotation.annotator == Actor(ActorType.PERSON, name="Jane Doe") assert annotation.annotation_type == AnnotationType.OTHER assert annotation.annotation_date == datetime.datetime(2010, 1, 29, 18, 30, 22) assert annotation.annotation_comment == "Document level annotation" - assert annotation.spdx_id == "SPDXRef-DOCUMENT" + assert annotation.spdx_id == DOCUMENT_SPDX_ID def test_parse_all_annotations(): annotation_parser = AnnotationParser() doc_dict = { - "SPDXID": "SPDXRef-DOCUMENT", + "SPDXID": DOCUMENT_SPDX_ID, "packages": [ { "SPDXID": "SPDXRef-Package", @@ -87,7 +88,7 @@ def test_parse_all_annotations(): annotations, [ Annotation( - spdx_id="SPDXRef-DOCUMENT", + spdx_id=DOCUMENT_SPDX_ID, annotation_type=AnnotationType.REVIEW, annotator=Actor(actor_type=ActorType.PERSON, name="Jane Doe", email=None), annotation_date=datetime.datetime(2010, 1, 29, 18, 30, 22), diff --git a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py index e60d9ff3e..a77dbba7a 100644 --- a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py @@ -6,6 +6,7 @@ import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.actor import Actor, ActorType from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.model.external_document_ref import ExternalDocumentRef @@ -18,7 +19,7 @@ def test_parse_creation_info(): creation_info_parser = CreationInfoParser() doc_dict = { "spdxVersion": "2.3", - "SPDXID": "SPDXRef-DOCUMENT", + "SPDXID": DOCUMENT_SPDX_ID, "name": "Example Document", "dataLicense": "CC0-1.0", "documentNamespace": "namespace", @@ -39,7 +40,7 @@ def test_parse_creation_info(): creation_info = creation_info_parser.parse_creation_info(doc_dict) assert creation_info.spdx_version == "2.3" - assert creation_info.spdx_id == "SPDXRef-DOCUMENT" + assert creation_info.spdx_id == DOCUMENT_SPDX_ID assert creation_info.name == "Example Document" assert creation_info.document_namespace == "namespace" assert creation_info.created == datetime(2010, 1, 29, 18, 30, 22) @@ -65,7 +66,7 @@ def test_parse_creation_info(): "incomplete_dict,expected_message", [ ( - {"spdxVersion": "2.3", "SPDXID": "SPDXRef-DOCUMENT", "name": "Example Document"}, + {"spdxVersion": "2.3", "SPDXID": DOCUMENT_SPDX_ID, "name": "Example Document"}, ["Error while parsing document Example Document: ['CreationInfo does not exist.']"], ), ( @@ -98,7 +99,7 @@ def test_parse_invalid_creation_info(): creation_info_parser = CreationInfoParser() doc_dict = { "spdxVersion": "2.3", - "SPDXID": "SPDXRef-DOCUMENT", + "SPDXID": DOCUMENT_SPDX_ID, "name": "Example Document", "creationInfo": { "created": "2010-01-29T18:30:22Z", diff --git a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py index 8a77e64b5..af394ef78 100644 --- a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py @@ -5,6 +5,7 @@ import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.relationship import Relationship, RelationshipType from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.parser.error import SPDXParsingError @@ -15,7 +16,7 @@ def test_parse_relationship(): relationship_parser = RelationshipParser() relationship_dict = { - "spdxElementId": "SPDXRef-DOCUMENT", + "spdxElementId": DOCUMENT_SPDX_ID, "relationshipType": "CONTAINS", "relatedSpdxElement": "NOASSERTION", "comment": "Comment.", @@ -24,7 +25,7 @@ def test_parse_relationship(): relationship = relationship_parser.parse_relationship(relationship_dict) assert relationship.relationship_type == RelationshipType.CONTAINS - assert relationship.spdx_element_id == "SPDXRef-DOCUMENT" + assert relationship.spdx_element_id == DOCUMENT_SPDX_ID assert relationship.related_spdx_element_id == SpdxNoAssertion() assert relationship.comment == "Comment." @@ -32,7 +33,7 @@ def test_parse_relationship(): def test_parse_incomplete_relationship(): relationship_parser = RelationshipParser() relationship_dict = { - "spdxElementId": "SPDXRef-DOCUMENT", + "spdxElementId": DOCUMENT_SPDX_ID, "relatedSpdxElement": "SPDXRef-Package", "comment": "Comment.", } @@ -62,12 +63,12 @@ def test_parse_document_describes(): relationship_parser = RelationshipParser() document_dict = { - "SPDXID": "SPDXRef-DOCUMENT", + "SPDXID": DOCUMENT_SPDX_ID, "documentDescribes": ["SPDXRef-Package", "SPDXRef-File", "SPDXRef-Snippet"], } relationships = relationship_parser.parse_document_describes( - doc_spdx_id="SPDXRef-DOCUMENT", + doc_spdx_id=DOCUMENT_SPDX_ID, described_spdx_ids=document_dict.get("documentDescribes"), existing_relationships=[], ) @@ -76,9 +77,9 @@ def test_parse_document_describes(): TestCase().assertCountEqual( relationships, [ - Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package"), - Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-File"), - Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Snippet"), + Relationship(DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, "SPDXRef-Package"), + Relationship(DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, "SPDXRef-File"), + Relationship(DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, "SPDXRef-Snippet"), ], ) @@ -90,14 +91,14 @@ def test_parse_document_describes(): ["SPDXRef-Package", "SPDXRef-File"], [ { - "spdxElementId": "SPDXRef-DOCUMENT", + "spdxElementId": DOCUMENT_SPDX_ID, "relatedSpdxElement": "SPDXRef-Package", "relationshipType": "DESCRIBES", "comment": "This relationship has a comment.", }, { "spdxElementId": "SPDXRef-File", - "relatedSpdxElement": "SPDXRef-DOCUMENT", + "relatedSpdxElement": DOCUMENT_SPDX_ID, "relationshipType": "DESCRIBED_BY", "comment": "This relationship has a comment.", }, @@ -106,11 +107,11 @@ def test_parse_document_describes(): Relationship( related_spdx_element_id="SPDXRef-Package", relationship_type=RelationshipType.DESCRIBES, - spdx_element_id="SPDXRef-DOCUMENT", + spdx_element_id=DOCUMENT_SPDX_ID, comment="This relationship has a comment.", ), Relationship( - related_spdx_element_id="SPDXRef-DOCUMENT", + related_spdx_element_id=DOCUMENT_SPDX_ID, relationship_type=RelationshipType.DESCRIBED_BY, spdx_element_id="SPDXRef-File", comment="This relationship has a comment.", @@ -124,12 +125,12 @@ def test_parse_document_describes(): Relationship( related_spdx_element_id="SPDXRef-Package", relationship_type=RelationshipType.DESCRIBES, - spdx_element_id="SPDXRef-DOCUMENT", + spdx_element_id=DOCUMENT_SPDX_ID, ), Relationship( related_spdx_element_id="SPDXRef-File", relationship_type=RelationshipType.DESCRIBES, - spdx_element_id="SPDXRef-DOCUMENT", + spdx_element_id=DOCUMENT_SPDX_ID, ), ], ), @@ -140,7 +141,7 @@ def test_parse_document_describes_without_duplicating_relationships( ): relationship_parser = RelationshipParser() document_dict = { - "SPDXID": "SPDXRef-DOCUMENT", + "SPDXID": DOCUMENT_SPDX_ID, "documentDescribes": document_describes, "relationships": relationships, } diff --git a/tests/spdx/parser/rdf/test_creation_info_parser.py b/tests/spdx/parser/rdf/test_creation_info_parser.py index e5f17877c..9845dd0a7 100644 --- a/tests/spdx/parser/rdf/test_creation_info_parser.py +++ b/tests/spdx/parser/rdf/test_creation_info_parser.py @@ -9,6 +9,7 @@ from rdflib import RDF, Graph, URIRef from rdflib.term import Node +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.actor import Actor, ActorType from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.model.version import Version @@ -24,7 +25,7 @@ def test_parse_creation_info(): graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) creation_info, _ = parse_creation_info(graph) - assert creation_info.spdx_id == "SPDXRef-DOCUMENT" + assert creation_info.spdx_id == DOCUMENT_SPDX_ID assert creation_info.spdx_version == "SPDX-2.3" assert creation_info.name == "documentName" assert creation_info.document_namespace == "https://some.namespace" @@ -53,7 +54,7 @@ def test_parse_namespace_and_spdx_id(): r"No '#' found in the URI of SpdxDocument", ), ([(URIRef(""), RDF.type, URIRef(""))], r"No SpdxDocument found, can't parse rdf file."), - ([(URIRef("#SPDXRef-DOCUMENT"), RDF.type, SPDX_NAMESPACE.SpdxDocument)], "No namespace found"), + ([(URIRef(f"#{DOCUMENT_SPDX_ID}"), RDF.type, SPDX_NAMESPACE.SpdxDocument)], "No namespace found"), ( [ (URIRef("docNamespace1"), RDF.type, SPDX_NAMESPACE.SpdxDocument), @@ -80,7 +81,7 @@ def test_parse_external_document_refs(): graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/file_to_test_rdf_parser.rdf.xml")) doc_namespace = "https://some.namespace" external_doc_ref_node = graph.value( - subject=URIRef(f"{doc_namespace}#SPDXRef-DOCUMENT"), predicate=SPDX_NAMESPACE.externalDocumentRef + subject=URIRef(f"{doc_namespace}#{DOCUMENT_SPDX_ID}"), predicate=SPDX_NAMESPACE.externalDocumentRef ) assert isinstance(external_doc_ref_node, URIRef) diff --git a/tests/spdx/parser/rdf/test_relationship_parser.py b/tests/spdx/parser/rdf/test_relationship_parser.py index cf2a8b7df..cb7b4572f 100644 --- a/tests/spdx/parser/rdf/test_relationship_parser.py +++ b/tests/spdx/parser/rdf/test_relationship_parser.py @@ -6,6 +6,7 @@ import pytest from rdflib import RDF, Graph, URIRef +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.relationship import RelationshipType from spdx.parser.rdf.relationship_parser import parse_implicit_relationship, parse_relationship from spdx.rdfschema.namespace import SPDX_NAMESPACE @@ -20,7 +21,7 @@ def test_relationship_parser(): relationship = parse_relationship(relationship_node, graph, parent_node, doc_namespace) - assert relationship.spdx_element_id == "SPDXRef-DOCUMENT" + assert relationship.spdx_element_id == DOCUMENT_SPDX_ID assert relationship.relationship_type == RelationshipType.DESCRIBES assert relationship.related_spdx_element_id == "SPDXRef-File" assert relationship.comment == "relationshipComment" @@ -32,7 +33,7 @@ def test_relationship_parser(): ( SPDX_NAMESPACE.SpdxDocument, SPDX_NAMESPACE.describesPackage, - "SPDXRef-DOCUMENT", + DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, "SPDXRef-Package", ), diff --git a/tests/spdx/parser/tagvalue/test_annotation_parser.py b/tests/spdx/parser/tagvalue/test_annotation_parser.py index 2a0392295..d7d130476 100644 --- a/tests/spdx/parser/tagvalue/test_annotation_parser.py +++ b/tests/spdx/parser/tagvalue/test_annotation_parser.py @@ -5,6 +5,7 @@ import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.annotation import AnnotationType from spdx.parser.error import SPDXParsingError from spdx.parser.tagvalue.parser import Parser @@ -19,7 +20,7 @@ def test_parse_annotation(): "AnnotationDate: 2010-01-29T18:30:22Z", "AnnotationComment: Document level annotation", "AnnotationType: OTHER", - "SPDXREF: SPDXRef-DOCUMENT", + f"SPDXREF: {DOCUMENT_SPDX_ID}", ] ) document = parser.parse("\n".join([DOCUMENT_STR, annotation_str])) @@ -30,7 +31,7 @@ def test_parse_annotation(): assert annotation.annotation_date == datetime(2010, 1, 29, 18, 30, 22) assert annotation.annotation_comment == "Document level annotation" assert annotation.annotation_type == AnnotationType.OTHER - assert annotation.spdx_id == "SPDXRef-DOCUMENT" + assert annotation.spdx_id == DOCUMENT_SPDX_ID @pytest.mark.parametrize( @@ -51,7 +52,7 @@ def test_parse_annotation(): ( "Annotator: Jane Doe()\nAnnotationDate: 201001-29T18:30:22Z\n" "AnnotationComment: Document level annotation\nAnnotationType: OTHER\n" - "SPDXREF: SPDXRef-DOCUMENT", + f"SPDXREF: {DOCUMENT_SPDX_ID}", "Error while parsing Annotation: ['Error while parsing Annotator: Token did " "not match specified grammar rule. Line: 1', 'Error while parsing " "AnnotationDate: Token did not match specified grammar rule. Line: 2']", diff --git a/tests/spdx/parser/tagvalue/test_creation_info_parser.py b/tests/spdx/parser/tagvalue/test_creation_info_parser.py index 4fb1993fa..e7b07d4bf 100644 --- a/tests/spdx/parser/tagvalue/test_creation_info_parser.py +++ b/tests/spdx/parser/tagvalue/test_creation_info_parser.py @@ -6,6 +6,7 @@ import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.actor import Actor, ActorType from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.model.external_document_ref import ExternalDocumentRef @@ -18,7 +19,7 @@ "SPDXVersion: SPDX-2.3", "DataLicense: CC0-1.0", "DocumentName: Sample_Document-V2.3", - "SPDXID: SPDXRef-DOCUMENT", + f"SPDXID: {DOCUMENT_SPDX_ID}", "DocumentComment: Sample Comment", "DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", "ExternalDocumentRef: DocumentRef-spdx-tool-1.2 " @@ -42,7 +43,7 @@ def test_parse_creation_info(): assert creation_info.spdx_version == "SPDX-2.3" assert creation_info.data_license == "CC0-1.0" assert creation_info.name == "Sample_Document-V2.3" - assert creation_info.spdx_id == "SPDXRef-DOCUMENT" + assert creation_info.spdx_id == DOCUMENT_SPDX_ID assert creation_info.document_comment == "Sample Comment" assert ( creation_info.document_namespace @@ -74,7 +75,7 @@ def test_parse_creation_info(): "SPDXVersion: SPDX-2.3", "DataLicense: CC0-1.0", "DocumentName: Sample_Document-V2.3", - "SPDXID: SPDXRef-DOCUMENT", + f"SPDXID: {DOCUMENT_SPDX_ID}", "DocumentComment: Sample Comment", "DocumentNamespace: Sample Comment", "ExternalDocumentRef: DocumentRef-spdx-tool-1.2:htp://spdx.org:SHA1: " @@ -102,7 +103,7 @@ def test_parse_creation_info(): "SPDXVersion: SPDX-2.3", "DataLicense: CC0-1.0", "DocumentName: Sample_Document-V2.3", - "SPDXID: SPDXRef-DOCUMENT", + f"SPDXID: {DOCUMENT_SPDX_ID}", ] ), r"__init__() missing 3 required positional arguments: 'document_namespace', 'creators', and 'created'", diff --git a/tests/spdx/parser/tagvalue/test_package_parser.py b/tests/spdx/parser/tagvalue/test_package_parser.py index dea9851d7..40794473d 100644 --- a/tests/spdx/parser/tagvalue/test_package_parser.py +++ b/tests/spdx/parser/tagvalue/test_package_parser.py @@ -7,6 +7,7 @@ import pytest from license_expression import get_spdx_licensing +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory, PackagePurpose from spdx.model.spdx_none import SpdxNone from spdx.parser.error import SPDXParsingError @@ -112,7 +113,7 @@ def test_parse_package(): "Error while parsing Package: ['Invalid ExternalPackageRefCategory: " "category. Line: 2']", ), ( - "SPDXID:SPDXRef-DOCUMENT\nPackageName: TestPackage\nSPDXID:SPDXRef-Package\n" + f"SPDXID:{DOCUMENT_SPDX_ID}\nPackageName: TestPackage\nSPDXID:SPDXRef-Package\n" "PackageDownloadLocation: download.com\nPackageVerificationCode: category reference locator", "Error while parsing Package: ['Error while parsing PackageVerificationCode: " "Value did not match expected format. Line: 5']", diff --git a/tests/spdx/parser/tagvalue/test_relationship_parser.py b/tests/spdx/parser/tagvalue/test_relationship_parser.py index 83a3d19d5..212d1c261 100644 --- a/tests/spdx/parser/tagvalue/test_relationship_parser.py +++ b/tests/spdx/parser/tagvalue/test_relationship_parser.py @@ -3,6 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.relationship import Relationship, RelationshipType from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone @@ -16,13 +17,13 @@ [ ( "\n".join( - ["Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-File", "RelationshipComment: This is a comment."] + [f"Relationship: {DOCUMENT_SPDX_ID} DESCRIBES SPDXRef-File", "RelationshipComment: This is a comment."] ), - Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-File", "This is a comment."), + Relationship(DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, "SPDXRef-File", "This is a comment."), ), ( - "Relationship: SPDXRef-DOCUMENT PATCH_FOR NOASSERTION", - Relationship("SPDXRef-DOCUMENT", RelationshipType.PATCH_FOR, SpdxNoAssertion()), + f"Relationship: {DOCUMENT_SPDX_ID} PATCH_FOR NOASSERTION", + Relationship(DOCUMENT_SPDX_ID, RelationshipType.PATCH_FOR, SpdxNoAssertion()), ), ( "Relationship: SPDXRef-CarolCompression DEPENDS_ON NONE", diff --git a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py index 6170062c5..8136a4c50 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.parser.tagvalue.lexer import SPDXLexer @@ -26,7 +27,7 @@ def test_tokenization_of_document(lexer): "SPDXVersion: SPDX-2.1", "DataLicense: CC0-1.0", "DocumentName: Sample_Document-V2.1", - "SPDXID: SPDXRef-DOCUMENT", + f"SPDXID: {DOCUMENT_SPDX_ID}", "DocumentComment: Sample Comment", "DocumentNamespace: https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301", ] @@ -39,7 +40,7 @@ def test_tokenization_of_document(lexer): token_assert_helper(lexer.token(), "DOC_NAME", "DocumentName", 3) token_assert_helper(lexer.token(), "LINE", "Sample_Document-V2.1", 3) token_assert_helper(lexer.token(), "SPDX_ID", "SPDXID", 4) - token_assert_helper(lexer.token(), "LINE", "SPDXRef-DOCUMENT", 4) + token_assert_helper(lexer.token(), "LINE", DOCUMENT_SPDX_ID, 4) token_assert_helper(lexer.token(), "DOC_COMMENT", "DocumentComment", 5) token_assert_helper(lexer.token(), "TEXT", "Sample Comment", 5) token_assert_helper(lexer.token(), "DOC_NAMESPACE", "DocumentNamespace", 6) @@ -285,7 +286,7 @@ def test_tokenization_of_annotation(lexer): "AnnotationDate: 2010-01-29T18:30:22Z", "AnnotationComment: Document level annotation", "AnnotationType: OTHER", - "SPDXREF: SPDXRef-DOCUMENT", + f"SPDXREF: {DOCUMENT_SPDX_ID}", ] ) @@ -299,13 +300,13 @@ def test_tokenization_of_annotation(lexer): token_assert_helper(lexer.token(), "ANNOTATION_TYPE", "AnnotationType", 4) token_assert_helper(lexer.token(), "LINE", "OTHER", 4) token_assert_helper(lexer.token(), "ANNOTATION_SPDX_ID", "SPDXREF", 5) - token_assert_helper(lexer.token(), "LINE", "SPDXRef-DOCUMENT", 5) + token_assert_helper(lexer.token(), "LINE", DOCUMENT_SPDX_ID, 5) def test_tokenization_of_relationship(lexer): relationship_str = "\n".join( [ - "Relationship: SPDXRef-DOCUMENT DESCRIBES NONE", + f"Relationship: {DOCUMENT_SPDX_ID} DESCRIBES NONE", "RelationshipComment: This is a comment.", "Relationship: DocumentRef-extern:SPDXRef-Package DESCRIBES NONE", ] @@ -313,7 +314,7 @@ def test_tokenization_of_relationship(lexer): lexer.input(relationship_str) token_assert_helper(lexer.token(), "RELATIONSHIP", "Relationship", 1) - token_assert_helper(lexer.token(), "LINE", "SPDXRef-DOCUMENT DESCRIBES NONE", 1) + token_assert_helper(lexer.token(), "LINE", f"{DOCUMENT_SPDX_ID} DESCRIBES NONE", 1) token_assert_helper(lexer.token(), "RELATIONSHIP_COMMENT", "RelationshipComment", 2) token_assert_helper(lexer.token(), "LINE", "This is a comment.", 2) token_assert_helper(lexer.token(), "RELATIONSHIP", "Relationship", 3) diff --git a/tests/spdx/parser/tagvalue/test_tag_value_parser.py b/tests/spdx/parser/tagvalue/test_tag_value_parser.py index 47778d2df..f9b6d16cd 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_parser.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_parser.py @@ -6,6 +6,7 @@ import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.document import Document from spdx.model.relationship import Relationship, RelationshipType from spdx.parser.error import SPDXParsingError @@ -75,7 +76,7 @@ def test_document_with_mixed_values(): parser = Parser() document_str = "\n".join( [ - "SPDXID:SPDXRef-DOCUMENT", + f"SPDXID:{DOCUMENT_SPDX_ID}", "FileName: File without package", "SPDXID: SPDXRef-File", "PackageDownloadLocation: https://download.com", diff --git a/tests/spdx/validation/test_actor_validator.py b/tests/spdx/validation/test_actor_validator.py index 313efa809..bd9803707 100644 --- a/tests/spdx/validation/test_actor_validator.py +++ b/tests/spdx/validation/test_actor_validator.py @@ -6,6 +6,7 @@ import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.actor import ActorType from spdx.validation.actor_validator import validate_actor from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage @@ -14,7 +15,7 @@ def test_valid_actor_person(): actor = actor_fixture() - validation_messages: List[ValidationMessage] = validate_actor(actor, "SPDXRef-DOCUMENT") + validation_messages: List[ValidationMessage] = validate_actor(actor, DOCUMENT_SPDX_ID) assert validation_messages == [] @@ -29,7 +30,7 @@ def test_valid_actor_person(): ], ) def test_invalid_actor(actor, expected_message): - parent_id = "SPDXRef-DOCUMENT" + parent_id = DOCUMENT_SPDX_ID validation_messages: List[ValidationMessage] = validate_actor(actor, parent_id) expected = ValidationMessage( diff --git a/tests/spdx/validation/test_creation_info_validator.py b/tests/spdx/validation/test_creation_info_validator.py index 2b4a65d5f..a015d258e 100644 --- a/tests/spdx/validation/test_creation_info_validator.py +++ b/tests/spdx/validation/test_creation_info_validator.py @@ -6,6 +6,7 @@ import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.validation.creation_info_validator import validate_creation_info from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import creation_info_fixture @@ -24,12 +25,12 @@ def test_valid_creation_info(): ( creation_info_fixture(spdx_id="SPDXRef-doc"), "SPDXRef-doc", - 'spdx_id must be "SPDXRef-DOCUMENT", but is: SPDXRef-doc', + f"spdx_id must be {DOCUMENT_SPDX_ID}, but is: SPDXRef-doc", ), - (creation_info_fixture(data_license="MIT"), "SPDXRef-DOCUMENT", 'data_license must be "CC0-1.0", but is: MIT'), + (creation_info_fixture(data_license="MIT"), DOCUMENT_SPDX_ID, 'data_license must be "CC0-1.0", but is: MIT'), ( creation_info_fixture(document_namespace="some_namespace"), - "SPDXRef-DOCUMENT", + DOCUMENT_SPDX_ID, "document_namespace must be a valid URI specified in RFC-3986 and must contain no fragment (#), " "but is: some_namespace", ), diff --git a/tests/spdx/validation/test_document_validator.py b/tests/spdx/validation/test_document_validator.py index 6d829db79..c58916c43 100644 --- a/tests/spdx/validation/test_document_validator.py +++ b/tests/spdx/validation/test_document_validator.py @@ -6,6 +6,7 @@ import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.document import CreationInfo, Document from spdx.model.relationship import Relationship, RelationshipType from spdx.validation.document_validator import validate_full_spdx_document @@ -82,8 +83,8 @@ def test_spdx_version_handling(creation_info: CreationInfo, version_input: str, @pytest.mark.parametrize( "relationships", [ - [Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-File")], - [Relationship("SPDXRef-File", RelationshipType.DESCRIBED_BY, "SPDXRef-DOCUMENT")], + [Relationship(DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, "SPDXRef-File")], + [Relationship("SPDXRef-File", RelationshipType.DESCRIBED_BY, DOCUMENT_SPDX_ID)], ], ) def test_document_describes_at_least_one_element(relationships): @@ -101,9 +102,9 @@ def test_document_does_not_describe_an_element(): assert validation_messages == [ ValidationMessage( - 'there must be at least one relationship "SPDXRef-DOCUMENT DESCRIBES ..." or "... DESCRIBED_BY ' - 'SPDXRef-DOCUMENT"', - ValidationContext(spdx_id="SPDXRef-DOCUMENT", element_type=SpdxElementType.DOCUMENT), + f'there must be at least one relationship "{DOCUMENT_SPDX_ID} DESCRIBES ..." or "... DESCRIBED_BY ' + f'{DOCUMENT_SPDX_ID}"', + ValidationContext(spdx_id=DOCUMENT_SPDX_ID, element_type=SpdxElementType.DOCUMENT), ) ] @@ -115,7 +116,7 @@ def test_duplicated_spdx_ids(): file_fixture(spdx_id="SPDXRef-2"), file_fixture(spdx_id="SPDXRef-3"), ], - packages=[package_fixture(spdx_id="SPDXRef-2"), package_fixture(spdx_id="SPDXRef-DOCUMENT")], + packages=[package_fixture(spdx_id="SPDXRef-2"), package_fixture(spdx_id=DOCUMENT_SPDX_ID)], snippets=[snippet_fixture(spdx_id="SPDXRef-2"), snippet_fixture(spdx_id="SPDXRef-3")], ) @@ -126,7 +127,7 @@ def test_duplicated_spdx_ids(): assert validation_messages == [ ValidationMessage( "every spdx_id must be unique within the document, but found the following duplicates: ['SPDXRef-2', " - "'SPDXRef-3', 'SPDXRef-DOCUMENT']", + f"'SPDXRef-3', '{DOCUMENT_SPDX_ID}']", context, ) ] diff --git a/tests/spdx/validation/test_package_validator.py b/tests/spdx/validation/test_package_validator.py index 5ebca4672..02f4c3942 100644 --- a/tests/spdx/validation/test_package_validator.py +++ b/tests/spdx/validation/test_package_validator.py @@ -8,6 +8,7 @@ import pytest from license_expression import Licensing +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.relationship import Relationship, RelationshipType from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone @@ -63,7 +64,7 @@ def test_invalid_package(package_input, expected_message): expected_message, ValidationContext( spdx_id=package_input.spdx_id, - parent_id="SPDXRef-DOCUMENT", + parent_id=DOCUMENT_SPDX_ID, element_type=SpdxElementType.PACKAGE, full_element=package_input, ), diff --git a/tests/spdx/validation/test_relationship_validator.py b/tests/spdx/validation/test_relationship_validator.py index 1d5a493c7..3b68df0c5 100644 --- a/tests/spdx/validation/test_relationship_validator.py +++ b/tests/spdx/validation/test_relationship_validator.py @@ -6,6 +6,7 @@ import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.document import Document from spdx.model.relationship import Relationship, RelationshipType from spdx.model.spdx_no_assertion import SpdxNoAssertion @@ -17,9 +18,7 @@ @pytest.mark.parametrize("related_spdx_element", ["SPDXRef-Package", SpdxNoAssertion(), SpdxNone()]) def test_valid_relationship(related_spdx_element): - relationship = Relationship( - "SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, related_spdx_element, comment="comment" - ) + relationship = Relationship(DOCUMENT_SPDX_ID, RelationshipType.DESCRIBES, related_spdx_element, comment="comment") validation_messages: List[ValidationMessage] = validate_relationship(relationship, "SPDX-2.3", document_fixture()) assert validation_messages == [] @@ -57,11 +56,11 @@ def test_unknown_spdx_id(spdx_element_id, related_spdx_element_id, expected_mess "relationship, expected_message", [ ( - Relationship("SPDXRef-DOCUMENT", RelationshipType.SPECIFICATION_FOR, "SPDXRef-Package"), + Relationship(DOCUMENT_SPDX_ID, RelationshipType.SPECIFICATION_FOR, "SPDXRef-Package"), "RelationshipType.SPECIFICATION_FOR is not supported in SPDX-2.2", ), ( - Relationship("SPDXRef-DOCUMENT", RelationshipType.REQUIREMENT_DESCRIPTION_FOR, "SPDXRef-Package"), + Relationship(DOCUMENT_SPDX_ID, RelationshipType.REQUIREMENT_DESCRIPTION_FOR, "SPDXRef-Package"), "RelationshipType.REQUIREMENT_DESCRIPTION_FOR is not supported in SPDX-2.2", ), ], diff --git a/tests/spdx/validation/test_spdx_id_validators.py b/tests/spdx/validation/test_spdx_id_validators.py index 12696a4de..1a36f0b99 100644 --- a/tests/spdx/validation/test_spdx_id_validators.py +++ b/tests/spdx/validation/test_spdx_id_validators.py @@ -5,6 +5,7 @@ import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.validation.spdx_id_validators import ( get_list_of_all_spdx_ids, is_external_doc_ref_present_in_document, @@ -35,7 +36,7 @@ ) -@pytest.mark.parametrize("spdx_id", ["SPDXRef-DOCUMENT", "SPDXRef-File1", "SPDXRef-1.3-3.7"]) +@pytest.mark.parametrize("spdx_id", [DOCUMENT_SPDX_ID, "SPDXRef-File1", "SPDXRef-1.3-3.7"]) def test_valid_internal_spdx_ids(spdx_id): assert is_valid_internal_spdx_id(spdx_id) @@ -63,7 +64,7 @@ def test_is_spdx_id_present_in_document(): assert is_spdx_id_present_in_document("SPDXRef-File1", DOCUMENT) assert is_spdx_id_present_in_document("SPDXRef-Package2", DOCUMENT) assert is_spdx_id_present_in_document("SPDXRef-Snippet1", DOCUMENT) - assert is_spdx_id_present_in_document("SPDXRef-DOCUMENT", DOCUMENT) + assert is_spdx_id_present_in_document(DOCUMENT_SPDX_ID, DOCUMENT) assert not is_spdx_id_present_in_document("SPDXRef-file2", DOCUMENT) @@ -76,7 +77,7 @@ def test_list_of_all_spdx_ids(): TestCase().assertCountEqual( get_list_of_all_spdx_ids(DOCUMENT), [ - "SPDXRef-DOCUMENT", + DOCUMENT_SPDX_ID, "SPDXRef-File1", "SPDXRef-File2", "SPDXRef-Package1", @@ -146,7 +147,7 @@ def test_invalid_spdx_id(spdx_id, expected_messages): @pytest.mark.parametrize( "spdx_id", - ["DocumentRef-external:SPDXRef-File", "SPDXRef-DOCUMENT", "SPDXRef-File1", "SPDXRef-Package1", "SPDXRef-Snippet1"], + ["DocumentRef-external:SPDXRef-File", DOCUMENT_SPDX_ID, "SPDXRef-File1", "SPDXRef-Package1", "SPDXRef-Snippet1"], ) def test_valid_spdx_id_with_check_document(spdx_id): validation_messages = validate_spdx_id(spdx_id, DOCUMENT, check_document=True) diff --git a/tests/spdx/writer/rdf/test_relationship_writer.py b/tests/spdx/writer/rdf/test_relationship_writer.py index 483f0cbca..9257976e4 100644 --- a/tests/spdx/writer/rdf/test_relationship_writer.py +++ b/tests/spdx/writer/rdf/test_relationship_writer.py @@ -3,6 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, Literal, URIRef +from spdx.constants import DOCUMENT_SPDX_ID from spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx.writer.rdf.relationship_writer import add_relationship_to_graph from tests.spdx.fixtures import relationship_fixture @@ -13,7 +14,7 @@ def test_add_relationship_to_graph(): graph = Graph() add_relationship_to_graph(relationship, graph, "docNamespace", {}) - assert (URIRef("docNamespace#SPDXRef-DOCUMENT"), SPDX_NAMESPACE.relationship, None) in graph + assert (URIRef(f"docNamespace#{DOCUMENT_SPDX_ID}"), SPDX_NAMESPACE.relationship, None) in graph assert (None, SPDX_NAMESPACE.relationshipType, SPDX_NAMESPACE.relationshipType_describes) in graph assert (None, SPDX_NAMESPACE.relatedSpdxElement, URIRef("docNamespace#SPDXRef-File")) in graph assert (None, RDFS.comment, Literal(relationship.comment)) in graph diff --git a/tests/spdx/writer/tagvalue/test_creation_info_writer.py b/tests/spdx/writer/tagvalue/test_creation_info_writer.py index 161d4047e..be5d023d1 100644 --- a/tests/spdx/writer/tagvalue/test_creation_info_writer.py +++ b/tests/spdx/writer/tagvalue/test_creation_info_writer.py @@ -6,6 +6,7 @@ import pytest +from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.document import CreationInfo from spdx.writer.tagvalue.creation_info_writer import write_creation_info from tests.spdx.fixtures import actor_fixture, creation_info_fixture @@ -19,7 +20,7 @@ [ call("SPDXVersion: SPDX-2.3\n"), call("DataLicense: CC0-1.0\n"), - call("SPDXID: SPDXRef-DOCUMENT\n"), + call(f"SPDXID: {DOCUMENT_SPDX_ID}\n"), call("DocumentName: documentName\n"), call("DocumentNamespace: https://some.namespace\n"), call("DocumentComment: documentComment\n"), @@ -39,7 +40,7 @@ ( CreationInfo( spdx_version="SPDX-2.3", - spdx_id="SPDXRef-DOCUMENT", + spdx_id=DOCUMENT_SPDX_ID, creators=[actor_fixture()], name="Test document", document_namespace="https://namespace.com", @@ -48,7 +49,7 @@ [ call("SPDXVersion: SPDX-2.3\n"), call("DataLicense: CC0-1.0\n"), - call("SPDXID: SPDXRef-DOCUMENT\n"), + call(f"SPDXID: {DOCUMENT_SPDX_ID}\n"), call("DocumentName: Test document\n"), call("DocumentNamespace: https://namespace.com\n"), call("\n"), From 91bb7442ed41f59ca0a01d00bf28f5d3cbb5869c Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 3 Apr 2023 15:46:20 +0200 Subject: [PATCH 042/354] [issue-558] add optional feature to generate a relationship graph Signed-off-by: Meret Behrens --- README.md | 16 ++- assets/SPDXJSONExample-v2.3.spdx.png | Bin 0 -> 147064 bytes pyproject.toml | 1 + src/spdx/clitools/pyspdxtools.py | 32 ++++-- src/spdx/document_utils.py | 20 ++-- src/spdx/graph_generation.py | 76 +++++++++++++ tests/spdx/test_document_utils.py | 10 +- tests/spdx/test_graph_generation.py | 155 +++++++++++++++++++++++++++ 8 files changed, 295 insertions(+), 15 deletions(-) create mode 100644 assets/SPDXJSONExample-v2.3.spdx.png create mode 100644 src/spdx/graph_generation.py create mode 100644 tests/spdx/test_graph_generation.py diff --git a/README.md b/README.md index a56cc8f3e..3aa762980 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,11 @@ This library implements SPDX parsers, convertors, validators and handlers in Pyt # Features -* API to create and manipulate SPDX v2.2 and v2.3 documents. +* API to create and manipulate SPDX v2.2 and v2.3 documents * Parse, convert, create and validate SPDX files * supported formats: Tag/Value, RDF, JSON, YAML, XML +* visualize the structure of a SPDX document by creating an `AGraph`. Note: This is an optional feature and requires +additional installation of optional dependencies # Planned features @@ -78,6 +80,18 @@ instead of `bin`. * For help use `pyspdxtools --help` +3. **GRAPH GENERATION** (optional feature) + +* This feature generates a graph representing all elements in the SPDX document and their connections based on the provided + relationships. The graph can be rendered to a picture. Below is an example for the file `tests/data/formats/SPDXJSONExample-v2.3.spdx.json`: +![SPDXJSONExample-v2.3.spdx.png](assets/SPDXJSONExample-v2.3.spdx.png) +* Make sure you install the optional dependencies `networkx` and `pygraphviz`. To do so run `pip install ".[graph_generation]"`. +* Use `pyspdxtools -i --graph -o ` where `` is an output file name with valid format for `pygraphviz` (check + the documentation [here](https://pygraphviz.github.io/documentation/stable/reference/agraph.html#pygraphviz.AGraph.draw)). +* If you are using a source distribution, try running + `pyspdxtools -i tests/data/formats/SPDXJSONExample-v2.3.spdx.json --graph -o SPDXJSONExample-v2.3.spdx.png` to generate + a png with an overview of the structure of the example file. + ## Library usage 1. **DATA MODEL** * The `src.spdx.model` package constitutes the internal SPDX v2.3 data model (v2.2 is a simply a subset of this). diff --git a/assets/SPDXJSONExample-v2.3.spdx.png b/assets/SPDXJSONExample-v2.3.spdx.png new file mode 100644 index 0000000000000000000000000000000000000000..1d050a166d51079aa239eb5e17365482fe566241 GIT binary patch literal 147064 zcmY(Lby$?!*Y}6+knR)_rBu300g+DWl1}MHkdih4>F(|tQbOtOl9C2t=y>;>bM*JT z;~!pf4Kw@Rd&PIH_1T6gDM;gBQeZ+L5FA+4kKY6@X;Q{_aHI|c> zg51IXq(k#QK_GMxSt)Tf_vGCL4|lco1<~6x{wnjN_c6!>G3B!P5@O|c?kfQ~R)vFDNt!ggSblN?IUzU^@@)l^6P{tM7j#y#k6XPSB#WS)o{Q19iS$ZU7>!O|{!uKx^4u@!>d!b)vP zR>Nut*3&8o1x5vj3>FBvIfx&W)+)3W3_oBBzrsS7>uI+!n9wMvOxYMkNW$fF!NJuF zdcsa=IK@59O?*3h@~cwYrezMb-iAUKJ0z^}z72w}V26*ow1k1waADy-u9cr>QH4DsR?4~>?rV?$pXve19n>v;17{QH}y|1?KK;9}^QD@JG zEfpp0J+!2Sw{%W7%b6IseTrx|rY8JBl3vDC``XiXM3>zqVqsq+!>;3aT+PDLa(Hw! zU3x#OC(R-q>v>1S1IZxrksfhX{7~e|_IiIFLqr5g{OZ|*e%ifz87?i-Dy7J8ae(^YJ~cJ}qA!^~fNQ+nE%N8d4 z&krzsSG);wqG)*rPn7rxGS2=X6l`q*NIe+3{JQoRl}K7N4G_^N^rO>mXs&e6^>NL!G@R+ z{!R^REJfC0Qe3A*-t0S~kYFysm~EvMyF^LJV8TNIZd1Mq45o3x|81QVL;3c$p}KmP z#OtC`Toui{Txr^=DQ4t~#4!vuVQSC&-eU~y$uwtLa&oH2S?~0&U33bTK8lIKN~2CH z70^#sC47rA=v~wBPiOZY^$+||Nvr68Mf}UmOybOQ;#fQ|JtvR(;JHfclqtl8UfhI_ zJs}dAV#LcJ+=(c&U6<>#Tm?OS@$vMkr^#%!mZIji=+BT)TTCQidk;u9io}-e^F3Nf z0_Ey$9mVY^&%P=U_j4j;4WcKA$(QpdlqlB6zc&gMKHV77E`(l)aQ~hO4}Q1%Jk{F> z%L2RT@*dXQs)Sow#s+Wq1ZfBjj^jJ*JQA;67b~(gzo4(}|A&@hKa{XAkJ3gh+*B&xwSuQhEOGCAN{@{R%@G8M3l1 z!Su-*+ulj)iKv;&Fn_}x(!kHZ&EsC~nVRDBbEU+x4KqQ^R!NDHU>r5cZ>GR5hsWDPc2pq2nXLe<6b)P~R6{Q!%tF>c~!DbeV!>~v!V^kX>z3)svd3e+;M z5GW)9X7QEC@zqf8tIVlIhQFP|zlg{mdR6WE1{`byS?{Uz$j}QDG7GNpB>@<(qI?k+ zcQnCrCBkdRwCGoP!R>Z9{4~Bijg)~p|E9Q1Ul|HYBN{=}o#`hDJ<**4zPbyV8WI$g zCViH6yeHuB%*~5*G&GJ^#RJvItT$QC#=T@8A{P|A1DjP;_;R7Jh|rDzvny^2s!zPO zvECk+H0Pa`R8;Em>PFi~Mu}QYc(5=qpwK`4L4I!15q&~d1F4FcuKoQo)gVf$mbi}t z1jIilgVd%~Xd9wMO7VE{x=O6Y8YLy;*iB^F#mK=*SNS!4J~0)>QJ?WHJwhr> z#em=xy1r@f7q2+eg&trZ7qB4`?@l7W+fM&>tD%9W)<#LqAUJ`rCM7Yi8%^Tn9nhDe z%KX>hx3lgO1-PuC_cKZx(g5c;`=BOffd(tb#>3-L`G?@jK-7YrZv-%>(cxjL zH4XLl;(QB{f{e^|Y41y}v+hvp}l|)6P zy$Bi@g~L!AxJ{eXWRl3qA3R-XrwhLf>2~-Dd%3EpW$^)f$97Dutj{JsSlkWZD6aEBsh&kA=0wZXqwMyZc3Qh``*{5$=Gcz$acLVE>C zTBmsIkWs4i!e(B6AEMF}=O5*=y~ipSB)`5sP&cZQARS%U_T4N{!~)-Dgx<*Mtzq9# z2%9Larz=l-l{J}iQ|40HFNYOk;_^q2#?M$UsmEM?&CERd#>N`q(`q9b^49(EzBP6c zjoBB3_K^oLq_;r^u+&Ig+N3RH)FyQ@Vrl`Nv97a7)LO$e?YxnU_AJS54K(D8UJP7I zTtk@;Bv-fCvdRb?efnobIG8`Y3rneO38*YpTn20=NK2?`BDP%-VOu-9POt8&ZN= z91A_-`T?`3h?(pvPR`dMkK2Ck)?X&EVB$N`#BPJYPWiLrIW#uqPrCGX% zmgR>YS=;L%D)OR`z#h9K4E=OJ*H+4wHSWp?og>CC#6T9>A4yAxh*s`^yp&K-%>(O zKFDYM;dD=Apvkp6c#=p-);j!Jf62&4-}uJq_-K@%SEJOA+8%}?lS>Lw8OP?=l}n+- zjL>bAD=HDHId;;;W71@g@DIxm9|b`3Wnj6q zhEo1nzA(wXc2BGjpY6-Y1{z{RBB>5-T&$Plb>}$TyY?QRf<{rfcgsR4e%Ep8Ng4$= z4(8ZGylXm1%3Jk=YOZ!z-?L3rITULK)p)Q_87Dr}cTrMO;h5Ge+eU*B^+f5|5VC25xc8F zFj7Fo^=?!qx-k%^P`Xr7Q+WHsQ}xi9rCW9vrxxrki5fbAp z2!zv`q+2|eDwBclL%0#G zsIS;*E@P%bIV)LC4mb}9_ZBYHUjs=G`m`V4>}xB%((A7=9w6+DTT1D@{x7f8PR8 zu#nAL*D~V~-9woPPI{f5Eq!X1n`2$7Od7&UeJr}96drV)(mtfLavwhWD)6E5ax=PEYTN~Z@Vt1kqg0!lwNM_Z z+tcM0Me%BNb&E1HMP~qxG}~@|Z92mFC>`}Dw4L7LlgLv-7`F>O>>%7$-D)kWLZ5mQ zZ_8k*LB#VG^WS<_`K=ZVcG!AKvAy3y8QFTvZTMOyMU?jI-Ih0wJfn~EM;V7Ml-m(oT_kK z?ItYE+7YO%tW?s~jYzU@Ay4A9x0|SaHY8Lv;W?%6WovUALH>+jLq0{Irjy4i5w&hE zGK`S<=Xd6`Zv}k3H(jI#-?C*tEg!iXUrkq-NEfXuoRU>nTaGhNkq~tYj4?rQ~e|uku1`id7;yw66!lmRI!?^~|&^*-sB#JkySB_be~d#U1oq$wx^!g3mTZLpCXw{MBEF z1xwRDUx1!597g+z&AKl@gCNtY)+;kmRNuNeG0VW^WL?S@w_xgH#k$p9UEzWZww+bd zv6)Nv%0A|?g2FB60@${&F-1}8Q~jq@O>?NP`X`^*S5w!eZnZI?@Bs1eH*3Aj+k|aX zQf+uTYG*D^c&^zHMl6W4TSlt;*}jv_T;OnGrIrRSMr*Dmp>({kl*U>B)~vvG>T@-V zuKvuob*`-l?Ufpumu35}NA&;cJ;J9&h2QF|zKmZF-O21xyUC1MmxaB4{dL!@=Iw&Z zR9NXwrOnLKi|gZ|u7k6_7N4uNRImMe@?-Y}1)C-WbZTwxL7sY@?oLqkn8q6s`XZ=OBSp8nz=IU3g>cPz!siRaRA@_zPX_R+Y^D z?xwWw1;?&aGNnNo*q&}PQ~8{|ei;#g&TYX(a|%x@8MZSOo@@DbO3zJJQZjINu1+x+ zhw{N(oxQ!&#V27@Ww|)kdr1Qi>Xv+)Y?fN|u6Vi`oy?1Rc2q4 zYMJ9Z2dkNQ>?r4MCe_QH&|TZdGz=(6C0a6q_?j1W{;4jsn#8;KU42$(oqdevU|4N zVWq=$>Sj3*k3eLntE=nxs2m3qYn8)_1OlBs6sFN};&Ht3JrGZ1dSz$FvU@Wv{Geeo zdt)OhXJb+)XRBuFo7JY%7uKdic@Ix>tvFw*kD9n-Z_5{7x_;6&@)7dTD~Z#L}+%9*Y@ zs?scxeC(+US`+Pgg^~2#me6|c`;JwKz*mz6VjLWtr)K?R4ZnXpZXI?-O@!9uUb|{) z#o1zf7km@^{^NDZbtc(7!N2jur417~d+Up4_J-Her`fJ>ro;Uv;~?C9 z3Y&B^O{9ETX=&U_XGkA7S%~+#^3+Mvw}t!uW4GXSv5$)A1vuKjcg>AFOyy)21#Lo?WUQQ|-q(~cgY%%- zDa|h{i&xHik#dOKU@9js{{@S^o^ED9#_%-*t!BdSX=eJ@N0wSq=a(8OQ9T(S|EpSO zjdqu!FVSek4xwkuEtgjAw4Ugt;p_n$4)>cZZ7+clBS2QWBdwio=Np`wng_x;TKH=B z2yqrD?YBmA_%@TB4ndqp;b=aT=xDb0+0m)rE-X?~R}a#$YhdEJnbfiGa+%T#IUW*i zm9wQ1@#YK0rN->!JOp9f*>b@>&F_{ULMJGAm0fqQ3~Ewtza(;faCgfwD6qrIs#{+^ z;G(LcayV@gosp4&P`BW!V{^H`&{W~PrSj_QQ-BU5VI6_okm8`DQ)k!3+j=pe zuy+kY~a)ySgQECb^?5dT!$CZq8 zB`aM%sJF^y9p#=aZ0jQJ&%CgavDFW9H|LgXVcvq;#OqE9GUDHQU>1M2904a<2vNt5{pszQ-%88w)Aabe z<*)JaXb`O?SKFlHJjJxAA3uJu+p7L7rOvfX!87HO?>uY0^MSOL`NE1cj?+B1Sxn!& zS^1)=-`>a38Zl9%X|gj}a{gV>cQog;#wKrWPow~b;IdGuS^zaU99LCr=fv*+`Yf*# z2DgH>%}tZN*&05FWeCJ@{l}Mb)}8k|scwrN__1~uvA3m1XywmL-@ zt>;}F4nQv$p8OhNuDP)s%U!|qJC_XU>rdtx<8-ia9hY!;%PO0(;U`MgLz{h~tT)W%0>0#?n-H*z(Z zS}Nl(#EE zq{h85^ygPgcTr#?sScoLG^{(}H(E!FUIz$}LB3UNcjzK}iJbt)6?YES8)B^7rrK9K=8IjDB9ba@bfB1ko?>cAu zkd^iQ*p`%n0&Z!;28GQ+BX?~-NTC^)6#9NQE|6_BJNYq({f14~1~#@D7wlVDnI8h= zLwLAiy|43Emz_xj$nDL69})y)g!7;|*GgS>QV@^WL(zRN$I>43Tie)tBUBW6=e6IE zH#g^acXPJ-*x&-Q)^;vf#~xZUcQ!>i^ZPiq!W4t*6LZ#4e5;iE<{-_?fx*jHRQYud zdt`#SI5in(Qe=B3KD%Epr$>H|c#O=Y3VU(7?dzJFoA=~Cmy9kfe005xCffFEBx}W4 zAok0bpnvwP<;t$e=ed1OPEG=^JeKULZ-2#||-*Na7(K5A%a_`PTEr*nIfCmJ@iY3-C!TS~8?smWZ{ za#^^xvGJjEC8oxDD%Bw+?%LO{n0kGE-Im=6I2ty4jDGJfEuLN@Af#2aDVl3r;HTxyDIIbxNoP{`BAB3QexsG1_pU~`H%7O z%#EdegDHY0eXM$oY8!(oj~TYBLJ4(OYoT)oes@TE3!DC&GZzL8xWQ2&;re&qo6}veO?@Qry#Te&OGq!Z+x$qu>a>c^fsW>E zli5I`);|ga_~S(vhc7*N#uT^387n^^D((!LKIN3q4@# zO_o-{!F~Xm1Z+;z!n#gvK@lwdai1Hk9@cF=U%S~b)baajVa1d;OYX1s>ax^o(cPx? z)%v#Wl_8}@haY2}>hZ#CD3xt%Ypa4b9*FDpi_J9q8gCu?#9T|bu+r3X`2zQoz0$Ff zXg6?t%-2VDBbm=D-hkq0VZT-Y^Rg63hM78hgCduf$#v}K`~7r8#{)YGraQ6-=M5X!1k`wG$vn=;^FU=T@D{Qdj)+9ySk zd$EHk;CGsUfJq-~FA2r8q{a=&&dvP+1e);}s+z-N1`W=KHExS6@*L1{+bd4iSOYt} zKGD8LQPwT?;^>!dQ$2&obs%Y)CGD_lm5V{DJw*}U`GeFH4mJ%G7`3yDl=jWB<=5oq z$@Gvlpc6DZPGT9Qf7Cm!YVVzyF4dJ*yA33Aza4o_S~I&3Um$LXfvivd)h%?Ahy*UvYBga$$9V#3af-utNPpbgxlP7tK1S)>dtc_QCt|W5V}3R{02;HRXsCn zQ+6xtJYI$1(c(h%3Z+vD(3q>PNrmm8GciOs`gy@aluczC$yU(TpZNclMlgI!D@1H0 zPtvl@iKLl5SKYVYncQzLHY?nZj1zLh;thNoq)(x~H=d9-kIfXckj_}nvWkj(SR|}% zKfXM6?4fpB{@usXGm<4;VKI`aVBeaa4)Hthq~-KHvADk86z$2CPcl9ZXr}{4Z1|d_ zS>L{hc17g&+yv6L2=$sW4(Fr+*U>46?L~`A4b;WO<@_kxF9L(` z0o~)rk6rr@fP#UDfsZP(H8nGzZ#kPMG<2>wfwBnp4L~@aBO&| z)Y^-o*j89`uJLWLjy}iqmNTMQ{I;_Bwzy`zC~;3o-SPB0|L=c#c=T#E2dFxYMG5NQJquKS!c!YQV%EM65Xmqg_3Lpu+5>lfcL#Sypj&Xht=WnRft&l& zr%w-iL~rl;-Ru|$LTN#FEA3|29RD8c>&p8)3+r#;GQzcqdc~oBBHCd@=On>7%;8K5k3ENTD*N=K#Wwug1rXZ(vCMDXo=ySF(>_QDXR#EbTHz#8V=>s%+ z%I${uSEqZOpkX5D>v*qj(ep8A)xm{BMtyy~`cQ4^Nz&3aDyZ{14}8xAufaaP(iZ&q zozES=mR_>a_Ubjei{JQ?o9}gmvCpm^tU{PQ9!tNB^qm+4)c++Lw1TeK{@W;%W3!%1 zjkAmJ1+}Bmev{{2ct0d^g&p@sTnb*pAwZ1T$)<(>&Yj z+!;2+RHEF4a!3E8y6yQU^-9oEUf-HVB~6CBc<{kD1UlF^*42xq0dM0tfgBVoAq@ra>eKCinZV;9?vk&!50RBjqVY zyxn&%z@94W=*(^T419ft_K8`sTkxPc5WJ^5*8qqCPHZGf9vh3AK_CDeW-asDIUCE0 z6uf$tL3rr7Ia`X37QH2VtWj*?w2+(oVBYs?uXk{;do@~g(P}|HiD$*F^-3>kXMd&& z4ZNuh6w%6RYD7sQz%7Z0iB~%DL~ZJ(zNOt=o3E{{E%!eg+8wt(@r0hY;!7C2#3KMv+$_=(z`w zaCXnR1?YGm^{xHa8iLVkm}HH!zh;0%3o&TW#q4f4e{XczLH5U{710F^M1Fqn^KxWF z1b+9!ba*@?%^PD;&3zRs7Cu!2loB4qE0mT+RCv=pm+{7p!Ns3f=-#KylR|L0_em)EaP;r{H|Zxvf4o zUu-0)=;%CFS6BZHDqY!^FF!P&{|v{NOAz*|h2Xa?EtT}pZHI_nXH47hG^|Dmn)XCd z6QCmlwen)J_%$Oir?`Ls#F=VKRUk!PS4x3SC#!z577&z-?S@LA5MKkWhe)`51_Am( zWMpK?q}NVK-M1BoUQh|GgCaZ@R7Ov*C2?s*SQSMsvQ14*d*y)a+1~+zY;U~cp5?8O z@73Iros$mpWxxE_r_WRUZZFiu=(EsMfAgc0 zHe_vVd%whufq^nQ>31)X{70`BTFO4P&rUkk?3qTpcwK>3PX#1~O{dn`>H-v8rL0R6 ztEa$E)SLCos05s4;NMg+w^!-3IY>y;nL0^EaM4v8)9jLOf0GpScP5GT;`P_@MaPiw zn>A)*4Rxj_{uHys++u@P{r%=+1%A-+x-TkfuBOgn>dQaqv0%m;VNZEdNCm{Z*|2W(xO z!%^$Nah7ZVBg;t&dK0tBWXAVv}D zLQDx1fmYk%&K^10nY=Xc6dhO{s~>AS}}EZC8E$R3I?KK<97N%=R%m z`#&Dn;FJd%NUES?(6xF5uU_BWT*CHh^KyU{SL>Lk`Ce`**yr(1yU%~lp*@@b&KMUe z)XK}MXoDx~l72?~zrx;&`(-w)^;2o{?;kvKM1H?@G4LxvukboU z@Zy=%yek)0<5+zq*W8*qDu0fZBVTIRJx-LNMA9YvSLWe3Xgo)uNOMQjkjGIeg^~;& z520NS!;(Yu)1F}?-=6ZGgHmL=CqjI7fLBsZcB^9HptR=jML`(gZmKYC0dnMXUtr>a zeB%2bKVE`MR7q@1}4;ZL_AHuY2BiPypN<(jGGt4>;c?=wC3jlm$G zB0eo}F;MhM;maOz zXEnLh_|R8Go5J$LTV+DKq+t8V3KMrcv^)h$hXpdh$s$4Pp*WsPKLSEg z-zyffHmjO3fc~gX)~<}x{if%7J%1$^HGs*6nmrs+{Y0)oTQXRh=AF;3Ry}B}MPU$5 zBgKb$Mp-hPq}|aS*0r_^y+s~$8VcInF3P~8_+0(qO%r#&=t5M9I>{vUlOx$LK`i_N zxf|2VD`inqCn#hjl(q=ugpT{rS$Em1ENv92WvhLLXSFoj+dY_Ub+Czg5qo{|SoZubg zdiHvVwx?%h(hI4Z&tUqu+~|T{0%*gEdxK7c@4Pl%O=DtyT&PACC!E$bGBOFm=tOM! zoU>X?MeUI)a#_TpOdx#uE31B|w22@W?iU?k{`fhY1eQD-V`!Zd1on=ML@BvsHCc#y zD{4_yZd)?oEV_Va!-GpV*}gOMWN}Pn+n`Y!4^{gn9|uDu;z~rHr$0DgyyeEn^e@Qp z+{}X?v@=77(P+gwjQF~vLri`U@iEH>#Kpz!ZroF*HCNYUyguqdw_U_GSrYlB&yhTq z+s^GHa8g`s%3CH$k2S6QW@Ysy7O2cpr901AsaLD2Mcg9!8MevgQOoltJN7BCLMTuy zadE&9I)O_|`X$Fc)UThzy=?wlyJtI?!<*wwK4DiqsDfUHUSc9Rl2dK=-?T z5)p`&(Xik^MB2&k@`#F%8PRj;>d9}VEJO3iAmJL4Yt)#uLL=|os7%%pO;{>pW-2LX zQs?aGi+5m*?(X8vBG>r~8>*-$dJ2BUDJTf)LNd=|Xk3e#^30}f#WK=aX~j#iB*g((s{V|UF6 zlsV{qMI(kp;BW|8lWRNcXW{5FCnSl}70R(~?oFoNn3n3!8fN8F$3#wrrE{Uco3CiML8l zu%{h1mV(?EC%YURT(G=mrW=vPNNj5n!1A&}x!Pglb6)Nj7kGd-8N0WicIW<=p>qBp z`|$nY=^m%Z4bjR%lM%Hj?!bz_Z9f^`hYyCdqBN%+9U?PU88W%h{Z z8|UmU>RiB6{B42vckV!A2G~OrU@T~O9YXH-8?lW3=qLTJre8!wpfsFzNLaA2e79r2 zm*TH(fOots4ohKYdFOaY_iYo&hG#k$N3}CIngYcOP(I>;9~b8J<&gPC@AHk5;rOwh zclehgG|=Dx#_P8#*IJ%c?^~SW!;t(sOKj;ypXyp%JFi|b(JK!boVV}pV+9D*BEk`AfOkTjxvf|xk= zbxng1M=TiO_}nppiHS3s>Yc|qCmhLCSA&Fl8%Rg^gZuz;>53bS2!Om|`Tfift%;~$ zSP?ROpVw77AK}T4aDL08=Y1adNq8z$fkn=LI~|k!@y)iNd$sH^87db}uj})cKo*MN z9IIZrk+%5?r$p>!r7TQGyh$v;2Zg*%W!_K7wd`FR{xRMY^lE~!6@10j7#mt6?;@CV!&xxMsqGev_WW&UuRjwbupRWGLz8W)eev z;V2EBcBP)l@ja=2QjXaLvM5y}{-@JVw0ff2g?y<-r}IfFXAJxLRG|x5bw-`(cr?Y0 ziOOZlltff`=#Q?g&bv%}U3}! zQ8%cg_&3I2S|GrDzB?At|H!IiB@H>;v!qwWp{0eIIW!DOe9G9!5#(BPPh85PiY~PF zj?T|R_ir@3mQ`ze(wffxyKd?YQt%4}zFtM;sS?Es=B5cBq`$7$!v56Tx(I*!+)-;{ zVj#m#g9PAy8Rq7av|RZYBp#(6LbAT}Qh8BaJROCl8g+$_T*8Iy$p^Os(RvhILsNel z!VftGXL`D%pzJB5WHZ2Bx!X5-Cd9*nXnEvekRQ&4_`ID3?UZMH1F`c{V&m$*l0oG# zdT~7&;ZiIF7(HwTPsfTszNA6gvsMQXjTFA#G2u`Pud42H0r7P$)9QDat=j_@9}3N9 zVn3;(K7T`0R8&Nz8t=Gl6cdh1^BE{dQ zye)o{uk(6_3XuKciHXMHRy2xE`IOM1{`VU&K<58*k3muKXE;5g;p=h=3OX39+{${w zM_yin(;EDWM8@0s4Wo9vU`l~_eSE?Q*;mrFQK?n z_d47UZrD-)*D@p)xCD{zZS#w(qPRt(4wDgZy}yTHk<>X8Gtumw$awVry#;5|p4m{{ z?KcAMW*4sB5)1~7xqcb8Kr=V0X|GR$)3zT4h6sokUj&xVDjD-ll97-(t|Z8ZW4&cO zD{v(~%$=QZil#oCb}!Mh8X!pj4!I8A##qEBIggMLqf}_d>+#t?>D^@S#4r_@fKC-W z57359cXQf_5$4Yl)2_YftiPy(IH!KVb(csR^$A^hs`^u;i-p5xu1DBz^MPwucJ*hCvyEd(T z_m7$Eq{q_p@`^qo{Zt?rhAw`y{Q7lxet)f5gJKxbY_46~B)pAHWElmLhwHvuSZDG< zPxy5D-REAeXlj`XONSYRcwG2RE~?tvA&~WliIC-Ce`GnpaTf)ktf7cw^Tp2}o#h^1Sp>9Ky3qcU!KbFlYo^QoutOYJqM1T!?1)egOA zy}%^yqPYSJ#zRW~A&7TutDp$uTiUa;hqnhx&O~7mB=Kmyp~;7_D~5b?lz+o`rfMgr zn*YvmL57V^u+zxmXUAwJG8-q=xSqgPT9F72z$7*A?rNnMH7q>ZjYMsBZSvf8F6?1p z8Mfge2AAIegk3|`1F=bZQ{c}{hKwzVQj&{-f$Xn@PVkk)#!A9Rowzb(aKmu&Ky&Bv z1|xbd(?h6`+11n2Nh>W5Rrs?0c}$tPsl&PPHfccaCH(>|#@4vcu}LdA#_=r1QRX~P zo9z^Xk)2ceoVV(6G7oWiy^Yncmr1#kHCz6YntkO|4=@w_EfI|5@T~|p?H|<;56i5pyh-2(-JZt zJ5=9OYNf$_xPMp^!mlT2_d@F zzRn~?NU7&?-izSFXq26(dP0$1D-oFQUyS9U2iT8>*uw({OBUa&4y^M9>#`M@H%z`x zS9=L(>l{5BjQC1WUL=IJgOK-~d%-~%Har&Wq+IcjNe&VH&FYFQ{V_fFwn>k*ri&~q z-ek>L)GQF5obPh-MIq-=$L2mr?;7I$c~)e}P_aW4ZiyI6rwf7={uBXvzQ>49kik!TS&3@DQ;CMm(-l&|Twz#-NLe#I-Uu>mlHNgF+QQOMO!CfAfZM4e` zhw?ptP76fwBG_ASwepZNwe-0p0S*s!Ma+GQ6U0ZaMl$(9(CeHK<@*GPD#snhf>Fo_3b=E(2dE;5;th8_j5+6M^sGxCZzJQm zj4E71F*}ns^90-@XKsW4D71S_U*5bv-xR$I`|?=R7`8njBPZ91!#nT)Je%xYBF~^Y5F*cl9`3V|I@TurgC+#i%YESe*`JUAH@lQ#_ zF%|K!dlcO?a3a$xT#Q_=JhdBK@jouW|b*=MA+ecticx!ip=<;%1nujri+9 z)OFPWIaXYaO!UuQS(-*v>Fm4;Rm}{W>+esv%Ku(I%FG5Ra~Hst13_O75fIA&9#=hF zIPfI}%|0Zdn-hUL(D=sq@ZrN@k-^QQ8F_w|6$i2*(L13yHl5&wCb!iOk4xc{Te#C8 zKl6+{Bb@8q2IH;7|E{xoj&BSkRe)A8n3u1D5!Dko9b+?Bi<87-+X2QI3%-=Ir)an# zNXMH)Jzz9Y;R&-+Q&U@p4{iZ}T@GjnQ{HI!hvh5&m4s3Yr7bNqk2OoB937v45$p%h z^ISdZp_TUV;MXYDdI!dK_nX4TQ5s84K;Qfvbo(j*>jLM{0PxxI+B_u)&=~Dpg7yBC z|8&x7!u}ehOVasbO*jdg1o&hg`$ei9y(9{#$Ya>+k;PhCQ2Y-H9lx4)UyXeD=urol zmEPO`b=mq)%j>iM-_J-<0kbR)=n0tfCIuI$=KWl{yXD<)IuHTKB3Y3}348@#b|0wl zCJ1>v)hN*pg74!;IrerqITt}KNCLX5(qPtDnIsMW=<%KZ9ha){P^vJ%05LEzF&%)X z(20uDT2GaB0SE>@+{LEgdN?DWO~VN&+G4E=M6a{`F3@3j1ejuac{x6w&>;kj!&XwDS|GJH%$%}q2KLj z;2*18_V?~Xs6ZE&eDlreTmrW>iGt{jGknzeEs}RJG!PBX7+{0&pLJJO>?~Z?V{@>aq0qUexYeNoS3g{*?;G-{t z+X7OSmMn4XdLO_Dh#6Q~NWCt5f0`&Qn3Q&7aWwm<2)Y?}yvKkqKm;_`|FhtSmVW^n z<;QVvR=|k68_e*Yfc+FYoi>5*44hd7@H&apM*q77J4M%L1$bjF)Zkz3U<;1`3zbz^ z_|NSKxM_jrvzXM!1*v}ylcwuWb2HR9idr!EO<$bR?sP@{Ze^dtavQ?+XCZ?1Z_CR)j?Dl{iw~|uxSy|t zJTd9U2EaQt+?lU0j#nJ`z;Y-cnNZt0o0$Ok4GVzQe*+v$x%b6eWW;xWTv_L@MN^~$ zhM@fI`pZ|zeD_rI6uRKy0=yZ3V;= zW5CWFUU>hpjk>?hC9XCpuPG8DqUAxsgKvOw2myl}!?9fX^L@A0@Xwz=oASn@L*O_A z+>p`mXui3%98(K{qXP8fHzYhEf3T|m7W?b7@t;zZ3&O?41?N!tc8aSwUAEPVb?R`> z7TjoG%E?t2cVWItavLZcKRa1PJ6G$L4td$FY?~39(V(6aJOTKK9P|mJ_Dt%k3gC+j;_~g@+*Vl0P%+ zmvJQwYl*3@=3>>ZMn}V?Y6I6mBBMnv(G4y~<2kJ-S#4&kS!M?QiR}U`e_i7;4C-}e z{QV;n8IKKFY3r>g2(U)L?WU{D@kluIBiaMefNx0UeIDET28^S^X;YzCA4&lT`!4uB z8aSH^xHehW<9|{`R~K+F#kTnuMl!l~92c#@!I8^>3SW=s#n2tK}wni}g7;%O4>@p3(@3O`O9GPeWt zTC&UJYj_|NqKTeahlkR8+<*N#KO9WDx&dPn_W3i>t27a6xPODmaZG%C2wWH-q2Y2h zNoBHI1M>vQkJsUFSsYGOgL^OSZSRoa2tBy)lBD-WFjxUj*#{f4fn9|<>AutR=K!xddf|G+KT5t=G z4eWS1z+u7tDLi=8%*@OL2NkN2nNeqJX7)fuMa2Oy3daB0Sh{86zjmsO*ZC*4<)>VD zw}>6g0z%su@Wooy7WcpfK_sX(lkC%`R}5AeV8p!wuJ&{RxHBd;_8t5xpky$1JHTz0 zU7P;wCHmjJ+{*?wBNxy9TtWh|v~l|pq^{ok2}G=iWf zPw)Rc)37SG4%(k&)_^fFJZ+e2e?C*@ezq%x^{YYAJAeF9P>s$uSkUJ)bIiysjr;$M z|7SaN|HFLex!~-*fEK{k_V#HY0W|?XWCJKuR{suoNJt1+V{J8XBDPhLsyy_zMQAlb~HoE~5AzMx;5QD3<3Hb9@elO_VQBhXL z0wSPA9Gl|UGIap~kS;A>wQw)hCODVYybFtYe;!;Lx)jRq{0)Syp@rdBvDTYOIJA-nXALM) zz|qdk*!})N8P_ri4BIn6meIOzV2T_tbU$84^v96UP?Tb#WCA>p&UZ;t960sL(82J*dS6Lk_$Q$CLv1yy^*fd*TSa~ZQc(IK z!$?gah&~XrWej+0WZVWcs*bMIq;5w+_tVt9&9ezFGk$=n|z71VHDAI!li^tw$;AU)5G$m?<3EZh0$HJf(2vV7; zxBIKA=g*(lNYf63Yew1NUSmMRcp|LWP-{$nQFL^46T0SLJ%FTh>@Os1q7Gf`A2Uu< zM3S>$W8?tnPnz9pxvfI@`_E28JH$K=R|gNzc!IQ%IP%$4R9;Lfgg_R>MFdigPH_}o zBQ{Zoe}we}tV_#}+0KnW`)enJg~_1_mgTsxc~onw8V!HmSSf^}K!yn|UBU$A=kqZu z2EH+PpzX;C98_@mWY8CR45cH$p@dcoMOX1BTv~@sOin5^&sS#3Pc37I6j* z{3ica{6`)%NSpJN@%S~HHVtit?a^~=rcjN5URfnOJ1!J-P$=wT3=9maCnK23!I^OJ z@@8C=G_Xahf^y~g+JvIg+7HV&@-xaW3Zgs#a^k?Rx5Fr_fm&}(j}N@B&$`74$o_|D z{QfnwdYuZKEPFB$X?lx;eM0h0{9G_wgear@)fAWb)yv!hc3Kg{v?d+Iv38E)dZzjp zFGj@**Ahb75;neeee+Qc-+WIV1wTK(sQrgyBfd)|z$cU{HYw8TGrT@c7wFJ6L8Gu6 z&W2Cwpc2Z%xD(Txm0erQXuF?y*2v{pCG!||tV{4L-CS=`GVxi%EG44XS|ozynsPgD zPwzu>S3D3;C4Z5-e6~%LkAOfbi>A=&gUIi$>=uDHUE$<97Mf~jwWE~&>#GK;byWylOWu69#-=hhBOG7iTL!seNBaXJ$bor-n;~p5GuZ zR_scPC%vEZiYkpUGI2@4%`0B213%U-n3&dkki2g5=P@naE zPN2u0e$5HoX7hqSYJ_!mkvf%lfh~czozqs_HOX;1n=F3VA#uOO(IYSHRc@Ah{JuIj z|JJ!)ddYk-rwNHi?u@$Cq^4F1MARWOS$kPV#38EQ>}Cn-NzAxKcHzXd@b<=rI2T%! zufhK%JyR}BBB;;B?cPumy2v_-6{N(sOc%HtMxihnice-aNrr2x+Y&wf&Z9b_h|>y^JT{SI)24@}7FVU9pxljGpts+s~u-qzaTnuk146 zb@ZuA$_;(l!3!kcEl#F|tyh_$1XG9~a%8KafdAgUxIFdP|A!VKht-RVS$xEv7K*bz zoR|?HeRfHZ?Tp{KGa>e59WOA{DUJ~q@qlab`e+1`S59fS?=ime4jr5>(KCYXoWT|^ z3DmFab4zvw+P&9*wzrfBX94eAir3#Ct!!A`%S2SLdRQmc{Z-4n+5APrsCGx42$Pwx z=lJUjyAQ5B{{2*wIOLfX>}YTb3-e2y>>GT|GooP~)-ET&(e@S``B?*54+i0T^W1!W z+6D#v1Qqwy?I+k@>%8PJC#S&WwLUlSB{=UGapbb-Z3?r`C*%ig3@d1_>0ytER3e*yvrwgRE)#kHNBY@Y+ugIOeh}u zG)rlH=mKHX-d(}KMPqZ`MMk^OQ-JUO5%ajB13a@ zgAQeV&R2b588rhR@@}|Y%%xo7v}``%=S3XlS9K2^r|$0qbI}&u`(XRpk`ONL(5dRBWsVd z$b5J$4v*mL?=*OxmVI7?1or~@Al3ZVD5YkEz$9T>%NdD9y^-d4{(6NG@)1VkVAdE6 zC1)hA%7_Cuqu4o8&ik6%3d`7!B53S=8TdDekJZI^NdFc6LHtwSxA<6Jdy&EAi?KsF zX40{l54;Wp%>#P+w&Y7@*U8zY-sZV82pchN@diE`xKN{B)*xx66cXls=FOj-KY8N^ znrEoH&q-Xdg@tjVIl4%NCdAG8dWmr^L|bBG2vb9saNa*rc^{Y>NSGXQzO-^l+$zhk zOfA|ngt`Qm+m|T8xjkD|BZ;s%-LHQl_l`fVRjtuPSg~wV zT+5rrhE%z&xNm>rU&LoOBA2Y2VJ(^b$+r7hZc>dS!;Zv%JNF)++K0QrDaZ1s=|#cq z1#cU;8s(~#DHT`}H>|6Mgb{LM!*)#xdPLnjLFF86FXD}iLFnk4KXrvg*ba%=?Z3J^ z{Y5$600)m4{_Onqg~VIha(kEdUhG)P!XKI5^APm2W~g)>#1F$9kHl+Au-c5Bk8D+l z)+E$cx}_=I+|okD$QYB9M2Sm4K(Okw+4ZWo29C|l{?EI4v)M`lN^nmxi09mQ*sRzr zd2;V5+V&K6E3Bd!O5j#5ze7RF}9*I`|7xek$Y9Z-CZ_iyJ4;UaK zrRVEDr=La3-u@(1rGyegc|BU=WqRB(XJWsUEm4I@)lx;e+h(jk4t~K?!C_AcZD^Kr zWj%SuW^?~yWrOfLfj82nEE;z$!~E|k#JuLD7X{ybqA8h@@CI#kKSrLxVxF&y*!{e0 z1a=9#D7JDGbI706KfzxD>+Hi%;#J?OzW+Jb6ckL)%|p4pWxB75h10OAM#D&4p)%wA3w|%#NFL8$aOtVPu~a(7sNyq25UyE#dt5Y{<4e{F$|&>1Z8Rp(Q3yGA8&n{sz7C#Xp+ zC(l+hC*VqAbvTJ93u?(N1Vc7KcT^azHw-ojVyjo2iuy|!MyY9-lH{b*#_mPwC+TI4 zjeYx%-15#!yTM-r2Nl(v^r*?oN&2VcA-EmO)C)$s z*$x$O2yav0(qCnX;P}Qt8duAq;~+hy7!vR{02YwrJh^JE5KD_o%Ro_C?8z?T^7cA{ z$ls9|%tAFEHgaC)bFP#KY+ej;d1JhqqFZ2^I~abUR6gf^SBoMg%`zslq)P zdSoxG;CZ}n`*8GR5G77FQ7%!&y^dGAqJ8C+cCNQ!f$0>%8pXiUFbNTL#Bjv4`F;)Q zjLuUM7C(Q#q}fj@&n%-aavyiBlz3`(fuVTkhHy)G{oDG1rO{aaT;c$s0I?5J#Gxgj zbpd6+B51L61h)j?Cw^t9x=ztrGXG#{#u~?hqg;N@1b+Fho3_SNYRALk zTJPt7;haIDePg4-nu5!Y3xxLQkJJifsv2%vSx&aGuCXp}E{9>^M$Y_p z@2{qP(R z?ir}SEOPwsJ&p2dr+RAj44#=O}^oDvhuQbXFr9g-mr4f z4{&(roM?Ehs7oMep`%q{Tmk&?gZT$hxY{9u_9#ze`kw{D&D7}I?^{hu2QOs(!0W*v zw*lSVxi2l>Yd>{`C&Y$|sOO|Rcx%arT-n_?J4y%k7|SI|bbOJ&;cIWA_Jpx6JTQhexKyRnd?hjmln#sL($@UClVqz$tgg#p= z%)r|Kzm#8ln~uy+0|5SufBZzuR=sGazJ5Eq#u4DUlF~U(>OM7i4>J6Gobu=1WZV1O zRr^xD8BV#3Yck_!;bb?E|B<{J`Em7LSLLZ8i%XX-<$keKSI3uQ)l2dEb3;KZ8C68$ zn9sayd*Y*&j4-O2ZeI{9fuKaxZKOKoE%~R4f;>QOekc{Zc5&G`sr}0~3U3rB-Q=i8D_WN1F`>L{@eo%NpMatccX(}eBSkxB^wdR4U z>uis2e`o0J?X{Y04u`&bQ3)OA*UPAN6snS-s)h}Kiz?JoQ9nGCE2kl#ZA63zkQb0N zdk)>z<9GhbV9v$}#_#*^bShd}JPtMXu1od4 zUb$bkL-0s27~orY>+4kz_@bXf(c}DI2YTfWNZw$iC-2t&f zC2)j!JksTT`}>DB^fpc;$gVmZ`{8|zi2AGR!UHB5I$B@6vC`X2_P&=QuUDPHGs80J zD^`IF0ye1qm-1Xo9sb_yBQ5~Xpp1Xrr}{5}4Qz-Q0}Y5FAi-k$@qt+N#ychhQ&XQI z`-}_-7c*R{gx2m{9-8lPf^J(lBeKoS&E>#2I8>4vt%4rW{d-Hr1qDse+Ks{7`8~~s z7#R=te7)}BYGap@*E7O>gTu=>-=){U4yNZt7IIi0&1aG=Wug0GtiY>qGk}NG+Vg`H z+pP&KEF}Px-VDx3>d+i^rLu!0%ftp0|BNt*HF4urXN|eA7=YUl$MOSjpntw*t>LdF zh7!mfmr`btVh<696Z9e1FM`xwR7?ytrWNQs>4HCp$N!k1Jjk*8&*S{u?d+zRj+8c3 zXk4r{6X;Cgeq3_Pgn6BHe%*CT;>=s-4fD2}HmWQ5*$ifRuKjV|Re)VVRUX@Qp`>ce z$(!ZMor4Pa>xoD7^z;zI_E2{muzQ$ba;-PIPqL^@;C@+@cuDbvs(@A> zH96B?k1j5m3yeh6U8oXjU1*SnVy-2Y5>lt5kLWJ652xgmlQRcIZ~16fV(u28?h7WEX@=7eYvcF&JPu@OITn@$(ZylP(tq9rgA7gWzAM zT?T>xbDv7Q^V>GIs=Ir?YXa(_jY#UoM5Nzrq0-ZCK)k%h?bL^@ALQefdIqIwfS1b~ zmK0R;?Q-%N&YAc3eDuCnHH@ef?_b6N+BpG?g1nN`a2ioD{c`!WM%1t#$?D7J{uin} z!EH88Q2WKgApMgR)>fgu)S=+LHEN8ej*jd0FF?2|3m%`M;=;4`e(wTF_r(i!_->P{ z_f}YY5+-wp5=B4CkT#J2l3Y%%zfd{Ms3*69`!0bc7DsJNL)G zN%_hU5fRPzm$8A07=_~Ru0ngg=hh8C#n88~7+stlp59s%gkZCjupZmqjNx0|x0WDl zGa*!A5&u^b$RFN&vw9QL$la9YdCq|ZgTM}JdVt(MpPYl|{bUadYO}$@ya64aE{T=b zote@e1TEY_GVFLCmu~g;6Rv~bG9#WnpweND4NfH##BJ~~AP%|?z1dhIZ+AJ3 zj9t6;m^^0`fH9FjIB72XRjpkO(yoDtAqYas8Z)eJl=3f$KwD%m$LkI# zWnqF|zkaRWKbFEpgt%~m$4OXk&rr?G&Q8MV2eIGjVNapKgb{*M?~^>Tr&WyRX(64l z@;+lRmN>>{U~e>;GZD+~^J6lsv}=_$aM#-0v-|7-l$`#+F1#*GNG;6IZyc&{_5ffB zM`^;W4x=U(&PLoEOYVquV^r$n>L<=3+Z*PWTK~hIY$7`=kL1xq+ zuz~8WZ~$$0FfFJ zcrAL9kdR>YQk)%O1Z74c%Tnvd5w4l%b#%ypCx$Zu>V^=+fXszU%54N@jsSJZy~Z3B z_tqDS%BBkP9y=MYkPSJrA(D$$GNTTlj4ByUG8d@M;Tjg7gbcv-!**SYpx*JX#g0&x z(o?)CyF|RAn`&QdRzVD>3&CZ;W$7z4Gn)b@-Hf>)%$6Xj!M4@89J&tZqC}2ypKdsGp(J;)#LIHJfr7`m<(K65W+cQQP?UeYp$c_(?0sB`e5Z4Ozgs zad-m(2y7RU%>ic8u+f(eBybdLSxGjWA!dsYP7L@5x7C;2Tvup#bz6b7unv*VGoDdUxq0?{Zs&{Spv-;yy0*iT;mw%v|Lzo;Yb1;)tDdX|}_jie%dRgn{ zu$0f^-*y^GT#q^Y-oIL5b{Amcfq{$5qjhuuKUrjayFC@Se-Owl?|Tf?wrG)%!xYeS zr5)F1KKs_o3=<9$LKP)D*LH{uf{e^FM`wG5kkDwsILgE<(6x4(nvIPDQ}Wi*qU8oK zAM-M+z(VbHJ*S%NT153tOc3c1k#pr2_5gJibNtGM5n>YGwgZ!_O{eF^$0s#n07}GH z`}<3?P}}-;<7)Pu%MV9abtT+Jq=8S|1Llkv5F>6rMNTpgE$X}{yRucQ;XN7U$0%ps z!UA4<6aVd-8-V)&yZb|ykq-wQ;{6!F)rjGh4vE+h@ILX-aiz^`Ri-hEtQa<|KX!00 z&|uD##mXtc-=q{5$hW;KCK-#jVhf1#O;tbD|SGtW7W2E86%PJJwcO9wq5^w{^ z^7tpeT4X?*c6-oKi*R{OEv=>tdh+3!vco>N#v@W5D!?8c7wLIimUhV{nG6F9kRkwi zMNZ05*Xw8ke}O(1o>$J#GNvj(KrafW_OJ#41>BFL^M;l5*N9n=O9}We3vUq9+^mB5 z7ywbPnE3e36YY0B0wCiiAZ!oKwfbqf@RVs7-!wae%d)Av44w%@FJ9c3{cwu)-N4$8 zEiil#y&+}tQurZyiuGEr?DE8B#dV;Mdw6*8TKqYTmLP|z)RuRJN(VNE`DL!^x3wge zU{_DC2y5I@nlaXv&sG09bK1Jmgm$(&%!f$#)9}8k^DSLpS3C{|SGz130d2zsS)Cb} zIR}yVyxmb@r0Q5+Yqq|?^5)88pwA)7>miNNyyoTLZE|MmAViY}1&}tdVJ0CUT8vKu zI{?z_+FBXpyCL`$FWFfr*bEDB(9O0a%&=3fW_I&FX<-7zD$S&%wJ)db_bpzGhKGes zzzV9myNg=-Z?t_|>m>rJRxJ1!NNwK^&Y|cF(+GP$Dy(|yNvSsnE=X3D!zFh$?fU$| zgS&S<-c`Idew&(Tb%x&h#>L3uhK6T~#9Jyox+V_sVAgEof%`%TE4TXm=uC-aAmlLd zrAL|z%18;v|B`E1y{^D8Ob<4{qr zd$V$i)akNkn|E4js`po=YDr7K6-gAf@dg9}(Hw~yg(FEjple-wBcEko@dX&)pnrWF zG)gA7eD4D33fu}~qTCNcb?C4HYDI;%P{}jZcDFS*sOZVMFhQ&-SkB(*w`W}`n_*3l zBtk)O&mCABQ)PD!1Q4SJU8~8xf#bF%0e^>w)b-9Lb0NAsJ_bo|bzP_wlF&g(GvbN^ zwUGo8$aWBX@B6-WU})+pLI&kus2g*BO1iY>d)62yS>GXXANexu%si{K7U86ug$s8X6`8+lx~|!U*X4>gYv)zGSTP zor0YFIEGON_(DR38$cX$dMSvR+}R&~Grm$m0Y~YYk*c5cj67GWu^-c-c3i7Qd4Ro_9XHJ8vkzAGm}mGd7UT^*^S0=3gQ7tjlH7*iUjTTE;cYfVZ>~a7qZ+OQUW;oQ`|l3o zZ)N|$Gsx}tocH#w^@*9|e@yet%rVk!&M4jQ3AYwC6nLf{-TX`is!|!C#qYB5k~d=v z6tWs`T-*Co^*mn6bQ;dypj{?d5UHFZx-J9%=v9m-b47P`>EC_)SQrs|Jbv$PKxM`& zHPKn|c$rB(zg$H7vLQP2$GA8?PZ&vpdBZ<60c*clFOOdKI6F@Z#pw(Sa<5ZRZESG* z6CRuz{D4(%booYY_$RLnk5(UC({PKn>}MUvpqu~+Vj__;jpzr3Le(m6_Vvd<<)z7Z zzejwY^-?Yv9$FZTE*rTr`7)_9=_$`c3vzS~V@IAts3vEQn?TFsV5oSr)hL8?y2I~! zov7`4QR>YiSZT5@RQOL}PD!%v z6s_Ze4|c*j@**pJ3|=U6tjIZzs%00szbz-%(rP8^%6@?>72VI?{$ea2?W<8maZ!y$ zn52eO>|ER+x0klUWQ%&gIsiCgZDM#Wt}UO0qkYRGtSx(793M;o z@cQuxvq&3wEhDX!O_?aOoQneQ@cZ$1C)>{^#18ZvuFTOLCm*7>TRv973gI6Qo{mkD znhtotbtn}=vHv6a!+8BOz3_&TSixnZS8So+9dR+z%CL(o>^;ZTw6pS>HI@lqmJ~Ez zn2gx#QcBOrhUqOSoJ~3wwxK*N)+*DwoE(J>DC)5M@C$%Y08x65r>B~9%+C7~N@au7_ z6yXnB!XJibP5G_uKq)znf-y1sTQ+P-30mkP6ClIjvC`k0bDo__V@#`f(Xt$_*6z!DhyBeM7Nr^sqdjPTfr}PL< zKbhuPcRo#TAuLm?fXVEBUj^kLQgzNUutNh4k z+8`DI?9di|lK3??z?xu5q_4=Pz3u~n)0gjPr;C8l!^x9K{AnF zR}?(w-*3&?z|SY_B{XwhaS2f1E%q+b4eeFQ#fyN5R!AQo|?QP7^0BS zUS&-qnqPx?JU|in52IEOZopuY@_B3!&|DOneXg(rkqiwqjsUIt*0!T^qj z2qn3f3x7>sE!;8~p!0;?#4LS*FwT>R01%TN0wI%WgdSWHfUW~SV4~WaS=?^ZbpHh4 z%<$vD9Emhq4Tp~g^ttAbIeY-n@_-})*OPUY3?;l7=`LFMqxOT|rC(tbkq42;l3*d< zCsF-JC9rcA-+Lc`(E1w;rAl2ulxPz94K)#tzVsL)Nm}wjYwu`Je28{(|Kviv7zgQk zdRLdmYAC!!bgCMuK7r@(Qs%Z)g}M-6{pg^T&9>NA!(q}iNf8^6q1Q^~dTj22UFA*? zQVXCxaQh&ZR@7E(y*$-D{*}!mRhn<2LfelKtne`}#luK(4&F}So^U9u0JkD|QHiUl z171h0l^5*&**|-y%4|F#hgcIpAb_=lw^O*m2CtF@!Smkby;mAm1UE=dLp|)+E(szx zK$3a9BLqwa;CX~eZ>?o}X6NdQsJ&HW`(>s8EE+5ftSGQ2<^gk(<|d~)7uInfHXH5( z@SAX%#B6dJE#BA9f;;mH`>n)^R+R`B?-~osmZeKsw7qx!I^qG>2d;1US)jVu2)%%# zN?D-xLvlqOu3*EGW3ZFwHmQ#}w*e{8?oMXBeS>Ah`)bYekEIwIGPf?9iyu&{sjctF z!!=)Z)Gq5ujZb>a@hqH*sR!Pq+-5|c^MolaU9f6EDQPvcp?aqF!qkWfiU5oE;o8@K zN(&?x!cDmt!yM5@ag3G|HE?#y^DISX0QQEm?t{PdKw`P)^b9DV!h>*b=>Rkbau2&% zwE6?)tKK#8saQCDzLFm{Un;G8nk$k6d*{AU>q!q_S43i^VnIChs-!Xn5W#RW4q%fY zmQYV;76}V1F5qP^K73JjdrIB$c!9^+ftOYt4-ttRwv0WFCLw*sl^U~76bj0yEdLU)<Q+q$^q=)eP8>DAaD3U#$0?%`sQ)lM0*(;AQXW& z60a{d7?`JG#cVyPf^&t~HMyGwfA{l51=NTayy{g0nj?Yi3O*Hx3C6y(P+c=(>dWtT z&Qc}70Fx3Hk`ZsxCC}o5>VT!S(Qjt1McRBCFAN5Fu(MXctO6sZ6plP`zTmIyMPj&7 zv5jrYbhG}P{^(jgNi7W50xVN6{T5}G(iG5R=qSweSS{Y2A>U9@2vW5jAg7%UT69nfi;Z} ze6OI()i^)lWnpiabP!W{)(SWXTPe)F_P(!b!kOG!SgO5new7Gf!Q;DP#j)yqi7Fm#R99K671h8B)zMG z%^L^%$(-;e4Whsa>e6?UvwDe=Vd-v@5qi55UbkNyd|G+%+KQS>D}=O0;r)GA{p@D` zOB~uaa<{GS7bkI?-g_kJqtYm%7%8)8Gy(hIimzYCi_W3jvsp26~{;;mxEMqfQwjq$?J?d0s*xdcys&Ix3VjVpefwi z+G_RT-bvIxiv$`-=|vlt#o^-5k3YIAD?(BK8X%E}qV-T!pFm(lk7xw%woA#WMSb4I z2`bjzFcDG7uwt?uJhfb$VWpnXaWaA)oE>g%%4I3sMzRYN3P#d)1k1_tT_oKcXROjz zmL;|2(}VKY9$xE>%ng3*tA60Bn(u4lFe4@xKa^>Diz##6s?ni$nl`^dYAw2ck(Mvm z+L@`@`jGe@^AuNiqP!8i&gFXVi2>o^>|NUPjHih}Ru;-wG%)q4Soc;%K5tQeaU*w{ zWe9ZR`2YCC8x@sE_&SnCZ?8N1G*gaLSRQ^Hk8)vdmwVL-{ih&cP7JJ^lQ0D?1{yCp<>f~qx6a^) zQWH3$k2F}dccGT(4?sci()87P{02P~iOF(@ja z4l?wSP|f`$92>>gxU@Bey8qx_UWc({|234VjjDNjOTjPULs=GDOgI!2#^Av$&_GjM zTnuXo9s7-#@jVpb1Bj%v?FbT0IgY z{y#tMf|^D=YQzIEZ>c)2#VI60u>k!d@G&r{2PY>t7m5Wkny#)wsBs6?9zo_>&CN|1 zfDMna+jG{apBy^OVSe8y;S@Lv{YT}2UTj#jY7ppN2d#Aiq|SguA09lQhb`rl;kM}a zfZpjT81&KJ@MlW|geFkEB=!Rgko*f{F|6R}s5Kl&A|K%ex}iZ3r{3c<6g<<@8IgiV z7t;>(NvqttRXu2roaC*eZ`Ot3SV-0b+D|BKY;4w{uOCeZL`izDjSAriY(47mMydd4 z1+J#4S$qWeEE<~ptw4_A77!vRk3pS5%Z^j02iQT1R`*(TN=a!NE5dQl9d95`LTtXcqHAJM$IZ#(Whx)n@Ljb`=hwaM?JsNA}QBlGJXwKVwZsHU|um#HA znEqDLjh~7?Qdt1c4zNofbWyBnfkAFlu!u{ z9oi@atkEk5${`tZ&()Dj==;)JV`v53ftfS`9fvL8JKCRGF#UwKKcu3AW^HI#UdRQh zixwExMajmN2xAR6Wo4Pb8z3s2jjb)Bka;c-7#x0~+;N&Ja1jtieTSI=roeE(hfb|^ z@O%?6$gfY9i!+C(3g#w(Xa*6Q-~uIb;#Y&kKAOFx#|1A2K~M8ED2%s2(_o2@bZ^X= zOkL=;tJ9cv8?B`Uy&xQXQuoAnEbw6XTQ|w?gKw}E_4sc-x9c}JQyX2X6qA5`v?Do> z{wsG_f`fy7BjKdDpx$iMlnKnnUBLaSh3y4)U^?U!Oe|_gQ&55Lw!}hSAqIzhpynno z>a&NwSj5fv^XCu3;zx2lKv}26=K*|O?a|T>F@qxm+8hqR_kzCL%h5>AV|}6tJ@aWS zz=TMS1(90-9{WTtSdtWlz?h5G?i^@b<@rn*R0`8tCyYzdIrfMSCjbf@hCckA8By{P<8+W$4HcGdg&z-%xq5G(+* ziEmx-M2;6(4{~?H1WK$OlkQd^C!~4)yqdqiocHPo(OHA8hC6qBICqAe%fdVCzRDVb z@$j^@{?{~HK?DPC(CJ3awg52Tqi)$+pS4n-i)w1D(?BJqmvln-P&p(Uur%{5)E4X+ zpCVwkg4JlP*CELexSjQ?oP{YLKc0u#O%(9#R+v2E@nc2{`kR5d?4}QrMz) zo`nZ8w_MwQwrf_uyL$_eD;$_)0%OVeq0OBY{w~fRnt*FSvp&4A3UC!9>nQ$WUj+VAh=H_=&L{?FGcc^>E24Hm!xLclREU8$#$g~&d;GW!G=*#G>b`>x?&<{D3Vsks z0?;|qFJJ@&o?6=537|XMi}wa7tPq|xI5gS(u?PQ+q0TYUFg8ZxvCyJ9)EX-x00!|OO zx7N0{Y`}?qBjK7h;ywRgpQ%C7%WGd)Q4b?(Xa?z_4M6gnhKDbs({J|ZN3K*qgo9`T zDOk*0Q}@^2Zv}-hPoHw_IE(;aq8aR^F$fDx68OY(H5^n_w*`;Z%ow`9-T~fy2r45| z2g2F2eAdPek6eyNW-oLh(a;zh8yST`^iiuZ{RbS&`p=&&&?-I>Jpx$Y0^07oOh;a0 z3Z6&~#4U6qBSjFoAMa0y(vu$kef%&W1I_G&FK>aP9S?yC7@P485IRC~I8YQugZRJ_ zH_4;lpMa?$)f&@0TwLs@Pt(c!Zo2b&Xn>j%P@L;qzza#m{d4|KFHn+#SO+lP3fQhK zpu7XT)Mv=NOAnI=|lw_R0tbJ zb3J_ik5hG;hX?=at4nM8(NXzi)<;&&Ox1)MEsn&L8y;6u=R__O~ ze|}Qv14yVKKWPmMi5&DFP|#v$XIDb@FcgPqZzymb^Z%*y@v;2nHTR)nq_hU7LGAo` z(zkny0=v7runE z4k5Y+(i;Gh^DWRF*(A^VgxFEYtsvqqik7TI>A`~XKb`SeWv&E8E9iMg?*#)ymH+Rf zhS=xO5q@~oged=+@5~EmjYLW>hdk}mZp=XM2!pF@f#oS!ahKF}R&A^2n$~4sPzY%vK#uO(i(sGTzHk;I($5MgXft zr;?MR>EEq$8#l5g7}NqLf#xbJSHk7N}MmNbJzeuP0 zXFE?bU^tQ-cff9+Ls8cVW=X@6yOp{Wo^IkzO;33V7 zz7zN}=TMFS@7v=09AniHQ`{)YM%C7kFWP#fnV?5O;}-i^~dFI`I1_p8FcyGTEr7 zcn}60F?Mi6{~b~_Pfv-dsVO9<1Z4#beyH-H;Zhwrp-+oIcSd~aLyZ|o^e%#`&!Ov% zjf!F%gp?Y6?7)gQT-iAg5&1^WY=8!iJKW8-{iPNteL(|+P$WR%u{v@FX+Qws2xVBh zPZS_$BsBM1seo5(L%kHpor4eb3_iMeuX1qiLhuJeftkaAg##Y69cCqMk;B8&yTB>M0eFx|7*y}~P78Ms)TrLlH4ARa7HKW5Y zNJC@k7zb4aZo|QL1{`E?NLCeQ5S~)}9|su{g8awQiP&&&QBheW!9hf#9r-1C^KjLR zf&rkk3I!tNK5LdduF+9LL6FSaLX8XvM$Ir^wH&VXodD4Efqa)2aZTXg8tr@;dSIVG z=(>OsBZ%ErS3v9LkiZENJ1A^8KSbSqduySG09iO}ZxYPI4GY6XAvtOy$~VZRJbpX^ z@)m3GD7)YmoaIdcLHW`|^)Ixy;tYX{W*Rv2&A^Mh@jck?Id9 zl4Rz9)bX=PS+8n?X&q9z33A~k5#umz48vnUE$u9J*U>tQ!qo1yxa;saBLXvz)-4BUY!nna{ z#1cyrw(v}Vd`=D|A`y`qo^a8ANEcim#s&!N(L$8&bV{Rd6PX|+I2A*Z zJn`x$+!_wNk&6UR5IG-}FQl!d<&pSq6aqHT^7?l&;9n=Cr7xmHa)|UO#%{zYcb^IY^*<2#H^2oRQ(o5r>=-N_xt0V$i}s&`VE>uco1aByXVL25~RWKu1_q zKGBOXB-z24;|qh2Wdh;H`L!+s-;@@qAc0Tvii(4s=>t`-&l#`rFjP%2maO-@fn*|@ zxAyI+P?pX!7$R>2YM~7bCr)q{zPA&%?#fcW1tI4K$f~gm36Y^W_V{FsVMu}ziCscp zj0Z5lkT{UE*W$e~4jQTo8Rma6oYyv5_SKP^IoDgK=}C9NGDRUuzZ!#HV-TiDg+K*} z0ZvNDpi61x&&1e4mv<0AbVGD~HLl$8Vu^|8+87Ir?UnqNS$fwQ4$*GI-+e`-j%sOX z`H6vt${_RUVF2w0v`dqsKKYUx=H|>Ghl|J*!TMSx_V4{)cc=D z_B-db*n1Lfrie({yVjB>tDtU&uu->2SPM`vgWHuY>q^Sto1yp z_H;{5vd8lVUHtUoA|@5LVhFT z@P-COWd5*wwopPus+$@>?QQN0{%Lz^=aqz+&9UYL_Aruud9k6yNa%jZS8{|1o!oDSf z1BM815|ZgQXf5p`T?>lRRQxZxHz=Ca$I_6zR^@FxVN^6IobT;-TZ&enX(4X#`MF$q zIt(A?O?>=mmG-;{hWI%-e?=4jJuy;z9QYzoE*h$rRX6uzDP@o$4J~_%U+-tkLS?Uy z5mC(z2Pwspi=h96E;OVi1w%P~5|u__LUcH8-UUn@aTLZR&!oUi`!Bwe0v+b{-iV3z zSr@}&51jI=`1>78WqLaE8?!Jxc(kk;Po5-#CLpJX2n9Herluy;(t7pd18C!q8lu3b zG7z``s!GsQN(3FGNDwT6O_BW0ojc|*v=fC6VMH_#e6R5*4maFUg!_pEv+8^o)iprx zi;$4eVYRATuvoX`?Ms<9i#e>mD`~_Z7Mnl#7uM)X@CVhrF8v{e9h0-tz9hx@rTNg= z8!#EZ73(qFixs$CV6l0B#rdQU*1Uej<-q{^24}hy`+c*_p_^DkKZiQyOZ}$|o#lk; zzLYwBF&48dSg&1O32~~rFugy1C)MhcBAaSn=ic;GQR&(KK+|03hN4M2^S_Rt&7GX+ zMd9IwIH9SJg!hMCy0&kg9A~!{H*%2>c@p)F@#Kf?Eh(ojD+zfcZ!PglHdOX4>Kgn% zma6+oxl>a0ea?28qv6)gYQ-9Ogk4vdDR9xaadofGGsA**V445V&M0H?uXV4dTx)6# z0~zjXiVelva!oWRi6>k!Qi1E7Qg3$ThJ5O9r`aAvQk_0v2z;xsF3z_u=D786Fstv3 zf_kG%@1Jcc{&h(wuLosX9;eH}tMU9-HHD@p6-!H2-_7|+)_7USBS47*1m?yXK}grY zTHZ6IBaECy2C?{|@EDe`mcyTiIqR)_SG8zIP&c@(pwHuYq=RB6ZI!H1$)BHLzMt*7 zWH@g#(bChdq<273^XBceZ#oLTh8N4(c0XZj6Y@QrkR zn*y4iOIoH{)ITH(dJ)l@-jUU4w4hSefuhLN^gdxle7&jP7W>h z{dnbbugumwH^9Ox=|a%*via|Tck&P1`$Or)o#bGq!<9kpFO#rKIzl^Dx!>{qaE;#po)-#Wv#k$%!UVJbXmEu83C3yy_hmi0i$@+Q@~JFFW)vws6)N)vQYK*%N*K z(V;8EP)mqNvPhkX#cSbw;~ag@Ztyy${qTBd>=nOUGQ?^vaNsDU zBkHX6{pGk&Lg5-M=J&ZJt~;kFt-dDLVqL`xzRLbyTe&=~GP7S;t>VAR!;oC;E5VM1 zKNhdmCHuo;+b*T5d2wr5?3_{K=eleW&27qAte|zF|7=ETuK|CYRI&6Ay}GX(;wCI) z^R7l8s5S3DSLRn-EEl|l>(l(&KjfttO`MvL)~~hVB|r1GH^b^^&elAA*+!(q&l7Bs z`)xFO<;HAqQE-F*bVCuTN9uNM*>#n{K8I;regRo?MT^-80fy!DuRSjM=TaJnq(pMR zU9=NSlk-?<#}zYJGPWc5u@WMek=6KIQibl!>lv493+G3|m8R#N(n-yxi=Py@c;;`@ ztP8o`^X8_rP^=gD6sK=mSlDdka7I;+iLtB*tG@MQxpYwS*LNGqPRUc;&vxjBpPie2 zQ%1BdqO*wqV9;GxO{f#@$RudH+FI(jg$@^5^$> zqLg4*BS!7c$ziHwFbB zpE@>ZFe#VQWhwPDRT&HW6LH9!Agi*MPbSBRoBdz^B+jW!I85rD#LVRtT}vIqdtW++ ze|S#+m0F10sbNo^XIOzxjb+)KP8j_M-vRz}msI-NFG>xyR%Bi% zr8dwppG_@_eB&G-(9b8L?T9}xC8&*Sy6P~+Sa9XC22KC=P_<0hEvEZlf0RnpTpl{v z3O{Q&0RMAtpnZn_L`8r(k&TG$sCqq(K?~9Ah&kpW=X*)))M zW>)rU*djziR$OGOkiClREu*D`vPZ+-TSiJ&MqGBtitH2-^8cRh`+na4d%W*)JooV& z9k{OFIM46-9iMURC%?w*Js*M-? z(rDJ-5hq&b{~&Hl*k5R9AhWW2n$W!<VxRjb-Av00X7B zaeX~x%so-rJ4k2W3kKxSOj|5(d}rB&H8cyK>r9vdv-Nu|WLEK{ed_83}?z4C1b_H4K1f6yvV%;k@k!2%# z(lEM#r(8gJ*v`3Qu9Z{$C`$IlV)oSCHxkpG;%6&)%!!?FafaWs1)aK1y!zq^?_)t| zD8T$)slORl15C2YYAziZvrL<>eKwZ4A5zh`R=8`nqyPtxMD(z+M*Xz$iT<&;FTx3X zn`aC(_u?%q@;UmeXufky^0bv>=G6%qxkDcGJy9w=>O66Y9cRK{Z}%|y`h;<)*c-N& zKTBjP?35~!wtPLmPqw@&i({e_E}@>vVsAE73_I34VW?PKb=5jWg){RWKypqTJ$e4x z{63vZaAeca1*$5!&7(e#Q}7j*vT+lJf^Rte>B@f(EME3huwzWldSOJ&PhFE+cfd*Gt>y!i7#~c`29vs zjug>lQ4xoipNegxj14bZryD6M+g&Udl2dqpCW#44h-( z90HuQRTF;4iGMA3`;^3WRK@YQX$1AF2xy(K8^X6CC|7n43gHVRs3mrlptkou%;oLh zu?T$8ORR}4=vE(Nu^!81-Z%bzZ!tP*1aq$LG!2l1=MqP2HfaAA=3I1G#Oa&$4Piy& zi&P0d%~djXRucKRF$LtBXPCL>UUtpZi7_yhNXbf2G+8Q0(H_ACQ8$q9jZkTxZ00vs zk}Rlp%v~*O3E`AY=Tq>i$q|;_7Fby5agT|#zYA*ZsBN8*kwHpHsdCwt;e#k4(Ko8u zM5UP3U!m#we&3gi(r*VDs9qh5a}btG5RgmjC?`DO=Bi+*i?NUb(9Ogn-W-!@c^s)LJhtZr*sNN1Xifu9005_4+x7#gY1p zZO{^NGbk%Kx#?kPH_l>9yw_zNWx*q9%!>^=rxG#~9?~B!&>gR}b4$p{ba}QYJu7YN z+yjRdU5YrDewylA(dB7&Eu&Y+YzTTY?ihDE;}PHaX3NK!d#Qv#>RH~jYijiI@X;%l z924Xs-v3`5d5UUZ4;fuY~fs7^%B#&nOl8KZWTF)T)8R^nv8$+CfiSJPKHc;%Hq^i&? zv|0%^rOOF7-s$CP`>Hi~ulU??GYIAHO7Ioc8wMGnx;a6@*ee*OX1XDCSdE#nV}tx4 z`FXu5&~y9X8F{~O{Ji=H;>1p-o1Kpf$@rWei2r!`1i&nsZt5fX%qnv-cd@H`*xBBv z>>?1Am}~-LOp2~vuvX4ZPB-tzJ4 z(4B}vLZ|cu2}(}i7+}|b4yXDYugjPANw}PVXbZ?N>+c7)`&@H z{!YxS2qyB0-wzPL*`8r?343AEF#8x_>LN9h(!6F;mlW_n!W z$Q2em&=vymK$|UwxZZpI+@5v{513G&r4}g6IGK$h!4BM<3qd zGQv1&v5yI~Rg#wqg*Xbv+#K-nOL&%4+S__FAT6Mxe?Q##+X*kr!G*B)>AbTrPI zF@4(n9m&*Dh~KKNTEN!Tf2rW^x?Zp7ry%+3#9lw^RB)WH5=bl4ux_Wc!y6eRk4m!3 zd)dT&lW@Ht`3&MC-z_a$IqVJ4n$b<-$P~Y7W1^dwOlM_6Xk_42 zPM-eoIVEHVs|D=1x;y&nHK&A`NuX4Q&f>E)qnCHeoh#|uN=Qrd@m0S^npx__7D<|6u@f+u|xB1Off;FkeyMs8M5EDM% z34Zmu6_wBx>NOJYYG~kp>{-gpDoHo#q%<7l0%He<8NNCD>BH4<+k1Zo6tD8j_A)Z} ze1%Gt7^Bhe!mYVZB$&|5lndeB1Q0olupF`@tK~4#M71csRQj@K-Pp@soun}PlBBt z6P>AF&3J@3?A|?285t&o*#fnF81NPtdmIo9bphM}sWpHYNH4?w0@6W;{_Xprp`m>y zP&0A~yZhM{RP(df159dRfVIxv?%*_=b;IcDc-Jfw&Y-D<&Qi~jjx%hTXpfaX!h zK@Q(zq80aQuLk)3x#w3=2Yr%_nb~Bj0nk*XgAAL03OCm#8$WvG*42ZI^9dG1>l1&x ziR>>F#+nlxUoQ?#P4FmUnJ(tyX^si`ad>eyyDG_tx2|kIt8VQJ!lW z%l>Mc$}T?;b?m_P>%)3aA-RR7d$C%}?N^^%r!N2HJkv@+sBuiDcq5V^8vjb|a9G5j z=civ@{Q0=S(kS5iqR#{_W@hmDwbuqcW2Ep!U;mo(d>QW#^OPqaOm)4{&USP!H7oUi zEHZn9rTw_yuL#!G4I)X;bJGpxuWi&uOH<#TK4GkFaCaB5V)lM=+J$RJ$a@=8@cMm| zT%CBiJa6T0&!!XDwFvKhh(DhMF`;|5U|}a>+fM*8nDRRxnWN zg9-H+riU9awa4w$fY!Oz8HOXJfTxr8-gpVK6)@6MoplM^P2!8@1VS(Nq~7?vl%%9# z!{0v+c9RYD&%12YE?>^xJmVo82soQlAlQUygI;>>hf>cK;~J25%RAp4+u-o|^XH8L zLksM%1Wfnw*a7fRRO}Bk?u}*&QBxh$ik!9iiqgeL4%X1>D+PnJOa5l|H7vPpBb?YR zD;e&omlxw%OFNg^M|Vaq#5!&4aMU@B%jg5_9?@<16*I}0}S;|cb<|{DiZ|~@^cRd0SSbB^*Xyy}NP}Q@~{jjq0$X_pK ztz{MrnD}8hR0`u&c-Qu>(_7FB&o7memNvq)0a4ue&HN6`yoiDT7g{j7d+XD4-T6yL z62SO?3*gm%V7MAs_YLrx|6dG?B!^hnKG1us6KwD3Kfvhnd`68bs+ zPAWA==f*cV7yC9h2S=w@SDcR6wd4xPz7)@PkzJxSpQaLTRH|#^C0X9sGEZXZcKZ8~ zX)rcbPrLS+_Lpz-^BRv&%2@$k2D{~;wmDwJsO2p@!gHYMR;>AyiS-TQUO&E5dwKo6 z9WVXCYEvr-%W&LOSdp5d<1Ma}i%!iCPlsTdO(Gui66q=&gU%(DynpIw9DF!P}(U*6VVkVUAUD0#>t-M9axrl!Utz|?832XMx>knLa_pb21X zIX=b)@HC__!En~lCtdx6l@ z+&X+ zlD>1{?yJG@t}n{UvuE|6Bs(yOiXsl;H-n=bQ&hvq9BcOfS?Ts&xiVoMcV?c?Q6y} zj4*YP-ou!ihf=@b4iSAUQ@kK4E0N~L+4EXkaQM%0 zt>sPwx0`plE?r`j%Z+94bnoHsWcK-z{oRc5degX^W?Q+f+9~FQ25x)$$&*7e8ehDl zbgL?v4;OKFqBsRI`iU}tH&t)L3Z>gFX9lpD= z{kQyh3IXkxu}*ZNQH_m6cH=n`+NlG<2?Wl6^=lW8t*owq>=N?i5&?-YFK=%SF)>=? zvW5cGoOH+9(#pz1I1#ucB*yBS>55&=MgyF2E^w-8LDq-qRn* z;Mk#8R8$1-3+>RGe_?2kXG^A}qKib8hPD$8^5_7HBIdKXNOa-C1(;o32LwD!b}Dx9 zyEZ3iRZ!7i;xHtFtdB^K90^NHV?)Sr2wM8ytH_n+b&|6ZWHo#H`)2@S04|619Rcth z^IY@SYL`SX3LqR6z9PP9Rk&2*vT$qLZ`bE3%)7}k>o`5_0lNd3(q#eO6X6gMoE30$ z7qO!G+_#}2hY6DR|HCdNRc-#bAZHIR2>elyw+SHzk)yz%sTm}yrdC$W))+Ro3kM8u z2beEiJt`J=?^$a>#nJR=XswvS!ZDMpIOW`UnqbR1XZ!125{cA1nIAs;l{m^SeOQwg za9+CJJeQF=$sK1ym!udvLK;$ z4zQlKODXkLlOit5CGFi}Z?3WWsN!mI)&)-h&W^{9nT0^d$?3keY*e$5dH>YevsVF$ z%`Gab4J|1?V0+w$1!azy#;5|ReuL#3Rf7e4-}p` z2k8$L{h~@rxFW=3fY~<9x zsTT~=HvoPpq5cWrqT(N?Ho(I1va4$`pheVxXu~ZmtchH*@YsVJ$)UWkK(gNBZd8|GwBfxI|66r{At!e7SXVGN#AXY|Dc+;a*`~f3LW6UM!@L0Hi>d zrSE$HIU2W+&=tUg8(rT8ywXcBNLyV4v7r@fponciI-mh?$BG^-q;Bvw{@^-AD{5>G(v0r9U+?J9Im>{u*QF##v3X_@Vjgmey7Zj5o{< zPRYueoIQIMr7_f@@7MwJcP)Irphx=7+}VLC*EWC}S_4b!X-dkA=h(>R(NJSDG%ma>IUkKh89VxcQqsidaxIUVNPt5Zx>KJ4k5D`v?qHje zYcBzfJ-xIf2s(mvTV^%x)^YPEWj!6UPC3K)-{iV4Xw?x00Z8ao^A?!N^A2ADd^eqoiwh&LR4a-Y+1MslXzK7Zts(24 zcGaJhf_KdY9mWCkHe(@rquM(;Km*goCm}r{qgw$|3`ExPuAC6YXAv62VS&= zKhA6l2MQ#~`BwU-fg|(4wrT2?SzdnS2dCSC=1Y19nM{JS$c6LP?1_$-hRUdZ`+#@!D3^ENrVZ)L>nP=D^x}| z*3BcPt;9=Iw+5vN%EN|&o#hk&y?KcQAYY3$J+ z=^_`8MR#hqUkkc;?11=olvp`(4&Y3f%K-raar?m9amHhZT_v~H5GO9?mXw-metj3f zc7zIXsiknn#5OfGk&gkfs>SlOzHPQUqm*kpCMK3w+rYbPBkCCS6Y1OENHIWD(N39& z)$lk7g|*cVQoTe$hzWu{+28xz?1UUbkGNAy0-hL9Er2sQOyV`sw!Yb?{nGJ+lLwUR z`cuvQ9vr5C4z-?y8qgrAnvU8VkRpUZ06b?#Yt$c9;Q24*wyvt=o%P7X`c-&B`vgY*soi{>X=4(>8u4ymoX-iz1u6%{NU=V>S zKKF7)o5+m8o}cs%8~{z{8iIDAzU3@UWvzRGqEDCj5I}|B+gBhYiM+f#WDfbIfnW`W z0pQlk+g*uxK){m+G9MuZMB(<%4tCgCj7c!xY$jS8iv<*ep%H~6WImW6U{Dx(cXccc zLI#G{L{#*U0J(}Ca%(|5bp`B5SqGM39K6oa@k&ovxJkIn+W_ZBse@bc_WjS(rZ#p5UuL*Tfbek>{0J~};efhtwiPp9znyr62ep8pAtSmDCaz82 z?@XhJ!KLgQ5Z9Tu0di_6&LR6aM1=&mXUHJ#!Rj2^+1cDH9Kgb64*rusAU*=h*uY#f ze&a7X>s3`L6U0=g8WZA|)Wom(n~9$HtAo8a?;D}cP2oW_sk{SWw1tAzAhekF{#2yY)pY+fJ-;F)seCD_sg-ow%k@T7HaEp-JR(m;@q|ZR zk2YV<55{f|Je}^TBGbpi|MXTqo#L=5{GI1@EcJ>%9qO#63elZ(4Ve6PerGmz8?qKR zgct{W`RWRy8)6Xmm2RubxBv+hd|g_)506iO_%5V;*wjFPdxA>oqun)>n}aVd-If}_ z`T!ftG*5}00Z(rPb%&qjenAqLcUDG$l9=_bXKjAokb}{G#5&q=ScUx6WO)YL8HZdgzN<+Y}D*+t>^-_X@Fi5;n z%6H2#)V%Ta?JCIS;q=e$_?zmU%&bIb3GLI}Va`Y4_R4FCbS4c{_HA zsVZ(r4p`Y&Dwe{4eWGs^D=sHzh6?iUpR*!>imnChA#OoI4X^?hf}EigL{VkxzXAM> z0|P}xPV*KpaMYoKK#jhDy&tM)UR>FLB{8&pA=?qwHNFDzQ5HV?@0lhK>27;KB7w>l z$YQzZ@2ddEZ4TUg=`b4*&kcqpWn_%u7v_L$m;f2ME<|%{$VmH&EH3=m*mw$cYu#@- zxOS+Z)%5kBp^^nPF=0)`!iKqwl8pRV1L!2fv>_JC$-#Ojh)6dilB_`;e4ub&&&a8@ zfg^3Ic6mugByMOtC+}y0oA2`Q8E6dSD`X#kqjpeg3*B__IF)lq~sJ zmD3mx29+PB&|sAI|5FaZSK4#=Ig(kPo}1$ab^y)&ma9`WOgHP_)W% zkn2AId?Gw{$czdMA9U@bv{KwTY4@jbntQs)!7j>LK#<*SV#q0fX8h?Q#$F1m{ODWG zM$7fOw{ORICRuJ@);%Yba?34JXw)Ua5j0XWgd|x#+6#_?% zdWZm6%w;G6eJB4UUownWst1-rixABg# zjufI|QHg!?5zD2^F@Kl7l&1dr;rOjK4vI5h;t^eOVFj1KTTo&&AYJfxluFNGVj zP>?m?ngsfVH_}ATLcRm;z@8%Co%{B!1Gv)c&;p@__5gIco-dD9XaEv@_R)_h-qaX4 zZVjULLH6S*P!O>rf1!}B6aCaNi5v`mFWFdIw?lM!1uaeVMVy>UpsH$?@gw*35bYCz zF#zwb1$+r6Ah7~%*6Fo1QPd&^TGzmz3(wDcyT{Fdxxwk*`*5HZ-2MbUADSsNUUS^M zyqyqz=ir-8Ko^IMf+7|kyfJb${~exke<|}jP^%KqI<&M*hcKvq<;sJ@PR(t$^Ikeg zpOuW9oCa>DW-&L&aM1vowHd@WJY=8eAIEc-{cD1~tg>!sl~VZ~MU!G4Lmq+4!%riVD{2%Fg|R z~|NdlBJR$MvDhR~WZ8>!JIGA+?!ze>j(r|jqZ!(sG|FMZNs{&=LlkQxr z*qgTpN%6(|dogBOv|?-0Q$PH$=9;By)BHV-em9LK{H(qGADdjdbni-a6%myer|yFG#D%bekW!6*|S1~iU`G(ne4Ln2;W4=z35W0;&h}@V@w8r_oeDx{=DASj2e`pPYUV6 z)UDQPv@VETd4w(I8Hg&s@opPUIcHS3bZ;|$nFvy|n zAx-a0B}Hr{u38EaM2*AzlGrPBVvN(r$(Ql7@XLQ=d)pg-eS5=>OQN(_ei+ULv1LJt zZkXs+w7N@6NcoLmGa^4tg&_<99JUMe=?fC2TYk~YXo||xt@l~*L(o#@5z>u~PuHRr zxq!0*LE{7BGyqTIDD-ZJ0VaM}j^`aX373jnh(r)m~U3`F&-7?Wg7WLz1&I&;W9HGXND_w`Q6 zAgNd7wHR|DSHPO%p4JqayetYKwII4=UUYn51l+zKfs`|LcnkWlQ=p-PZuG11hSbwOShGr%;>_a@vLci>e|3LW=v+@V@=LAPH-W+D-^yCY)`hy-b6)P&FS%e6F3^-t zN9HiZcUO!(glj5?NL`rLQFi9TiyQC0ZV?|@vb7@N zus?f<7s=zspB*Ngk0vrQV9zVpJ=2<7@QT=$>(0e`=t#@53D+f%_dRnQ<~w~6BOV}LJ7Pl0#GMs&|$B63bAcwbrokRvbYC`Nbq z7ACuc1e=dsVW1X26G6_>hJBL!YFa;o{ey|(fos8WqQ*ewR6%Zw;?4Zy-&;b=GY)zt z{9Dzqdc0%PVuEo>SgYrk}O??NXinb zcde>t{)UjA$q+71u@1Jrwe-ukXYH}<@6}JM%gxQDcRT0zeYzZMR=>QEyE~RFo%U1C z(4;0aFO?^l&(u4MemGu?be8+FlxQfn^3F1ni_0|6;pi13HDZ-GZM1Yk=i=G}G6^!Z zqmYAgd@jVU@QfxopBskbF?01YwL*$T`e2b+#AG3*?T}9(-wmpF9x>OknIV+E>xjYP%MbnB+-8+MrzfnAth<{vB~Ri;nn#=`6k+r z*{6SyRr@^&O|1C)THOp2S#mGDMuL4L!;E*7`_u^chihH3$PH$(-cMbR?X?8$r$M4b zXGy}utqP-Gf3N7V@w9Z)T^{XxgBi2eUv{-4@S_PzCM3J~RG8tZm7>sYxbn)hVbHjT zfG3Web}*MTTj5gjmZUgmONdnJ#=Yz@8cb!KzGHr$z`P#oXa^lv|21jtZ@E7y9Obj8 zCrPl?p-pa4^vR=!NvD)?FAnv{DlYab*mib2vn9xYhwE1PddVv(Oe)Wlm94ht7!N>x z?nvzk=&YS^B?|ygP&4&AB_+0%$3~@G!nJH_sR!0xTYgw~* z`a(DH($9dPNT}xTxZ=AOc|?(A5=1pWBvt}KSR*UcFO!Zxt_bc7g6*@Zkjmc6fa3`g zCrm74P9iGBtN1QWueQW%yHCO{pD+5vG9l)Jp6nemJUYHyJzf1GqN@Y)ct-f8)8$l> zyoyRbjy)GdPwU>sZ^F~o(=jm?{c2c2RwPYE<9_@UOTvdm+02RNB71E0n3AC3wNvaD zXs1sm*aoK@P-GK`A9E;pDq&~o6&?0Yjee`M?arYL)Dz>Am-vR^j!cDohw8Q=BH*UG{Z=G0C z(ERS1>^4{-;z zZ}GIecn$QAfBg5|-sH>KBve>)0(1YaUbtt&ITsyfuOIxQ{(-~0&n)QH zna7eQ()_OD6^yEH=cXB_545Xy@rs0R&HK`_7J`cuR8|z>;o-wTm<6L0`!8EQ^~gl) zPO@t=nG`hf-I~dG*)LpRM_J%gi4QK zqc*N{kOR94DS$wCQO=V@QCaS(K#+PBgtL=XO{v5XIV%aBE#8FvEg4nj-EWT4lDnAI zkQ-{kkSELX%bxYGegrM~j|z=62C`*x-Mb$St(YD~QaS01@CS+B8Do+e zr0w*lu_z*UDmYKuiQIHQI!Jq-Gs1zbW?poB16cOE)(gsy@SVZ8s>e zw$Hg&klKKnMl=X0kaB?H%#*k{>#(vvo5k1P1M~Lo2aBpfQP(B{eeVi94LSYW5z$P- zPw6LKOO*$IqKybURY(7eXH+^!Q*$quzI$+IGsd84jwJVDqoGgQIKQeE)xr#}TlU3` z1a`G1B$PJhRP}DflZ%R!Wou{>1O>I^HgPxa+)>6Q;YbKOmUX#JRC)S)>?0Q?C=C!f;&jGI=W>h5*CT*21vk7u=8RS)eQsEms=dswr%Fl%%|h0?~uh;#7(HS)>fXxmy>EDXxWP zeh+l*KXCT1+X|F1wsw&6FMU`)@{%P&B`yEBaojr^?gw#rbt)A0($$x2T$c)?r+ynCvOgB_P)kP@2d$(mXoLHuUy(&k<&0hRNnaN zR9%>|+@}ih@keF&KO|C#vv?sRxT%oNF-+S%NJ418|Hr?;rQmj0^N3Z1K~2hZ%!98N zwoVg&5EK-2L%O2?$7!89BFzH|UUTjqi<6|(nE?l251wN~FetbMU zu3pNp@H#v!1*2ay>DYzx$E0JbPNQ!sa=(5{cF!ii5^st3fIDq-(IO8=OEo4;8s0Ek zDyPM$z$Y}QWFt&l86kgaajMwybI9DflQK^3d+2O*?*1|IN%|xEMdaC zBuW$(7q8ptZRhTbQskcg8@NM9{o~8U&v`~Gr4msp7K7%Mm`6IU_Hn-~vCN-JBSH-F zaOE;e{hsZ^Y1w&tv_w$WUOHU|U3?JjIS#!7K0!h7Z7mhz0s#_0xpj^U#oF#QVTHF?rDV#;GWEzRyb=kr9|jC#HCsu99=6{s7_e6X1}~3x>H|QIetmGRJ4om!WhiWN72D2w!w4Q}tgi|2Jq(q@z+dgf z<0(&@|5|(;3A&c|Ag)Vpwb@1&mS`@=Vu zO^L5LRY;S2R_`K5k;1j0%ygs8L{bV1DxX5zEz=bWFS_e~DO-K-uPZQ%h2#88wgayA zOQ=y8RDq5i#r;Njdt;U)catP?#O!kTLjW?c?ENNhY@M#Pm2E z8)1)U+po&GzeZ=9t4vhh&XU<8v9j}L@@)xahJrzuoT0LOm7KBuACtsx{*z}$xcr(U z39kuX9lm|>_$8sIKTO%(`=aD?!m{7ot}*2k5^{7~9RV|5h#UkM5T}R%V*1|RUgXc7 zqipglpwz{~_O4{W7&FX(D;&>QvfZbDbL2x<{HbHd?rg67Q9iaG_()i+{o;js6_*83 zhWWLlnlwlFp8Vd==zruDk~vaQ`B>FXn!45IGyaH_Ak{4jqUDTqIT6~otz+d>4d+N2 z0SvbeN`dr907SoHjyYYZli{4r5oqb^00ACa?noCCO>W@iev+6t>iv+LlN`>qQ*TBi zV|3HDapn3&-TV#*zMBW{+zeI%UGs(Sd%iH&&Km#Kl$h zh14mvQQw$=j(h8Rk_!V}rr3yVvQVV8nJJ>o_Q@fSTziZsu`fwj<&| ze)J;UmXGbIdt>iyYvmDb`yW1Cc}vpYgBRMw#l$S32M*91!~1g&^YZfWFrXC)P|HX+ zMwm#r$%1s%EZ4%HkX#9!B{B-Sdc~&WOrHh{D>`)i>l(^^9DW@{`NZUHGl3W%g|BTK zO$1Bj#^qstp~S|7s=>RMM6K}8$qgZjxSMoO*6jZHzG(P^*DJ=MotFKk@dA^g(|T`S z&4OZOzW~Rjqm9HjtoZM+lH(~=%{ZF*7MozPZvh64^b5kMNQpzKAD;k&O4##|O(0<% zG*LoiFTh0t^yN7ifFjKP-t>vapbt+4IT!Imax3@TZ(g(fF2N&VH}tlEgzUuE}Cw%jyyne1_gU2Ma^=Z1*8;`T z_KqJZ@T1W*nV)rD*=P6TJVxd3aeSYa;SZ+vZ^P@x3(~W%EeB85y6Ce;5U=@`f!;V`l*p053s!%gNF4186{^G5w9r#R23=jqLWohm-+HJtH_ENKJLi6LMy9 z(U_+!V#|Bpj#g|1yuL^D3hKL`jvv&`{y3<-_|CNAFFg9v+CPppMbCLu+rkWztydRb zYt#BHh3|Mx{fPLnoN4Gb^NioMgSDz$p1R_nBn*f;k+m<^tsf>?04zWKm>q~jGIugY zSfKN{x>_psamZ-roI4T`9Im@7ik#-4U7a+3Y7qmboX8IiiJg&hAc?m_H|U?zxw$t0 zRe^*tFanO0&f!Q>I9q4e+a1CEY@d@@{^Ob7IQ&j3INH#m3$$##PJ+=yo8(Jc@- znL&p2;Ae1OEtaQZsRl+*?~!sMQjxL<*x_bkVsZs>(nHB9Z~|+ONsC-y=zBi~ze5kG z%CmLS%5wCFu?NBrr_Afj@G?+4c?agn7Vu^GwsOgGka(jr6GU;~QXW+R=4}coF<-n$ z0Pi>g%wWrslv^*~yvZd*->IuvyT0SM4Y*U}ri@(Xvh(wm0|MlEw2~u{C>D%gzqv0c zE3+;m=|LFG{}{gccq*9Wf9luKSLO{Ru4g2YNV2ngtE)VM>Ekc@d-+fQ@II zzes^tW?2%*IdLITV|BMUzm#CU0Pn~dIRPUDMI`rxmIy%Is)6lr z8nD5p;A-e9#bP7*Br@B?7ZAE7?HFh=pE7^t3{Afb8VqB z{3_YFLkUx`uG@AXZqg4tmi4;H{iEPu#|-L=ZGSm*N&XX1SH`^;6BA1ZX)chNkto~* zQ7p2MckGySB)tw&dzt2dvetxW-;NS)B#*_#MSxa);AD3H%19Xr=w2iF=0gckzy_fs z91vk=0`|P_Rl}>b1C<425$M*hDR~`GuBP7M3w-~%TW~Jk6A%!1U|H#Xxi0V^026dd z4Zs9VAdU1u!%HgZ*)yvRT^*NlkcUU_5eW~WfjuAw;NI&^?dUl=kc@lzck&#EQLl{H?V{QXjLxhZou^w6Gq4qHOPgp#%mc4QEF@S!uHJDD& z(xx{woW%T7ztMT9&46$lC#b{Ea&g#iz$%}Dx%Ed7y+iSJ<9BRrGR#z`k^T`p-(tvz zt!~|#fq`Kw+`b!_C_f)R56Q+7GD?T25Y;JCcLZ!vj~a@w%P9Tt`>#y9*JKixLHGuf z$KXsp%&7dNBUCU6FSDGd5L^nsl7lheK*0y+24S@Zv}002WeD`e5Y z0&7TWD(tu`V8y)pZsnh955*+(8Xyb| z(!W~g41~F55vm@>EF!?^BYV?t=NTJ0Y7M*H3napR z04po2w3OyevO77_2zMx|kMHz9P944jVG1dwCW9~_+M<&`qei3twG5#Cth?@0pPii@ zX)Im`G05xuNemLoymaZ3GN13>kJg#6<61~JJRvsgq()H#BdD29_^!zrOzKp<<|7AK zF$KbYA+i8KjSk;EFa$x!>!hIqJ10I`kvGA0QEGR&><7?NQt}+BDhU4D?wJ>D9n@x^ zU|(P>7&GnzK=HAsr(XD-QclshFgXtJnf0p1{fEbCvsD37@eWD00`hDiZ4mT`pX4AU3qT{L0jBl=43@pjeKX(x?@;uS`*)GOTLuVCZ*MOK1AGXe)I>9V zItpbHz{_~p$aIGgrp6RB%m34VzgLONf|Q*S%;XRC!Tb8IioCj_OlS!}2b4VDJI3}1 zRN#LeaD2Z0zx`a_46*3}`3N8&Rg)bmGr^}PaRs6VXxt&Qh{z>CjKJjixgV|a_vFO0zmTT;xOcF|h5}N13yWiz;t@v%DOXEe?g$+Aw@*hc@Cn0WZQNgRL2d;% zK4+>N$;}?hEiC*9B90NrtQ6THKoN&RCgOa;8Dt~*I5N8*oep3I@)7z{>mWDBDJWX=3Y}o z`R4UZAc?m$0BWZtF znL|X!V3s{)L7Le(tQ0=*lBI^SSu4o=J%CRQ%@Ed=MSZ}c`Yk5&zN_*#QWBra{vEI zxyC2pogPYof`FF-I~78go(8xm0;JeTK8(!12)lv}>EMD92TDZ&nezhOYVd!zs$zTc zlYzcILnkvbes-<`rktx(%!?O{6*oMA+yT@fiJi-l3)lKCjv>Vxh;VPv$*#M&v{ZuB zctJt);P3B7w+{X{mVkSxUaej7I(e6K@eG)ufYkPVs27m=M=R^yWY|7uS^o`9ndYxc zN~l3a9*TBlSjqP_{Qc!HO#uBB6r_N30D&$80vg<8A!LCW!D+aLHX+DCPM-u`1CoQS z1`5hy_FEaS?}K>K$eIGQ^`7zTod!@gF$-j5I2;bS(<5hLB;R~oOX?jw@E8Acb2&Ei za|gs-Q{gp3<(?i$>$q~h3>H#bPmd}bL+z>;mCd544h=!f0lk7CGkE(&Zn+`7?lCpDKni?7xot>TU-!~U$W@dJP?W}v3Gpq@Wjl+>pb3xTaGjM!O zAUnVbf`B}7$UxNqxUEHn${BmOwgh2Z%Hoe07jhwX>hSRHRY85y=oE)LVW1q-Dm2cr>D<+`I0a? z6Jsm;TvJm7Kz}bTmkxU7%dh@qGyJfw;y|{&Bo}uGr z31B~DfNkyB59wFZ7eL2!&zxrce+hS{CpjU$6x7H#o%nY`)SI+W0s?tL z7(s^p;P7XV^C?GP^8Qp<6WC?jCzJe!2=Wm=%5~gh=$(BhxI(r!16i1gy?rj)&C%+l!IKc?wwEjpqJay03^rQ@ zyf+z}f7h{Y)y$?3gfZ$8KQ|SXaJTLe5E%!lQ1(C4Hk;NDe*XOVBq@pFe#?ywsD(Tp zDX;^goqn_A-aTTZ28{}3B;5+azooGzs>&%jg@s4&pAh{Rt1V9khXuga7~xw*0dCmk z%tWnA@sAsk7jU$YdB#_$+#_o(yuGF2D3q!3P-czzH@bUB!vf)qd`REB2;ET5kYQUq z(DtxH(wra_a0A?psK*@a?N37;1G)xN=+J`H|B5{awMXTjKR&3UMbf#DDu44~W&gYoy*Nt`E5AoWEb4M`dJBz%5JPs7UkpQY?~QxQX)`eF48 zXEMabj}4$ksVis=kLHZmx@7=6FQ?2ENbaE}K?S8561~s5+VcPHqkOr_c{X%tsRb-% zfE;}N464NQ$O-EQV0d91)pVoeD}at$ z!cUk-0yHwcvXUMY5Lyn)5I9?es7Nip_q{@XJ{=t$r>#3^&;RPZcm#3|4WoaLZv^6k z5l$=g50EYvRt0eS@Vip&3ANn+U6KgIiMhGC0ugIdW8-Mc)1?39(#FC_Y!%Gb4!bBY zWuNcQb0P>1D(SjW!VX0%1aG(;6;IE~DB)9?g_n-GvibkgeU^}Lu8BKSWFAb%J^+jq z%%`YF@q-5JTi6b^RSm|kR{fX8gS)+0I)q1bGV}A>xshFHbOhTMpd7~}CEZU>W|;xL z-$VF+=z1l2odWq6ilWK^wWow?PuJlA-2`~!H}OZ2wPFyFfkDHH)U^SYipF_UP(HOn zR{IH-@TNO*(SQt$nw0QCuR#K+cyDaDLto)JP9~G<#qp)pSRPjJuFn*JxYia!HJoH8U^sCCoiTm{I;0+qP@lN~^Tc-F~q9JH3U zz?Kh08MgQT(mx(?lpw^%OLqIni1e*pp*eEKiX$`YDr_h;mq-3zK*s$6K*sCPbFz`V zAL(-%f-R_TAkz}aOMwbxS90fUo^wv!zim96;xGG=Z^8Ku1*N5Z&xw}r$e2)~2=*j4 zmcS@pQy#hui`|*nF?jcI8lzzk@(1je-*r50a#>mKGlZBQ;LCIqwTpl~ibz;9FJraN z))^_|LjTR>9tZAm{U5sC0xIjZ`xbpk=@RKK5lN+`8&m|OO9Uk)1w@dL1}RZQrAv@T zq@_zlK$MV@5>XnF5CqP8_`d(S=Zt&r7<=sDcDvc{`};l5in->R6IE4k!EN+JF;IYI z6&J@C)C>vy7s-$&0q6|olTgkmL(GTX1Oym@p#XUL>{)hkF^OCTc~JGrEqK!C*1|Fu zM2q?C>BUoOfPp-FX@ou<0sBVE^gn#yCUin{boC&PD#$kjuLopbh)ihUDtCj)Ktg)D zi+5#YL4+CjJska8l(&JVxr>PN4gWmQu-j9m?gB6{$bN!!E%5|%5a1C7b40QQ>x2fg zy&VfF)S0CfNN&NgT49Xk?_!Q! zd!e2%G_=L7f?QBgSa@M4{?Q{R%J;T*c4+iEHZ}%Wc<3<0p(|KO_zGrh(EE#JeB#;K z3u7(RF$I^-3*NeC{AWj}qC*DXjtdPmq;oMQui5AyUPMXMe|C z91|4%s^V=Bfr9GwKmpTZ0dq4O=X&MXw4Owglv_^qtPHL=N;Vz|Ru8$YS(pAZw_#QW z-&dpUw)5}6fE>(-n>QG1a5ymX95sK#Sfh0)D6lvS3_f|=ed6~$JH%&lGwh6b4?ei1 zp19P`CNOn5Gv1+`U`oW%essD*kAEd`YDGDVrGLRgmH)=%NZoBLHaHzizdQF2f%0Nw zjRWW_KQ?x(BPYWUer*_|<*eBL-C6%jWg8r9*c(LaH%Y&FarskRBlob$rIX}7n@V#w zHSzSe-?IDP&16nNIkGS7>2dU5?AT<*(oU~Oz88h#hm4Crb|oIRKxCk?shtgH{F={` zO@NIZFe}kD_@FI6Hl9#5g)M?DSSf`qp8yXFcZN2=W-c}05*s!J1$^(q=%Vr;LQWe4 z&4;Jw7h}4AHq$)G6KC!VpH1SZP) zyF*nccfm0th#*tZSs{mj^v7!#pU`f)jxB!JB~WSV(@NlI>;1u=|84N|C5zeN z5?`<4Z-h>A%l+r1a;l{sbXndF0QDa=jM`%L-+=v?b_}*a>2|pZc?J%FO6cIe%^=?u z{_++FcZQHS5j_%XevvM(V(Ldemu2So-6NmOnaZ*(r9n1;X5b4)%<%d;Fa^B4ytiewc-Vt#W~W$OzRVpK~l=IiBO1bW2kyk(;o`!=va>6N+x++l4l#e4qzf_B6h`FFW zzgNEV>P45}tJR8$FR^v}-(9r}tLm#b>;IrkV6dyX?QfWT_6MV~{WBCBugC9h2ghxU zUeDad*>;W~D&KBPs2gbQSJ8NB zF~dU|dgNPcP^0TSm?=)j%&9=k7~8MKdy51H+f5eawuEYn=IgZ* z>q{{wB%?A92)h~-YGZw<$qel_PRiAFR>`rCq3d=pafTI-*z9QJJ&^5^QC*mc+77PRS&vlSxWFl z9x)gcl@?rI)+ridsA;!L?=*S)@KWRF>t))XPW`sdGX|6Tt1>UYsVdmB*Aw_leiF(a z-23z?Q@n*!rt7YCE*)2oX=KrjKaPpGmz5sz(O!t?o{uu+?&Xewod&o2VYCM!2fBIs zSz52#6c^aY3QuJb;L#W-aGh1vPvS94tctSq;5dbqwOt8slykCF*C|HsZmb>--uSMF ziMASR9r^xy{{)`=tma8p_h*uoDc4k{CIPW^1CLV_h|wq>mWgokp9~+Xq-ll~o)IqC zR^u%y6VJc)+oNbL@{11`de7z7Mh<`e!}oC`7+?0&{P+EIFps9hYBcgmG2|pU-(s)N zI7_n@c|FRQ+o|Jgp*u6tz3rZ-Ol3B1;AttFfQ=`nMOv8TnDZgq@U?1{sq@D@;xe93 zMdI5B=blk}^ERBrBZA<`nNVin6ub1&v}%N4@%H=3nhs6_ZPk~lw&q)Q(-m>vg!4aI z`ICitI5^JmnMV^JBpntI7-n)9V$8VmYlckdqw`8MW4(% z&`rM3pd_#)Z~zYP&$GMmhgdHZ)4wmb-8i_avif7w2UQ9PN`>W>?*GncUrh05v#8#< ztf8^nyPU)CHa;=(iM@T=qL5gy6EAs52`><@S?1=Fy`^S%s#H2RfJO$XR6Qz*CBc74^nqeEKWoYw8Z= z)VCjA(C14ch-QOKcUW>LqQDY_Ww=Vk+4+2G68881ea&A{zFn@@z?4xg=Gc&I+Y=hW3!iRQ-Z@wlMJKVIuv zm^z*#M~re&wo7|ntUe$?$^uDFYQZ2ox|5)`g(*1 z8sNKZ_iXo3}lW zjQprqG?Fc;6Z2W&+z#$;%h?BT0&OzA*xuYRp<^Rgh)!(_u%x}7KazF9I7+rvmY4Wh zYhEqeWsqb2KCWz+8Gsa8neR_>|-UnmsG8rAR_zk+n(Iq(6flh&(8a8+W%)|k+>PdQGhaUo* z$DH#R4uTId6-1ul4<+NRxUNp$Th^MWe_|W<7y1=?FZ?yGE#vn*vOiT>* z&ZE=ULvovI+9SSaaWfMq`K4Pgu}~ zqHO|#i%PPJa7o}PMdNgSWt@Z!|2R_9Xs$gbu z(c~FS;o`?lokvQ({EGQ+nl31MZM3}kWcTcyEmvh7+{dm1-Gn=*6P$a0)H(Xq!PltX ztI2G+fl=k9yTclDJuRQ(s`f=dfQLG3r(BR(9s&W~0so!@RnShD^!2&W4Bm9mXVj(Q zS9HjvhG&cF1#Dt?&9RxhQ!o1yp1sEv>=uZiB{=t~RSPhZ zy}sLD(~p>@adiw;_;^RyHfsLC+*l#2A&;GURl~(XE;s1J(@;?I=~uJAeK`9-Ez*pE zzq4sZ4%32J#+2;6e;IN#a@2hXn-86OX&!1`-VNFryXk=f5z2b|SaRH*a(d4Mzw|V7E=$1A4iptp^dz zN6Z>;xMuYiU(@}d>mu~?G$z6c`#Lif1h4ds^O&U24;jeV2-&Dluo8|8Bc`1Lf|LTV zjV%3E#Zm!ffPd#(2Thc)P9%09mR3j}q+7l3)ZdM(41T;RHX(70s%OvG$P(3YywXu% zv^@JX^?lWXb%8%G{CH;H0P~aRmNnTHd%SlPlHo7kUgRtCRgSKEBEDN;LP0P@otlR? z`0KB4Q3C<{B+Jca@o!i^=xhYy!HEp%w0_uW9VKa0(r;VYy12FZ?k$RxuXQ$Er<*rJ z7EeJd+8-yy2uEU!JeO0ChQIyZ+PY4j{_L&A9?ACm_;(Wf;Fajog4|prsG!^gXaXU@ z$QG6j2rVnNx8-L>cA?UD!735_4VcQ_GTRT&idyJP{OPAm(=!5_34W7l zaMPH`L49Y#r6sYRo0stE%)hT&?sq@;NuK{vtWE4ZKR?f|sn^j7U^390p!T3bfIj#b zs>v*ZNuvE`Dons5{XuCpC$c*b}seb_y z$XwOY-+@4u-+mV$uS6~)hmewhvUE6lGy`a@unb3le zQ^XzR+V;cxi1FsXyE_^I_z{k19?rpXX)*QgxL2_{hkLD7t0&zaP_{fgiTnGABY*@AZYfoGqM3Po7FncweNcDMcbB8_UC z#UWz>5s_ee3^+G&{+B42N2Yp@J0Kt*;A4&*+3}-pkd!gKz+)s*09fB7(;L9Q+S8*BX7 zC};MXdLkDRB>GzKbzUuo?jf;YEe1(^%CN+bUCm)B5Y>q$XO!!>4>FC&*bbC8L=ZT0HAS5L-7_Im*6ga@czMV5=5EJ3 zKXh*F>I~eKPNS3Z;6f(F%ERZYhnuAno6OW%2C}+DCvs$0eF4OlUh$huZ}L`;_xG+= zxy+$`H$8m$bXoUy)Tj+y|D)w&p>M_hr!&L?!f`%4+-WWV6>@2%hQo$VMlsjOu+p%( z_WHs4m77UF%;nL zsys9*AS6V4c(6+gV~DP5u)Ze1UOg>{_XbonKNgsf#7Wo+BKqT)=*Qx2~#i9(_8xjEm)LEV%MrB^g^#VQ`%HL}Zs5_GMiiba) zU0-inY+9uSsY(k8i6H4BfuE~c-L7T|M{AOU{vG{$7DB7YM)J2SjDf@pz zBI`?Gc6$Rnx}$;n5rs5lR(|M^>$33Du8%efrI!U*KF~RS$ord?(4fFpqBoN_8nsPf z@VTMwwg%y-wpDN9LM;$K6(0dXzqTu$DLOtWsIx$esfYtvxzBLO;{0C< z@CI9_xTg4&?Z|FE*xs@>IOKB|_Sq=U7>I_<=_r9mbToR{Y&={}1OadIxeurIz4UK+ z&)S~criX*leLLAA95^+zFtqJNPL06L6Sr3Tdi|Pg7_dl@*rX!k^I*$i}hMUA$yOOV{3_y^CF4v7LV_7TZ5- z68kYjv_kkhm`qlHY@N*R$kbT-Py;3&vtfb zCp>bUQP_P3rjI8RU6?Av&=}$2;316k4biAGzV@oR^-~+_(kr!8(1jN}n&YYRrtNP> z6)dO7+`n)HvoveanL!sAIXmw?kgH5lozl-4j~rl>@BXl#RIX)c{=|*6G_o1HuG(B9 z;iF6XY*qwI8_ct#nt}9=CfCS!8p1wZQXDudNCTCliR`#OZA!v17JPS+co#J8(Bhyk zS5R6SSMRF6Qx+H2&irNNPQ;e1+<23>U5vjsKK+I8v54964kveqe|dm%ZMaM|?2T** zU~{;=U%ZGqb8o^(jGV(BE@W#r%}H)LMhTh|pvg-E4JQEzeF)~UxWKNySe>7jhrF0E zL7*PRMq%%}^$*yvh&hg4yMW~YX!F7BH>}gT6-=su4DxAByaZSuFg=4I7!hU$j<%vO z-5syMN1ef-B8gEb>J3CBB%lPV577gfbqU4g>)KLyz*06F^1o%$rA#h6v^FY7BRywF z;Q}g8l0csYk5==4zpe!?Wg4=iiAs?g@t8+dTKBj44)_*(m4yY}PxFM*)=mC?U|XR7 zap&INCY>$oh{KItjRStr18K{Nmy5muODQN~4lQ>6M^Hl<2vz~d2h%k^|1|blQzTrw z;12rJspF$|id=3l)4jRzu(O)UVcG$n1tti%L~8#3;A(7BRxR4!GQH@2yDbSdeqL){ zX-DWRTm~=-S>Qrli7Z_uA@^?rgBXCRC0l4&d}`J#R*2WybN4iBIgW@(%E^QqOa$&s zRQLU4yqY1`ID7~J=5EL7R$w4xr{fprblZ~cE?3)vtR%o(>cVs#sM{?#U@8ps67{c9 zc39uUl*BuD=N^NOUMJ9?e2ovPcVyQhn|3N#4n&ok1XxFTEFTeD3$++d8}gUj@O{7V zgdT9v!JF5!tPR@vpdhN1o^>RtCKqqejJTS}g%qJN<@STwk=-s$e{E6RLMy}Rerr;g zAmA9l>x=@*RjX~Ks(&9MzJh$e3Oq(wykpvaz~X!#WCYQOKh<~XHOi+j-b1e2#eIuN zYYhff9q93Z;c#8&yin5~hhW`zDiQ|K0t;uX6DN2ep@P1v^V&UVt&|9EnuNAA3JoJsMy60lpTqfY2?=F1s6kG@-lY6xcj( z&jf)1su49|I+^cV{j$5}s2G6}|0&QNGn4tIdl=vD&V^pG<^z=W?ke^ zzNt^X;v5F#uEO1>qOX}0?F_826&Ajn5?#VSnm-^% zmkVlY^9&zZfL3fJUK>PANN8zmhj-6A7`gcXOMC|2mgC(Fn?VWb)UpYNMj*!})aM)+ zMaeAWYUy(*V zhv(N3zmXih*BuL+$vI_{qbon&PDm}L;($6&1SkRi=ob33Ji8fxx4S z{nE?)h@$P>^n){ACKzoD$shl_2tFG9NZusEz-!@PJ}^T|h{pFcKd)Mtv2bu#Fmw4W z?JE~v+zROb{;L0q%ZDo$o~++myW--J!F4b3N@7aNM=tHU>Qw3^n@9HinO)&8trYRF z6jc)fB%Rj}4?un^??i)$Dc@9q~5ubD#S78Mgig61+9hEv=M^D`9! zz?DLd>Fkn1o0m=(#&64zW2WB2cHEQB_*lH!N&uNV$!Z#yFHCZ<7v#5h)IVLcKDn- z@on^e29R%S-!&G^$M5`H@!9m2hK02k7b%&TVqnw78sZl0Fu7(B%4T~F(yfcL95C)E zV`{GOaEu~3ceKF+tpC>az+*o&8-=l>R?#%Vc zOVxQLdZm_)L>M~IeojtD0;d35_kDX)Svj%&wKOKS{&&4Lte>5|mfit+br^Uei160b z)FiMr3a@FcDc!6}EPpJi{#)Sjp||{z_l@~ACa2w@NxK`F!9-h)KWsu>aJ`4t-R}Po zK%j?XvbmYyyWwwi>mwdjrh&7QT{&Wbd+n?cz#al&9j#k}?CPD-EwrKwyu5Rs(#$Nt zSxN=D!s>XFO550Xg#&+?U_k+>D|?WShJV<|%E%zLpaQijVxM6!m18l8Qr~J$8Ff9X`7${E2>9tISjw$i zx!JQ3$>YS7^^xK=DV!W0_49F;+`hl3L{}R@wVR)m$+Mc8EPuTzAeXu+g~eJ${>tx) zQTzmiU3GZPI-BH-x(Skb!Jdm+V%xr6q~Rx1(+$e zUJLkrIywGV&!&MOpso z|}mrbo}d2*l0@NA_RfO)lE}h$2;G(zOelUMu>5hE^vYc*QXgFQh78;^`(D) zT;_f+zRJ&fty0L{sLm$Wg)4eRRlsFg{&<(2gG1GXi+EDsMJsub8yrC}K?q5fw%EKAC7PbFdK*R_R|*s!rQ68Jdl&S6F~kFcA*-|{SUl-{QTx2V0D7g%~ZRAcUr?Z zGfhvnC%uY_sKyv~L$+O`7X+OLldwbS>NgGG0Tu>GKmHR3-nReTFHMP9-ihxYDIInc zff^LG5zT-5T-gY)VKKE*aP*6bZ_>8~@w>ncHUYAycDhVdLIMRMd?VH88qX@-;}JHo zmg@_zJ?WX}?kN3?!XtohzX!GKcviP(_t%1)GDaGja8%f#f(c2LGhOm7?)3L{da$5n z*A!PH$MW+?st-a=+0>R*4P=8|$Ob>;4j8Ugon^><_K5LhvfZ#(;IG4Nc+NsCKPsCy zW5TV$S)qOoXz`37ue=E?$J$BjPL~=R*l~sZE|&_~C@xJO*f7I->zXtz6tGDQ>fs15 zd@kxh_3Fy6@v-yqa{Ih*O;?@IP6a^HP%Z&~G4G(M1@CDbBjB}{J5Pv%miX*6)SjEr ztL(TXSzJG--)1!RyO;)Q@ozI(zZDvDC#w@7!Ai2)i84$)Fozu~Smk^Sa^0}+=RG|1 zVpH9z{_eZ4EHy>4utTb-SaQ#J;KjvL7#$OnF@bGQwKV-x*SwBj-a4Dz#139BKutpX zN}E7BW&qleih;p#+CgUNmeIj{xSR5?3)0^otFt^bE$M=*xc_l3WQ~cjD!HNIlBNH) zfktBJ$tr?#qioZXb|VCA7H9uhKkMSDsk<5eeWcx_dqsz457JMf!{xVvpxuL=Tokk) z0^kv)dK^GSaItak_a^hQ zPWznqcB0mO9@v~hY(PYVp4GQ#_cU(Smoh-Go|2_GOk3FG#5I++S}6cu)_eV1EXcU_ zWUQ}l8aPS&$||h)IaC`t-I!0ObGo++xzc0U{Y+<^bW$kcWz7Xcc^cm&7LycXM2BDSttE=~uD@;|kVV{QPKN~EOIr6OZeIQJ-( zqcQs?tT3PjDMeWEgq_90!b0$sPe@IT0cP?|fQBQZqJHUIg%>ng*wFoGbufJ#Dp^ak zC6t$!2iQmLgTEJ0BKo%(AJ_p=8D&tf%L2>>bG(XmI&sGS#T;eVRB*bXP<010FhsKi zW^dP}^>;a*nz=!Q`-B_12Ucc>)d5wc#~DX|P8L*7K3HYOAqkX6p#P}`Tjxj|9n}xU z)pzJc8LpOj33!iwE#TDWJ7al&;S2`JtFzr>J1^3-#LvA5z-U#O$ft`ot7|C3E_M3e zDVvU?tf!3ptXlOh1o*#0+R1m4bMLt{ai-ZzW_h0LgMguldD-|{pAXD)uDuk#8TEFN#dy>I7s2wHE#Rm#q-H0GIZdd6i5re+x`r9jvuy{G<_Q_e{XI+1{|LQdAI37 zA6a?e-M!cD0D{1R-SR;7pOUs*>92UgMxY0S_`M2%0& zA{NOYiEcd;2ZI&z|3NfysA0nf?K@y+AW1OFS2s^5>Z(@?n?eir0AA!!)%v6#NA^f+ zMOv%nmLQ$%A^>tVwOi(iS6_{EMD3=_*W zIeG;hRAt4vuPTA5MDD>6lWSYXVtFAzhfFBvM-{QtgM2A z7B$iG6_iuhAkHj;ew}wY+wxXY@mJ?>vBcHH(6w=langTtbj|DK$PRdA&f6`wCHGWP zD`6%*h@RzQ=EGOR2Pg2HcHNKK@YU^!n@{d&{L$#(s?kg>=3G)E>v{NOGI^M zU{oZ&B(UYtx&@k4ZNR~s1?P_twJ-ajmq=y)?mU41LOsnm!rf&);b;1LOmd{l@+-H~ z>H_NS-@I9{USiOXqHuoi%=(|l*e5vVKIy^K&EGwfzuC?oZ?b~VbW6W*B4QiNL@pd{ zM9BYnAcCXOB+Cjd_a`>78SR=&BEvS0Dd#sqo8zfI&(l_YyI_0<{%y@n$ppVu)Jj$hp;(;XuU7J7*EYSD{mC*i>t&XP=d}*r!vb#!+5Zr7im3VAGiNbG zD|nHg)KF78Sa0t=L**5O!Ma~9^WE4(NAM|UzW~|ANxPQotFJv_|4XIjHcj7G)8;c0 zp^Wh3RD%7mhjh+c(2%k%-dS{mANJ=H=kTSZOOGiYbHL2K+`5y)Xv zYN}mto++WrV-4$BdqSBxyW|XX{2P#<9HpXdp4n^|9Lx!BThJ}YYC#K-QAEMFQT5m9 zskD}R#00a(Z;iQUlPb9du!aHy8X{BzL9ers!+NOkD^Y_TTK3e+w06}ARb%e+N>y2O zIjkXr`-2-g_jxT?D7VW^D`*y-7ty&{P?AF3F8q7ptR5 z!&e}zB|%iNZ>;i@<7?RE(5@{f;uSo25Lqpjm`1I5LYLFRgU%f9hAg#`VXtIJ5V~=g zgTYd&>y9`3F*XP}2s?Cgz1ur_gnIhcajU%Eynt6)#cd+JBB@pBs+r;xm9lo68ttpR zQ3bBBgpVrUO~5W^?lm7U9|7oB?X;}N@En(b_bn~Qz_WYF6RfLo_*e@sb&brvoM+(hdW^pM?6_N4 zS>%4bM-~&hw5{G)0gm!lwx37ClQ+j`srY|J9Glt zoZy5|&U;JT%3I<27{g z1D&y2yPz1$rBTa1nV_6e6jzkMcJsL{9efmce;me)B!N}UpYy0F83Jw3hY~?6o-|$9 z!S_>N8tx$@?G1ZQ5tWO%>dPmJ3yq}^zPS&$&8u&8L4GL6REiYG)vf2fPfV}M*J=lbRwn{HKev5D zBO)3|?7HKaiG|8aofiY4B+f6%cOML(#0Z;8Fw9SNab95@S#ZiddJRoLsTeK99l$l{ zvKSx2C7~#JWLPiCkxf?T`HKqlTXfCLh@bR?!Vnx%k=%QpF}F^4Jh->;-Be%XkYMBb z6v|K*ld2VnQ?rj#;5uSw88{>fCfm1E!nEq1x%%rIYNIfah^$4s7TS5rmS1o!g! zPw~gZlaU2C8t!lLtko^DKxYjz$vZ7@ub^nym!#zQ5at2#ZegQ9t@t4k-(I1=i2gT3;w?! zLNEL!=ZW|pgwFu4Vqwc3uIYyUb_o^>?CxBH@ggAWf(?Mv$P!nMkzm~J-c>d>e%@O; z26|)Qgv|SZI}Ol?x$Hv@53RciNiV{j7E5OzAN$}^juW6`mrXirT*m5_zG!quNUb7= z4sHc3*@WANi-uR#>%t2?XTd|M8~>P#Fc3h_P1fU0Rz&$jE3e9VbM87r_i1`Q)5%G> zyx%%45tc&1j*WRRBuAG`j~!SgkBZnxUxI&PN6>a{@Lpg@P>C#{Dbzh@n5|WylxI9f zH$o&a$R>utyyX)JcL?vnD%k=d-!mu3*9>FrnckGi2FG@)A?_QgqYkkBkV;Fhk zXh4W^hJ~$6nyHYUC@{7;d%{d-`gZb4AO5|hx!v_Jtw;*EdJC-A4pODU9lNwdAQt>SPYvOg^F~X0uh1cRClH&N1;L?Dj#bYSW$=#Iw~ix< z3X2LToieZgf+wX2_r7(!OM=|snB?^-s+3z#?s1_K^*XKgZ2R%L@)hm0n9lPwoWJ6@ zAYIND?HJVS!wyLm=!hU;6F{znkcIJ2&z0!hwJ)Nzh17h3K0^B9#HIg+k06z_8Lbk_ z$7cMi0La;ePa>==xWJ24563Z-VJNb18VVtO;^E(Ic&=3v;RO+*{dj@$tTGUaZwQ&6 z#Nxwf*xCh!Dp21I1Na=|m~sjWiR7B(BAd^%3>>Xjwrq68#lrcg;ws2`Hh}M5s^Cdx z>^~&8GD$astEo_BEI_`II*|wW5rP*M#<5_wY_nU(Yrgq0<|+pJEf$no=gno|+(`hL z0XjUvkTKu@1961`llkQr8arNi&J4Od4<6v}m}CG^1}X5tX8O$wFJMnL8XV2gco5Xd zjLWSQE1lDdI{2t39x)CCoi5GMv!7%bzp*M5QQI!oE^_4}$r|6iJVB?H%FEtR3-Z!_ zaEC$|%8uW0lF&KeI)$*G(G+gF-O(>_$^CHO3#=im!DZLD&Vw69urir6%oLPU{pqrP zsPsg&GH6^Z1RWo0`-iB$d4JO-NoV+ub_f56{(O(k^xqd0#~7q$4!ayX$3CCqZlHB+ zG{gWPTBJ*)0ALf*j)if%cMl1Z^lsVaWM^j%l9Wc315ga!bD&^j4fFyERZ37yfMKAj zsVM`RYkEic()0ww6ODCk6N4ldq51}6Z|)_3<>D1Gj|hkG)@!TXrHN#28f5xW1_ji7 z3-g?S#p^$s7Lw8V1+~Xh}V?q>0xiit43@@ ziEPuOR~LB7#Q*5s@4?Yuv>LWpAS16j)o`i)F)kt8Mi{HX-vQ*gA7n?<7aMp*BX*rR zQ8^%0JI_h{)7?_K?du2bjKFzYN`P=9$jckFb?q1YDlRHYcaQI>*MG+ofZ!r#9}v}% zF+1QkpyoshAZSE$;O?r6?%9!^sm%V&O=vo?8M?h#_{jGh{>_x_L^OA?9ytc?y*~UN zm)Kez*~|Y@_v~<%X@OdmaV%ej*4l^Hr(%$?CgaZVufE^ zkpyQOG@Svdrxq(=D59DyAVI6@A8|Gk$Ybpsw0CpZ9HREkNL|rXr8NH zWXQ!AjUuc@25X-#eX?*KUUZqgji{&t}N?w5(E0AcR_%iGnmn=AtOHGnL3dmesdG78}+H^O3 zv7d0{mDwJgHlKcGn2DuKxv0ClSM*wmgT_!*RqVvC<^PtXw@*q^A)&CcT-RUyrQ>Te zGRGyR|Kw7s3w5{ynr~<7a9$IX>Sllv!>5p8`qJ5_lLl+CPvWQJx8N84-X1+tuYZ{T z`@v*399{MM>qs3%>94AT0{@vZ2a-33!$*DCYw17TkjfA&X~(E>qOEs8TG413KLiVk z_=qy0fp+ffhl?<#Hh$+LQhK8qG}XM3yd3}mLk?s;>;ti4%y%Ul1k$q7w`^e3c$3Mo zAO)|^Wr&;_$hd^SzV$cS$Um4fz~; zNUVNq^aBG$QsiBByH5aSZ-MXI?cdcFDSfpkO$p=yW9~5~Q*lV1Zx=6eCij zQgcPHK7?Z>5K#rH1iJNClDRYrPA@YkUxiSwm-fzn;ICBWEpI7Hk2o7od!}Xw1JnEb z`4837%{{$0ztvxSq?Y%PM&9#<GT-)M?QQm`u~(l!%Pm|p1^yO~VeHYMHqO4kAA zJ_#ZAu1PiTX8Qh0u~x-rKXHU+{VPztz^1GG?xME6C_`>;E*RJ%g*$byE3>WwJfNnq zkPjp@&`vw--FE^|3nhAi5dp;~HgQp6d^2Ja*Tz0}DRcbh8V~PH$E>8q*0+2mlVi)N zX4jPkTvv;Yer1K%kENzOfsaX6;)+#b;9$nAEHz_aoibgLI{)rf>fJm28^ibI38_>x zLz!c3^crqOuo3=#kOtS~VVr;LOZ*>Kl|77H`zK_FSVCMP81hc`*jTRLxDgNf9(5@@ zuvG%gJ2fjSHbhB1RRvto5X*IGH>Sw%Zd(UrL$A!@zur8)X{}9V6=A`WD(1h=6eC6& zj7K1NmL~0qf9cziU&~Cj*!C=RMJcDc`gi*eBvv^_UV8$ZFHyz#$NmUR%Cgr!8%lzt ziO{qwSZPPXuD|;?Fxko3?+mVJ>KGGnxbUJJL^BD3gP^ZN&k8Fl%6%C@$)r-GoZ z+6yAMNC6tj>w^6($lmJJb7co)IVk)}mALDjAT3`#A2D!=b$;@8$6qN$s_#}qW07o1 z9TltHI)0TjJ>*<9KE>yq#q4T{f>S)s5cRgcS&HZ)v9nSCvUoQRCoSV{9KA&>tr#CE zgpp4Q?Io`dC{Ma9XV8b)fYI-J#Z|~~H!H^|sHiw1-uCqLG&ZS1k3hM7Lp%kYd3X8` z>6h-2ZEtU5FcK0HU@KX-@-p_(qmYPGHDA_?Us+Uve=$To_vT-PtG%GzL`gvr1bRI- zYm;>Vq%S`2vqfWdz#LP=ot1#<23o5LFJDF@LsSUXTFDv^eINh;%c?8+MnDu$%x}V4 zDg-6b0zm#}<1VeW05y37Ca}B~WTYM^n-pK5h*?Mwhmq%5?bIOCl4k??SGBa-V0sZ- zP{5ma8QC?-6_=Eb!39yKW~`xfa=JYK^QXNa$+B9_a$y>1>eeKzap2di+JRml=&7MQ z4vJ==5CI298A=`K{vW5N7JEj49xx99HquXporO7=o2!C0A|yFdQ=}aSZ#E3-B|#0Y z&J$47+rd}P8K$&5>(lYD2>H`f8o8=NAOq5WI2m)HXB`^rbR+&4%$h*D_WxZ7%le8w z@b^E{6#cOGj`;jcYY38dh3lfDuOA9#4K_gB(a_XX1UqA}0ZkITt8mk8LJA%rF!mu? z?|~E-lB=TRRAZBsWyTM=+2TBWRRt%7jlc(nyGWbx4oLmNb1{O0rf3IDFH~M3QBV+s zRr=)-d6HM103po3mZ4^A`)X3x%*2Ec_!e9|JRcODfv`6@H3cXK0MOL7Ri^Min|tH5 z1K-Bp-X4RgZD`;W71jUNR{QHkC3v!aa=gEz=jt$S;0KxkppXp2lk%eKWZ~LXXq|ELCMI5nvP0BoN_Q(hRhp!EwV0S7aY zgcMR^LK+;9)RF`v2r#Hk-nRr{!lu7J7^QOiK70rU#T9osXBeQK-GEPw|N4K5tAXDC zU0mUp!6`;$L{OnbRSu|OBfD;BIDjFgTmMlpq}6%1x33SzC80gH+CZNeiB9ud)KjCL zYssH#Xdov+ls|2~5$?G*NkcfSeB! zz9==oFx1wf3bZ27hI>QmnYNi~yED|(RzSXmlOgG|!6qXkgP6c{B={hFn`%~eS~mkt z&t^d*4HTip2WD=g{GYI@`QO)t?NGZ#GsYD768x;91BxsO*4t78@@w z0g!5vYGl*Jof%*b`FR0sD|Kl>jL5vsqw_Ye-`b=UFsyJelarGaG&DcnIC+CaC2$_} z_p}Nw!pClwmbB5>UOw!uA3>yFg>pO4h7toiV&`TS*Tp*5NP>1SKVOuK)ys zGcpN$B0AvGoO}mvO)4}$LNj%U8STJcg!00^1)VC}{?w?zqpgfRn64LlN~xU43N1x| zJ9s!yA3oR(v4E>2IIDO5eG7R4xPe;9K)O^(`(!w}0@8cz(Hue5HKHuAZ!qLo)n=qL z)jDR7^5R7lcv9s6Pv4^IkSS!M32l&pk|zjBeyw%qg!)zRI41AaD~@yLq5{o8nSu%z z3pnR&=pulqG}qa)=Pjsoo9)C?&>jT#+aZ+bNPuivOq8%9Df;^ zAUp%iIJ2-2hJFH6Wgts1`>gcjLtm!A1y5`O$bP`tM#4(MP+mfn26ccHXnUDcgGwY) zWrx$!3PSo7u!Idl+$J!x+pj{RtY{S41ZoFyd9Mc$RduKv>K4#g>S0H@7!bak9 z5D$5cE>;a?3t(8ZZ_Kt=KyQvhhk0#+JoF4X04Bg4L_r)Vziy28vbFa?Ei(ad3!pv` z0FA`3o+;Z9cV4n_d?B6rR;T1w!M+8b(c=%ot4-`Z~s4Mb%QO-7dTb1VyCPk@% z9#!xw7(CR>FomX?RZ6#y1AGfH!vcDjd;0V(5HYTy_VmRSlpaALc@`{+g-TIt1A#FK zqA@-j(0BfBE#|y^OAVVV1f-+}sI=;ItU?rd0wN+M2%E<{*>bVa?CS~@fm}6=gg~b@ z3c5)IbOT7r&d%;3fl?k6EwzU<=;4C!89ert3(p(fX0c(^gu(bWvVemsfLb73r2XSG z26z=1*qN|45)i3n#t7bMIuRVO7oCF)4LEE2yZc+fgDMAZCQ!!CS#VI2vO%f%TP8l%)p>WZma*xipnvmIZ+tJ#wJ6 z-UP5;D;W&$MC~CELyb`{<5~>@%z(Q6Ux9dA41NbfOnA?�E!MSy`l9g+Lb&5sQq8 z(XYRvhY6W@xBz>2t!UiIRy;* zhZQWfZxIL(oN3q)Uti7AT;A5Ht}K$_Q+L^if%A%JNVVeb{19QHRg~=K+1> zkG2;9rBHA$%yzVb`~Hbd(mUN!Mt+3P4K6 zy0nu2$sTL3rW*YufLu@L>gtMInaLc1ygR$LR(ev);k@j#ZHI?o9{vWEFcucfn3ldi zQV6bqu6M^Wo`U-sRu;OSV%FezEmaZ=n)13LZ(!#}Mn~(_UsjtDj2Jshc zC3Gw-Vj=$4oxTTA96jX2PjJ;M><2mit=P%8L)}~kG1h;C^=RYNJD{RV`tOUvJo7dD z<|@k61vntAw|P?9qe>JmDX`O!S~-M7PHyh7#V?RPwiBxBZHbAA*$J@!C-w$jyPj;( z9KZ~Z7F9V&{1>=ie|ckuhV%h{4YH^j;=!*8i3hM4w$&0IKYj?jcxr&io-}Nd;^P3N z@hc%v>8qh=K=cwH*knPBYAD)uGvJAZz~Mn37pdIlq0fpuMhZxc$}ClZ!^1T6o1Jl%Nm;83_oWPYZnA2^({l8-}q#WUtJ`CpGy?deI;c!L8#l@eU z9v_;AjtpfkXho37IDFT>dPg`@1M|WKU+5ASusI;NoXFzTdi6^fi7!w z8O6N)0$^@aIgJ#fWP&%Wo6SAb@ghX#3}(2 z+W&z!0aX*NYyhnu!Rh~v!uu3(zmUi@d`L-;?*y>@06ZEET?jvD_XimN{zwi2I6y-; zAv4>5Dkv*c*Vc}kyo#JHVABoJ)Bz@V5;6|A)LrZ%CFP(q^bxQJ-9Tb1WL_Ke@+HIn zk(+@zys^2dyQgJejuhEJ(;uDGn3$OVRK_SjC{ry_lDNEx#^`Z{M2mF3a5g|BBCpuYU^X-t5J32dImPU#VA2|ow>k8lvLs~`x;80*gc8GuzfSkO6Hl25wivurBK9B`| zTOGc}5fo%_{~mL|cD%#C!}Y*!C{8Kq=~1jmL$Lxs21FiV;Db!tfmJQ(x5Gc=C|m~=gIUZVE(xoIG`y%HvVC8|WwHh0(n5JPMBc%{!RPXUa;Rs3 zIOQF99m!x>=$e>BLBD`D#(=aN3MBwi9EY!jY*(N%G^|$vdKd~cd6$z%{Rt>%4nu@a zSeienjfMS={@n+eek{x%U)i?yc8l;zpbi5oJ{ii)p@9BUQ@aB9pP$%)IZ#(54n5zK zv)2skuP}Uv`*zR4-X4^%d1BOZ-YxiIOP*IhZA(-=czyHzWk;2U-vybF8eagvaqeZ8ZBywH9{@!khH}GqQ(^CUb&5Izq-M z*n*e62^SQ-8zkop`yr@!M58bi+G^d{0VYTie4+t?)Hj%oK+^Lk1*B^D3zl)Bp`C<` z-ex5X!-^<%JW5h**cTtzM2kl-QK1uaeEPo#d+Vqwziw@K)1jc0l8S^NpaKePx=UmO zA|NR$NOwsJh!WC>bW2M&NLeVI(h@2qr4j-n?_56ToOgUz-|2-fbt7c9#rZ=+q5D8 zGZ2^r;tAW1`Ge7v9+XCn;qd-#llA_xN|Uw2;V2cffaMd;JlG585$w%>MbR)jd>g31 zjof?SRXznh4+h@nC*|e*3C2~>muzlsYW}_!;)PRGBm&kpdvFc9n;aeak-!$#*?r_j zE4(vahW7TQQ=#4q-3&;c4Yhs%ynujE)qB$oV6*|G0oE|`@PCa&rD*3y0p$5Uh>Ql+ zNzm=dqTiPYTD==6d#|221|rKOempSBvBbolPq|Men`>d>6tZt-Er=Ek@5{)c1P zJE;KauoQLU=Bqw0+6F}SW7=BeC zz0Q95k^{)rFa<=}hHY)R{(-jo9jND^oi3P^1b1oJA|(H|1Tis4{hBqH?Fb+dM zntc5{6sK&^*B(2?Cj(#`M3A-FwOYx*kMUImOGT6p1-KB(ErG!j>~gD=Ut_H}8lR^z`;3hBjbk z=w1Y<<@)s?T)uWAoEO=Y6}R}nwb;$`GcvhnrX<0%O;59c-~6S%l!&mfK&2eGP(t=2 z|M$sgleLu$^k=?WuzBF2lEYI+m1-cXDJ%>>{c-r;zXn8sZG~0#BswIGU_oIh^aUTw zcoN=p6!wFXFW~M5nr^oJJ2;&ip$@RYdTnuok}f7GY5Awm1Q>$Aec<#uA|z!0@qa;C zE~L|+p1+6Rmi#u6*3AEVP}tfEh|4xNaozAJkfiSc1q5L()mAhx?}&+x_J?{86>uo6 z06Kpyaa0rn<(mrzJjKrwT{|L z4YC*DD1LbN{|BW-S2gS%_^l91>&gV!kvxq3kj*<17@&&63UQS{a_A2VOr$(TUt0rw zQ!9l~whd6eul5to-n;YA=KxxwASV|%r7jM#VRyxoR9YE>x}zwThENvM?>@Q;Cia<7 z^|erE|NS^#Xbv+3xQF46Ap#~Xg4+;YoSxqMgPnp0Fe1O71{*!AZgZ;~Iq-Z%~qNLIOxm zi4}ePwa2K<-1ywwtVgeP8ahJ2F5!AN1(yL7%>YsBr!JfPYZzcFi>2X!skh_}%_eMy zAm|$azW!IJh8D;}7*;4;w)1eH7=2YDfSkW<*;0_y%=r9@U>-gr=|v0UhyQ86xyD06 zRH*)61Bu{ZxYe)n3#}DRLk|eK4JmFTdAYeix-VpJu)ueOCt~wU3Wmhs6+;Dx{Jm^MG9za@ zzyeEP|4Tk;zc|3EZD7C?Tn%so7W#8QvwWoN0B1y&UkZwfz*~a_poRv42kSqcS1#lWGs&12452!{)MleXk3#t(4!l2R> zZBTx362KO?XCS)iU&4X*st!IUhop_FZqC*QV$ z%MY3hZXO;vxcEJWv+;lhHh{Sc{`C7>R`B^dS!y8B0h$6?$lGEb25rWh>1pF-XW)=x zDhx^>lfY?Q2wms@(w|_qLB+_(<8Wtct9u;!OrW1bF&5&#U|d5&$?Ok^Jd6^Wz{G3` zCf4*K_NiTypzeVfGtx)x{ard#+okYfUYiNFTV6#rIv_Ak1Q9H}*M3_$XV3BRT}Pkc zF;K#h6CyIm2RDq%P%m1KAa^GT&_qJMnH>D4Xmzl#I)}IZmvP1?0NlF(DXB-4-#g|| zBXqod%k4v_05a3k2{@>8V5kk!HDtjb6B`={B@CpPavPr?@aKoi=Ig@3{HJAlz#|~a z;my#Hc2;MIR|eGR5M&23@d^kJMBNv_FF+swzaMGn3ZN%~;Q-VI&-wHN!9!^lym55k z5IO~0?9m17ynp$LCVqS7|7v1r=k{X^`|^7}ehlCa1Bn(ClW>29pOrR2bxpxp5Gp}b zkvl{8!nbc(ka~g19Q{sp=FGa_vxtZYK&$J}>s(G2=nqgLn}ozGwZ1q=s`yVwf%1N# zKZf`Ke(1B^+iAA_AY#iPwRV!wi~iWuNjVJsR~3jhm44K<)fXaWgG==}UV>iFTF z14zVUd5=>y@LKLlo^>d3WXBorJb14KLDmM)1?&T6phKfGEjGjp%C~GO zK7gnwt*$@;myvM-Pzgvm{V2NzJQRM|`Dg~2?FUl>bOk^e0XYLftfZKU_2mCsP!Q(_ z2I5bF<{fE9A&KV=rDQEoz~J;KaUaRc%Y)>M>R=u&wtUEGfa9ZPseZcFjtNfKmzp{X zzEA(Bk<8=65hTg9=HQ2k9p?d4v)t!&Q$cQ2<7wq8!Fqr10Lh!K!Q`x2E4Pl`Dl+ZH8(k zMh+E+09Hcx2(=7=Z~zLwh70MNT~xk$3URYZ8G`tRga5mm{9h(567o?68K}mm(U1rL z$0*tDqbiSuA6oIFM@LiQHs_O8kDUuLmT_0mBs|7LS`hN{;`|M|;=eEN))*8T*3|rV z(`zaDR-Elt0)OUK)7d=sALxy*{ORvirS;wfsNeJHq5OBGwM6k#mZex@z?Ffx6@Ec6QIRXhXOI!A>p~q18 zat{ur%Sa80wjSuy;X*_PaZo~^TD$Lrb&_>*5Ujr6nfd793w8*M5XyL7bMq#=|$EJb=-n#6=X_21ScflPELp z?OcE%Wj+Dad7v#_vG02Q5|DTJ)0E5bIu!hr!EYS=CZJOI6-f~MX3kNJMaWQBci~Ld zkiO~{K(&Hz%0<4JdwT|02PjWMQ%C2U$k_#C#&8cRymhS_6axd(sI%boBvthMO{f#> zK#->{wv>rDeC}4pIAe`7q0m6#WypZ+4)QvIu`8I|M8dS-3#i`Zt*v>WBp;}AxSjFy zYc@BsE&IKc6ZJbaojDS{NCOl{!9$N4zCAZAht#+~;1Brfm1Ms1Yl1pv zoH*ELA>}l(^s0xyu?eC!_hszoUqfgj2X|N?cNlnP6o{*cgA**6x7DRc>Hq{aQw$NA+T_7h3 z+a-^x0TEc5th)?w4pNMR4KWx{p_DOHta@#)(B(dN!KRuf3E7-NvvQc}0{=6RYttFK zr~)w*s5}GtGCrJz(EYRnnF#I#gdXfkstGYtfZ7BRWR09Za%x!%1=AQJco7-qBJ>0D zr!GwN%x%f&zPuFxkM!P1kq!!z&6#GVv zgvYT%gBL&BCLTvbT56}*?qRHfEE|!17?2F`Rb%_hZc9Ilk56-xR*i*#l6lHOP`Oe8 zO#y+R0KH5FOn{NWvp$9o%UZXZ_uo+_u~y&(vSNg1q+Hs}Sq74Jh~zGkYLbX9@kbL| zE6BuXYi*9`D$0visJXaY`4>h4Tz;4zcq{bTRgFW7OXWDc3Pskyr%%MFLsAh1=P=iX|k7jc4YJ#$S z>5{Jx7`{QNs<;n6J@&TLE|ua&6JH(O=547P#2sH&EqHC4Q0kHN({XHn;?2EB`k?wa zX>Vx82W}Q!qUP^s-!&|(nGF>a%51t?Zh!6?uy1I4&iheFj7~g3iS|KoJ&l2Z0ZO0x z0-;KnDb;r(5?^8F+ zyS{$%DJJ}Y_Z-h(o{d|8@SA=#_XBZSHy*sewyOpgD>1>`_+l}fJKSA2*^VW0AFPaA z<4;^J`DFfm#podD5sJnJm%0-is)29jmRt=1GC;4}!^7=4E7*G^{F9$@BDxpM+m980 zRTZmf*y_DRK&d()_tT(n^>)6RcEINM?BQW!bZ%=CzCO zjuKzoH+c3!DOlDFx9jrfw-Xu^LeI;0#_#tWIy&W}&Ea6`mN7Ty1cw8PN9`xq&O2eX z9_5?WJ;GFDF;5?vI-TsM%zU>jSdd!ET0*nFd&3{cd_^!(Ubz_iKml*rK+j*BQ|96W zrpu+halFO4%N(BKDX*&T6Qo@}iDO`ibS(EOaU`)dDsvBIeIsuA#-xP0!oRxfK{fUx zO|&~vZW`XIX)`&0K~l^&PxFnq5q~XSRz(7OA-S7kK5+cKMxOS7r^`P#KYP#QBq5@L z!Y|wgHx@eaZQ&$`VQ*m1eFztoLf*3wyBCEh{D3N)P8d&09g}mC(C0kbrA(T3p-gJ7 zQ#%vf{AMJ^<$>F3uhIb_#qLq59_Jfj{fqUkAHKBdZhd@swP^9TSd3^V-jSAOK((5c zGXIhS>ljwAoW)=RS1$4y*R<1awV_2rsnWr?u{kNC(rcn#yCdsL-f*RqN|I89 zGcl7&pF}T*ki)1~DB?iUaN|%)E3ge(XhcpzY?P})LJe_Fkai0QE*KA<9Q*;m7Y-5< z`T4!Kmb9*lh!9|)^#uIt3*~$G`t+gSQhye(UzT_JIzy$ID?7AC7tHSoTCfax7sq0j z{3y%a(sVdAsg+$XaW#GF`cbM~G5bQ6{WtbY^Dcpe@P%3ZjVocrhnBioHtgn;Ib$hl z?f64ynztDa7jnBO$9Yd)^sJs_DR3{TyOyr-LfE3oTyT%jS4@spVxq{yst{+^Sj2%{ zxrrZpQzn*C_i^9y0`jPt$6bx=Gu+CyWaRMBQ!6m8|vyB0>{s%c*LG)P^R~I?)cf{#I}j7 zab83^CVZYowWfs|t|p*p{d(a154C)O?f+TvsQX z@vCr|>OYtCi>vN=<9={j8~cjZv1FZ!Uif*rR^#VLVPZ+1WpZrhLW#Dmc-EU17Yn)< zVpWe`QVX;PD(lgvbbE7@jR;+OEv`Sc{;iLH{9~Ht8|q&1PfR6C6*;si*EY7L6bW7w z5OLV}KjYq`r+Ez1+j$7-zKEK*N&6-W=r;!Jsq;xTp=O+i@p8wf5<}1a=R;qXo!IRS znY+39$H~-%?;8nCju($_uh=m!>Bv+nIePFMw{FY)5q^G~Qh|qZGd(`vL%eOp8pbLYk<@=exJ0c<3^ySCXbc+>1X5zFu zCIDv+49`$%wp&yl#mHXYvgnw3pM$Yecb(WIiJ9+FUE^mGIR>&9PNMQt0b&V{>T_h$ z1g%3#?%{ZAK6K^1V^3!#aJeC76nU*xrp4xKi2VIDvtZuxvYY%m_@B42^0)^C`OMZJHol(9laj^6q{znv?s-vIFg>;Tjc^)sne z&=EPGEw0k4g8KT=H9CURfizmH)TZwI5p`J7i?}G3uaw<9vIe1l@Q(+!rK(>eqG=xW zcCe`P$fb#5H*$;$oDVv|S#JBCHSr90;tLM338Pwv%r@6py~oM&hJPQKKYbXw@T4(% zG66_}FnO1<&Y;m&A*`;a&We{&D*l>svd1;1*`X{V8?(#J>u_7e~3ZEyf;3xQo}iB^{mk@PGs3Q1mR72bqNBEZ!=>#uh4u8x!SxXV?&G5;khA)N7UZYJ2{fV?@jW{c;@KPPr9 zmt)k~M{B=4UExfhOHR-7!RHl11J0f42WsI;W>W9WD1NQw6^z>y5vvT5s|*SF&Yiz$ z3KRqcHbOk&;%{VCwYK0$oeDjz(Sy0i|Age=VWNy$gJISBwvy|7{FA1fiK~2uH$Ckt zy_rX{F)zF#wpN$oJ;+~cJbe`L8EwROy@GT-lsglvro>73$G!@(^THOJrt9w+6kx~F zqr!epuXUfU`~EL|wSMptIsqieH{krT_orGiQI|{Ys-@clP7aj-mpZiN@onLo;PzwJjCwod#B!}sa@ z>dhs50Z0C*bHqyb7{6tsgS{!tyrCdIfs6xzj3LhVDDOt$KdmU7pfG4qgv7zfv(k|; zd#*+x^aw%cwb}XZU+K;xuD+ULDwJYsBk<<4 zbwJ6;;M|Ya>6X(pm+2{T&j0SDW5(&Rmdhx{85iF8HmDFhnBX$rz2=-BJN$Wn$$|at zT{(I#3BqfRc4bf36*e&e^l4#4j@rXAVV`u~bWfZoQc= zN?(eT`MUi|P+a1X3hj|&^84)~qCr>u8#VZX)wcQ?3y7VXt@spa0f9FURYP1RwB!gt z`wy#po(!(8d8{KZRlg@-3)5}f#O;6)e4#0je41vb-F0_9=yJArNf_# zzOTh2E=|*68>=3_Az@hd2XEYKrl!GIEGBXfU3Qn@p+ zS|!wpRjN*6o~>d@Us`xAjO8oaUw|6C*)63Z@GE%dXsjWnis$ zfW*DX>FGtP`|+MOcdPNcTK;h#WsL&GqZym93B3*Nt5YpsT`!0AdQF}eqEN>UjRlEm zUrD~+Q{Z4Nms7~#xfr2@J35E)Igshx&{;lq;m8Hca*oRTK5xJ+2jgn&Y}|1Q!d*U% z5ppR`anV%GJBKwGU!gK7!>Z|4ujD#ul|9Kk8zQr%2hK7YbD-Jy-Sxffjp=pe6v7WH z93L22URILoXOO25T5f;Tw5d@UEQ*P-R;W~xF}cq(=*nYu{yTsD!*lx!_cygF$ewuI zZZrF38TJupS?zhvpqNnjUCLzZ($9;FOZph;0Vgaoy~G24l;8;@000P53BMsi(R1X(<}3cI9Kt^Zwfn?_B}4Cv zXMH9fuAy47<4ZKO*bW~aAs5{7`%5h4y-hau((c^ZBa~7E2BYIWB@00`Nr`jQwj{|$ zWj)tI*+-YwYu(xLXqB}qyBHiCi6WjI#m5A;N3Je7Vq3nv-Uc#p?JmMO2HSq}ilexjO?}y+CQ^1M0}@KV;aLz&8BK8r>ZUOIW3nAf=`bRT6%t zL2;S*ygQVQS1 zoLvepzs)wGb;=qanSsCZ*?5dnvR?FaE?#G9ij=Qp3&P{$t_It>r=qQXGFGI##H*Y# z;AYi6@pXmh#d3YmNnWfOe`}UT^mCnA8lr{EHv_Gb#8}n(Tq6<$7E*b?etTL}N3}9B zwo%@zL!n7Kc14IwRVMwr$e6fj%NjS3&H;;?huGB)7`p?^g2M-n8^70o!11O@i-TA$^(uT+^{#8Vl-G#}^Foa|y{mDX1f+`u|F;<4Q~Vkxw3Yp=Y< zd{I0ij!wt2KrG_=AA{ch)}=wuwZ)Dbezv258$n0uA4?DgxpRF)0r0Jl=AYv;v}?Tk0C zSJ+B^Pr0zGpDsI_%YF~j^fs{S^AL$nO?l@je}|7_wvxp+;!DkCJ^vm$VUH)>(iAbB z8PfTo{;lZu!ho#fZJnTUEa|t4LC(jRmb6AXl_ZJ1gtrAZU)bVY%duk{RgLjh!9TAP zCuTHhRE9`h=pIeWV7?tnh|EC|?FS|ZmLiYiWTt@Si2S{gO*c6F!qxO9^a9(NdOH{V zjvhhWRT`Y(ttUC$<*arYW_XV;;FHHH($~**g|aHNG4LL!KR1NmL6DD9CYpu6I$hS; zkmbGxLzD?|`W+@pgH)N41ooDJ1!;rMf*&jw<4a$S{=A{fOc@N|pc9OF(M$tbv)8Uo zI+fSc$8yM)=*piDVrCh4$5SE!uIf=kLw+Nxko0WzVuitO?Dy z+F8Pv?M}uF5-hYFKTRlXY><@XIKh@v8EYdcr> zreDX-S7&#fPG`$()l!fRCvkrG=ZCTpm=GdX3XH!`qWaMvxc(SK42CF-M?h8kS3h=B z#kASE@n%&gX-@Fv6g?)gK6pXOeVs}xu{-=?`f^vO5ThMm&adjnZuH4(gpU~M6M61x z7Wv~9vUvmsg{c3;9$FjYq&FxXVw2-DI~^keyBs4jd-|OsW*xD{Z|+y2^vHG7b!h!j z0{p$NO9JcEdK9{HIcf1@B~_J!v6vK+8)PRJ>IHwh#1f_(edOT%wNSU+*9DZZCJITOM{NZh$Z=s{8 z7q8*1hI{@xv`gluA9+PpZ6ljqSz13Z<2Wj?vy}6nYAdwdw{?ZZM0C1b%jQijF5mkHrvLNG)qMz{!;7fXS40k5m*lrDenUOqeQCq-yXpVJ547+ukx;Z{KXr+sT}8;sR^Vn>C%- zp#=unV!Ao^HVf|v;#tl-EHjSJG+sgn^KA5r3A+@4f+8R3q8&wJZ(OYyt%%fFDG7=@ z1$CQRbS0J)e{AaB9~F^(^{Xo?$isRHCU9nH;ZS%ZgY_{SwekHL4-4b@>_e8zLvvN6Q({g{dY z3Ub?o+|_KDuTH4Xy%m5YYtZ;8!_*du17QGTDH8f7RJBpa(K|1~v0UqYyV7&Jv=oln zKgX#EwDp(yD7m!CRolp_!gJJva?Ug0@b{UB!atmJGHD$9!mNd3D6nGpAgL*ecYB4= zwXXIM9P+o7t&MT zAlsK`N%0!jhbnD`I&{)_)cW#m<{al4;v%d}6`v}T=-{gn>IFXABgT^poLTB*jiQbV zXFne}F8g7aj6SxPCwY6hy$_#KIe@gl{+{d<`*{YP62fM3>}B=0<;U|*4>W2Z<{6q8 zgRF#J&`iaZu|3oq(X3HO#cMFE3;|7o0_q97oqGce^N%xw;ZqY%$&TrqI$k7wZJi^~e2BcudbP-Mw2Hl1iw4%dxX<`IMag6($PDya-krUbmOe z-hNNxW1DGH3vqr`N@}TRz<&UlgT{py5R9LDgN(` zr!pC4r!tolUUz!`9H?f-^}Tq9msI zyinyy?lJo0^m-{8%KRqFN*chXKP2uRtw|H^Knnq@s-TN=+i!SHalV^+W#H{BAL$!*G0ZBlC+5aiK7dGIFVHI?s{m zQ0bq=!1m-tsLFss)8j?T3+)DR;cw0hd)&KBaLiy!q_T)0RB90Bd9K&f;_92iV~*9!+yR#rp-I|;7WS|9lw~`+r8zNVHo%^ELD#*2UW)O`g|gr znjIR@z9*Vj)=U#7sY6WzX@gvrjeDSMBT(i9cn-8 z=q##$W0i_V(K+)jtB%+;^z)pQiKjI&#T2vM(V|!F6#->gB7!9iDQ54L{;&h3~60fu`UT}b`zu&5{&3}QRf78o{X5rgRhQQJWD71 zV0A&*SE;r9DL-CarMg$8Nc+BBhAhe7cU#a;g8hvd`<4iKJ!{II+=D>!;341C%9A_8 z6)*Ig;fuqSIq8Wi~!KYS3RW*Q> z)bHUx$}b6;Yq_sad4BQ*A}$zGfYR*|l5v8_aK~m62yKTuO&|rC{tmOd^{RC+Kwhnm z2xOHh8@;!+G=NkajrYXnk-P-h+KM-B#2zri5TCT(u3$9zOIO=XJP}IWF9~mkKYTiN z%gN}qMK12@Sfic6vVF$|f?!5-AHS*4)>RMFZB;VeQ2vGla*y<~_hrh~{P`K=IfCyJ zk4-q+VMXKyh##jxA_b6#==n`Cz>`DTFN8q0fiB8C3-#LWAobr61%-Cb5l#pJM%#7LS(b8m62oCH50xRpsCB5 zt`1UWul)JY<)C=8jhkYD;%0jRRe7n=>q-Jj9~T3;d&egSF-+#}a8rHB!Tni_rs+sY zQu=(wC_?;6p_5ZO{Yd7;(GC~(TfVC+LLoxbT3_y^nF%qmI{osr=3^{uAO6g9b&T}v zS-1H#dE9DA+_`rJ$Il3Se6Scz^Sz7n_;tF?BlvJ%Oog7jfDO>)wmwCww8(c#t*sW6 zU2Ca*Gik11V*rh`)5at$B7e{>TS`zr7w@?b_N27X(T&=hiz;)7CuZw=Vi3K&Z;8dx_!9~b%;AY5%A?pR%AG^n#T z&OgAW;fhL2^MH6T2w`4I7)w~{;laWAs@raELhuc!F#C`@wLbb>$mUbO=VIDo-R(@_ z30q+RWwOCJnFeF<>VebJ>F%c&4Qr!WNvlEr2y7r%fT~vjuv?pHm7d)(ZupcMDQfq8 z*|_ZB1J%2O0?8UXL0{iaRkhvm<#%l2zV6+!(j#ia3*qivfx$NNqhvZv9IDyMXFP*o zG=C9@6F>x2&@GNHDlT3Ihy7f@0%;OwVwovBL~A0xoa=WuXENIt7g?dEz!^d9>-k!> zY_(>n%X@9>8yQ!cAWSZk&*G9S7a2mIvpDuYRjioAvHiV{J?$0PY$=>#wK?1F3QCcK z5^>-o0?%{+L{pYP>VU@}2mW|lFwxgiQc|Kd_^xJQr(tHmq9AU~;Z-#zdwI2Ds5MHw zFi&V_E5BYg`x}WqlOD6jVCce_4f|+EDNT`-`!?fS>K_F^La*sOy>6o+ww%i*-rO=H z3*W){eaPFJH6OO-?vO~f29F0v)Gi5!e>Z{;zZen%Zlfx>H`0bY->7mQF7>XygsWZ? z6yDh6v5VDWAuYTXj6ZZM9z_a0UX+pmaT{LdM(dFjU&kWH8K5FPOG{G+HnK%^%Imqe zbQTm-e>K?$o+`TUZzVord^sT00_1U7%o0#7DC_?MhyBi*GxY5_sf8Gy&8Bt(Gw3=hA&Vn#=t@WQJTb7 zgCAYHg#N${>1(vpD-+6hF-x-4C{ZX|s~Ym=j4bf5#3h^WZ_$4@ZPr=MJZsHSIhHf= z;!=CfIp+x(g)KlcPGSsNd_3E>arto|#qJ@fo4)>v*naO9$Ag!+>};`6DM!(k&zGGv zRqxrF?J-+NFGUbgdYPA{eM%57ywKTK);rrrXn#390svP=tRpKZ873X3zeGu&akIDy zLJ9SB3DMcc-igmN(VPs1Bl)UE1fS5X*abe7%b zN=BDZ2+_RG7aEo-OqR;jEwbHpR)YsZtw*f7;ato2J(G z_K^sMsLy_L<0Ikh{prw-oh%pD@{z?j;jh}HDxyjknsLW&avN@lmToB^SQ^W`H%N`SCOvIHY%RTVovK0YL^ z0QL>^<);T*KBq$F2qro{-tCj!8>bRce^$(wO2sLGn-pxbIqbMptEWC`ImAqN-Z_yS zVON5*iT$KBBaTFjBAz-ca@eqaPIY-=BmcEJ3pgB?Uv1(;3{Dg%bH!(cdE&`|U2!vE z@{KCrZ&*WD9#h-rA(KxEoW7qF0{B`tJ$iGFii^h}TbrhAgv`fD?scai+2ac@zfRK; z@w~9US8UWG@+YZn?OhenYqS9029eKxi8xUHF{W@6#@Op>x_;V8_s8g7^PJNZTG-N? zdy%w>3nkz@FUqqPL-xDn+G}OywEiN0@h3%2>e6(TcU>bLN~2V8QSO{=<=H6z2gp|8WAQ>mTbLBtmDLyeJa|m3@ZZoo?WL+r15cqcURee&A1}ww> zYkk|+-jkCZte6{(W~kerIrjD2H#`iC6i+)I0=G^}Pw(`gz(3YXPa=6>?D*=;F7lD<50clGkcU_Q+@Dq!W`U4*!C9{xQo^r4EoylUZg9ljKVn-U( zk?&!lr>@?Ln0hhxN##EagPjx#5e|iOQ=v$=E%h%CAN@l25)-{qw@<}80^h@0AS>?2H_b+;ekWdVT*Sa_>*ST@9%SiWJV0Z;d z62M3{s!joZ91C7aF}pe{5x*4q@f=r;Vj)F+|A00qo#ls*$6D(B}z%H3;xJ*#LW`Rj0Xg%TI1@$#f zOc)@|$P(O%z!?DRZhlBf18LG|a}NaGfXW!<-C$&Z3lB>UIhIp%qD{^vX*e#a!!2!; z_R{RNEeHQqDT47a5~@iZ;F1K10$J;i{C+&WjltxhLUBqwt^!_phVx6jnNYeSjQ_^mZ_2g8KnQK|`)= zNM)rU;RIM<$jR9ggZi zlo#DgLRj{(a~mFFJG{Wti#KC4#jL$EYdON2eT0YE_?x51M|bqH3UKfDe}2HGa^g$z zx@G4@Y(D)pT+h$t4jk3?Z2{+fdOjB8N2co*tggOfiVvIiy~*;{V1-{cNp=ch{DERT z(JUb@KG`h6ymN=U@A<9!(3h^s>zu^%@wq8yC=&Vddk955HLgCe)>r#(m(o|U)8b;M zJ3Zwq)B;DEHAPd>a)AvP2oHH;`tj_4|eInwjeP{TTvE1D%ENTg?laD5st7)G6v)LKdApJ-Lu; z`WR_xHPzJA+I;bQEMUm00BI<#7equ7fEos8;QGsh>im+Dp6N( zhe_@#)ie#NLdB~f!XLD**#fJp{Z(y!eN`Y5fc#p*pz1zFQqO%c$61VenpiwYRl!iU z$Kn8V9n=_@AAhgDNSMyC9pAp*slNr>^#q33o)#uTcGYC`I8Fr zz+CvbG4JkXLGc5OOKSB*{&NL=XH-{81e)Cr(3IFZ_Ts zUl@pbG?;w=MEe>`M2wrG7JE{Z0hnfc`c4i`k#l&N0M8DA2%)f`AOwsVn&I{)^hZ&* zt-stmoL(2odQ7{WMztwWYSl_gN}vu?htEWcmkAPs-?mJhQxaKAP6c*Sa4qKM=WByM zh%e~>)@Me6mU@AUE7(;mZRSUl^FtoHWHC1$yRq^BVDBwKxHxP4HAP4ZS>MP7DQ7j< ztU(o$2h<7!@NB}%gn487w%9wSZQUf3nT^b-C@gpCwM!or9L~D-lLWJT4T-qmF8@TD zM&fO9v&!2AQiB~5-~Z+UsNryV!1r$uvH)+Ct1xMSb*%>L!b>&Mw8l$IF7DN@YHOck z`eAf^=I5T=$k*P5`n7_HQ2Way@~SxseH#_pPV&DW+sHqTGnux@pP*0cs=ZP#ENQvSxc9-mRb`uYYNz#nWX)E+B{X7x}=V8H${;^o$kQw*l*Fnd`D74z4-cN z+HtGfiHD~b@kd2Z%zYBgZgZJ(-+t9T#+kKZf{N_Yb_fs#=0U`zrd2@*xIUKDvw+*a z^1Pt@!`ACF;w-D@nU=w)rOJpRIj7-QndAf90rq)H=%}q@asBK%)I=f(ilrB zCdq0HO19ty>W6jxXnD0U0w~pdt(j+I7SF96a{X)122gC!qxZoi$&tI6K$}gxdSF; zM)R&TdYvuPuX=BB0A^|@F+ih_>-&jEK->>LE{DC7EFEO|#OS3$8LX}DCm003rV`Y_ zPUW^smwqUPmkD{>Qx=mTeT!~4C8e+DBtQInbD|nRVgC;8mIOdIh8?CMZ;4tE#I>$@ zI(etxtny9XzC56&=q@;Zcl6Y8;=k8T|Lr~I+n9oaf)5sZ@Q)X;A+-dWfcwoIWo`cxl=IX`^s^!d;gH``DW;>NPgXj*_FrW!)wGQOoPTkuu<42t{f_riO98e$Prf#pAWv16X&4A`t(A`6s( zi!IV!8*2XdmmQlLu4R97G7Y)_)Z~3=&XxdQ;lRAOQD_PJQ>n?I{b)+}4B*4y%P>Yf zS#@uk*@v4h9nh&|*hcJ_;bOhZ)|Qr}`##VDRs&jsFN2~P|Lmx$sj+L(9)?r1Wkb@v zKc*l0=jpBqrn8VnyL)8^{N#q`7AY1CNalgye;$KZrJDi4+W0ciDUcbv^aydN{-unD zyBJ>v+F`%%_7FM;+t6n-U}kY^{UkLNQbQB^Lm%PsNmw~qo`Skr(~RrF^~2(g&a|!d ztlte~@RTU#2A+T`oW}~^a!Bdt4j~~Ssmb0%fk&9%=GQcm1RsNiz)VHc7wp_{CNNAA zF#VtzR0jbASANwO>(j=2&9(XLl9ahUVP7DJ^MK_j@Ytm#e#h_X{JZ&sd5w*Y{vAuJ z-m0#;@uJHa%5UKvBF6LI~d*&9y{cbz{v@@hkW@~+VvZI0F+JXGQ<8{)h^kPc4 z7axturgjLuMd^zS_4~6gg|pvLW90Oz_;99fd z@7o+CA1IG0N$2#m6W?!j4W2=fdEt99LR@0Zl3vfil>o2~EDT5-=g+i$d|*p0TV~yQ z)m^K2r2fy(F7%gY2b9k~=1@fjhV0Jk0J&f=s7jAe`cl<vG_eVT?#uxGIT$shZr3D!3huqRIP_s1O)@FZ*%WjAX!djmG9+HT;ua) zuX>=D#tK=?TuPtq3mU69O$VSN!FonY$}tQU6wWGZQPr1%oLfq*ojqzewczOBw@z%H zq<$}Y#xTtv_ikZSov>a?33rxY;4fp4m$ZlC?ZAPV$fea?=Sv2(Jd1bFx_5Y-?RsJP zx;Q|WOyx#Lfd~iz-in(0Z&HZyh?&O1CaL!Fd+N- z;BW|ujE1NX273^E%qu9#k!1wfSOkp}>yh}Lf#-roAqqjDVQ1>&1K= z%xIuMhtb8Ur|%qmGb63B>wW*$7N!y@v{J$Pc{mw28$N@;_Vx_23cJfZKqDj>W>Zvl zh8zd$hcDdDJ^S^z=wkqL;Nsx(TYkOnBJmej4emb?xFaCXmDxjfb^MD4R|8t$N9X#5 zNVomg!+K7K|HaQbGHJ|K%;pA5x&u2K!6Y#W2W7(Iu8Pg+;A8p6hYc>gWK1l=V|-ar z{LpAIyUb-y%AtP0u^q}`T1QXs!*Iow62i2igFlg36UC`-7b`l>$b*;+A#5Il;DEa< z<`*z2TZnJKETiwT%5Ya92yVw&DAY*nO+NC$b2l2B{0U@G02o;6|L%Vmc=*>R!wn?i z6wrPI>zR1IYkpZ?-hX%m;juI~l+EC+goc+HIaPo!VQ;e!1RFYvrGe{i@r)G6m)Q1q z){f;@*%Us{GOco%Q+FJh(B-KVkZlGr4Bk~_o%!B{N@TX7v zwjL0ZNPq#3!I!EjXzc*@k%z(<^fBYPeGI%Xloa5;=wo$ouTnup5GDY$wJr)Y|G)-F z;F&$~@HYXP0V8$YtS}VZ?_t>=GuhYU0da=lwN3iHNJW4H@TP0G(y>lLTt&GAN+W| zZooiyF$l&!-uJ_MskNrBVef|Z*`ED-J;d01fT?&S3??4?d`Kf*Jh*KOM>R&QKO`J=vLUwP&zvTk{U=4ol&373} z&c5NPQpEDgqpV{G4ZQpKgk`O8l?4?kLR$>w%I0`2Bs>6VdZqj@jcV0}bz;W1e$2Qd zwkFu(Ngqz)vav#_>JuR)<6}mPcjXsfyL~QQ`8*CEd)?2|0>pc*cw7NnS3a>~q({22 zWpILkme5b92P>I^M5$^Cm)?PM7nsKNBi4=Tar_aDzj}p_V2TjZ;OPx{Mb|L}<>k?6 z?-dmkuojP81FPUna2QSkfFk0oboxu(;y%A=0X?{LZfa}GLs9wyT#8aL{U|Ba+Rko! zysV-k1}YFMSS`FLao>Gcd>JS&j~7OONyj;iYdg{D`bF)6!on=Leg=RhX$9&rGr^>S zmX>rhFB7Ccz6DsoK66fvCnNqqyiJKwLV}4`D70>cH8t^nH;(>B!3I^sSVC;5^oodJJ50`AL~qjXCQ6roaa1y7S?I5VKi0++56 zD=t!CqDANrw6@;;J@$_Q#Gxi*_wqZRZ}z-XglPM>3st}OpT(ulN$R|vn>Znwk688vP&wlTkd|HgkcZe}o- z0Dpw9mSxN^*BLiU_w6*@Y)Jqyu>nZfghWJ!ppIJxd3i4M$70Yo2ajGb*{e{> z2C&)6+wC_+bq!bA)`XO}PTl(%f=ALccPC9a?z#k_--}MqNESq$?9hLLi@*!8w~o^- z&V?u1SVxh2n6)J5(e1>vikdQzI05L&m?q{H2Ij3w)-}oCn?Gj7L^Ew7#Z-B{x-ooN z7rR)egSEcv_3GeyxLaZ${%FUCiEiU&;;gB@tQ9rx{mJ+lwE_dzqr+Vqj2E01A8mz) zK&rU}Aa*90o#7ViCG`&Yhc~3oU_bK>Jyo2mqnS)qcsTBmKVn`X+IMlZ;llwjevi|n z@gjv;LQs)+)>e+V%~L_;-_I^+qb7Fgru4mtvo;)Fg&%M=(`M|`?vr+CrsL67f&HNY zx~Xpq3xfdZF|Xx0V#yTS+U#<4@^TMW(SYb(Y!fb)1ND27KR>V|JU|OZx2h$&aRZhw zAdEB`Q7){ltbUAhiHat*#Xg;S2rvKImPEh~6=49>PnN?4TCR|#ItZ=+hdaF7+?(Sa zliZfJwp-%oF$RsUR&Bp7-YRd~_^q9H-Ki`?!c&ln3T7okVAgycjH5Url;lN4MO}d? zx=+t@+vkU3n~TFtOS55_8}MVMUHT+%-nyj%6+Z$dpu*c4yBF2aCkmaPLA7O!hB&zE zZMZ-2Ji4e~`PO%}u~BTl$H7mYfcQ8od}Dy6u0kz?x{0Yt+nJW>4SEf!Jr1gvnV+`= z_=^n8{tZsjBCqE!I_4;pt=FI#O}*=T55mzWAFLjUKyR7}2l9w-A5(->$~8I-E)y~0|vGbYLpLEcMl5Y<$af`ArK#zsOh_tBKUpEJQo4g@BsosDTX-Q4>u z-z-f~Lq=*@`rG$1oSd%Un>Ywl=-&N<2(DyXK{P^(Kq;H{D(0X|;V9dT00PMbUIwlXSuFJh}00xq+EdYoBsEE;hlW>#jfn(1L>m zJVyp#A6p`n1Xk7K0IXLA%EyAUBn9vJKMV;=EaVQpr3taY{`g`T5K&Gv(qGgRm_<0I=X2@X=C)^IZA0 zwkRQL_fMVt)`Uhw8jl0Neps%#-Zq-g`RC^4d$y3Y;#Hh^Y{+OeH68I6Vf+z{_PWSp zn#ELpn!hgB0y$`4y03hb9naJuE!^!JHF+$N(TK)lS9@)jyUeAnp^tU&KgFwY+ebTT zm4Mea4xINSZLWhq}| z_yWG;PvG8bn2h`ws)5KLkm6zr>tDZ={WKeCva>Wjsw>4C_aFtQAdbbcpAX(VHeCCuHz-f8Cn{J@1ZNrH&ct{kQ zGI}W=EPyka0}swq@$vG)OL_qz_zD$np|Uv<<;A-1HMRwB;`0mLetgVXp@5BVARA*e zqW3tU5WhwA;#|4v`)4LR;XRQ)h5!_FqyS0jUT)Am^`JY;Z1+zU#SGu+6ZQ%3ITe$^ zXR4DF=+O;!o79M&Q(1Zh#TwTN zY&pA^^W~mIGKGZpmicY-f_#2HH^BrS1Au57^q63Kqh-&~ks{2c)+Tv3_D9ucp6i|8 zKYNyGq=`KS>50AMd9J?*8~(eMFFgmQ2;XE4DY=fjPBgDM(3U$UGV*GuJUED^IsGjx zaaiqLnj16jbYUGeEFaeD-1S}>0nyu!EvIpd79sS>m*zEd!dWcLUOgNOeZ_&7Q>g%) zznu9$^N!dbviI(>qxJ!5qQMU4HRysiQDi%eTOOk}C^ImAqvZ|Kz7*5dW)A!yuaob@YJs(G@H ztDTO?IbFWOp=QDm&pB_g$3tJg!+8~TxX5)E&0a#e(lKrLjj2oQROPKE?{{^m3H5Gt zwAtfUAdS1Aq~u$`^`vOGgLUn8+F!`S74I*>T3J+!H-dnN|fgCpf;8hXPet{ybuwX(h2im3#8;cY*)I z*L%lv-M;VRFCwdCZ!)uqkP+EJ$$DjGudJ+ulAS%vCR;}KR!IB+oMWe8=4`^QbVmB<3;>Dgb|MfYn)b-wbj zii0c!A0`-gjCPPFIaDBHb)zLW0+mjZN{D_gb>!O8qH%+R%J$Xj0|l#07hg?n=yOLd zN!#MY#adr1qt@2^U&dLnNkWx7qB|G+-TFJy1jxZ&MD(bypPPH?N1s{Fc?Hij>uFb* z6#EAqEx9jVmw^h_2UxhO?S>d2DX{`o6Q8~L@EYjQI9#mg)3dU|ZW}X&Zb;2*ev^bA z0!m!{_jfFzf&4iDSL=tw8`;;S*xQ2 zz*Db0R641Vd2`2svQ90$sE*Yk=kfR_y62~;F7}V>aThek-uhDQMcyrnXY*S(ADk4S z0I6bRq_$O(jwKsi1MVxkn$Q+Q=26E-fq=94QI?!%Ktz`*2%yjis-cP9B{#`D>qnP% zRNG?D^Xc^z{b7&ESf5~k+8>eY^EC-bFQ9u{ogGg3903M>wno)zEW1x$O&8@t1qq6j z1l%U#rvjnyS2Nu{XY&p3YCpAzs9xx~#zh@qFp+$(idwsQs`P&1=jBYoHl(aRXwcoE z1}N(76!)$-xTnuCDsbS2@d`vt&GN9O#@E8B&LS0=cq}hS^3j-!)#yaiLsG5S919n< ztVS|Y@d3$qoZSnU+AZ9N#dY#RXCuLcgL}{U1~>F&8sVpP*%WhiFZwXVdyvdq6aavd zUQnw!qFFpR&g;zfbfu4xcHv(|qUFsxt{8I*O zbV*MPGZgT$9N8W>2RBz}v8oB@2JqdJqberU$$6jEJ+Dj?83k?*+Aq~X`iWbes9X%w zfO~N6+3)IVUA3q&M4A)8sbc{NoOWsRW@Tx3^X1*sjbGSU`g^`zx~3g*B9K}c3L1I z6I2C~0RwHNfcL@protr6jU6-mB!=2?Fvzf*1@Z6eT|jEEcBUJezKq zke|b!Fm;jZh))M>&a*^vu5%uHJOp2b6YkxTVqa|!cWUW{pc78Z{837ll|Ta(>#gRt21GKM3! z99jb{>0c<4guf?0m-*Dj?+(90l@-T$xczw(ws&OYP+(aHHk`#E0+xuqKT@N>f8*K- zLt`~}f0;qi;orPQ*L%SrliPrp?LCdquhs(G>K(cIH$E0Ul@^kU4C__kaXAO)FUuii zo;9~UkqdAPlzD47Z;Rsq7>gCGy;pC9CF$hD$?wS8p76twQvV??6M07)?27wijih06 z;-mykmh7V6o&G>oJinGC{l^0*ZkbLURBHk>T%znJte6s^eC3Q@MP5^o?Ae8)Q>@_4 zvLv_}bq0^dR}*e<=NjPn$Flz|s^%n>6P6fRzzhh84rCa~_x)g9)wh^T6Uc2+Q2u4Z zmZ!?TBhY2z8solzVb9G^Mi-sWg}ma} zTpA<#rp{9KhsDuXJ}N&?uF(vMmHOd0_1J=7)+VyQ@2iTS#M zb*XzWIhE{utbDAxrmS9sU(>J3tQ;OmdKMST|5a}Z_#|#{PA})N)GyDO6+uPD)w}O5 z2maB2nW9OI5&1Z0pW4^y_Lo>t?U27--l4@}(1EBTzk!JLj{8Yba37HCO&`PhMlKq$ToxkM3hE>tMlWQj7%U z$jGueb4Mj}bcUo2DPO6gB8GO_*d*6nOQs<%df|xW8Z(oaiVYst;lz6V!Ra8TpTQ>b zdzY&sz1OBIjS52x`&%2XSLjS11*vfVZrG&s->DV2g`bBfGr|eV0m|!!>dM%@BFtBO zT>FC)hwn)0ac2HH3dC}7in%+a+UZajWbkptmr;9c%LWWfHrReybnf&niVW$KENh#N zx=|vV_;lfF5aHHE={NG8#{vf*MJTKsS4FI$7t{at?JG!}Exma3uK`-G)$408u!Ro;YCh-l z#QP?>G53|I0Bwb62O{@v=RfQmlK#d|^^2zhHdx(0KXr_+889Yzpp+SUQew^T8CEfd zI-+JhO+kN_S5c;N#V^n~{=p?87R{}Rx^qMk4H^y(BrJLh&J+u4B{kdw+pz{?JGz(8 z)?V8FlR!W6>{+kef3W~MG%jxOawO7k0f=M7$zCR@;t*maI*m(fI{9Sg>(Ou?J4PLs z!MI_JfMRWunC}|JXW2L%Ot!h4+0q1=t`N-2Jw&_%PHIH z%!M3F(wRms-4Bv~dHwn2cflPi0wRiv*2gPxQ*!!o&ha1B3WUY|E9K>>Cu;B@9{T))C*fZ5&wD-Eff&CHm^QW7k@|zX}804N+w~`DH zfRf$&Q8!!-5h9E$(J_}%(_Var$$_S~h~6o~^tR82O8b)~n)Q;-KB+gxqg<~R zgqI&u-LZc5qnf>JElbX&(V)_Rb*kXz@CI%R%i8|^szy%cTxxqpyr|mw5IHNsANu7L z9&NZQB=w3(FAMLq@=JE8<>Zy$B;y&lXrq(L6JwS&BpD zb89a?!Qj{>S1upt4N@D*wDwc# zSiYI-cl+3`|HRC~lXr6Ur(|Y|K;M3Cm>h_Pe5A*ByM>aa{ud1duR3*|J ze@gh(LU2)Mn{OTGkDSZvtxHuBkJyI!=e8XC;NN$ocEe76h!AtiSurdRbs!0@`&B`a zFE}my{N?KnD(1OI^X4?q-E^AvI%N-X@>+YJI@TozOX-}yKCpwCVC$XW(OeA-UmqiU zcB!vy`*+*q#`${5slv-ZR09B#dpx%c?S_2*C4$osb< z=*dSKoD3kE z#|OM_Fj{O)@me>NB!TO0#b5A`pJ=4J3bH-QUGp#f6*)0d{42UN_QfL4^VYs12W}H1 zw(L5;#2aU^ES4XS&MvGO*R)3}G13njO>IYiGnd9*Rv6x%DbnZMSi8jGj^e>!Q}Bp73x1>^XF0ge|SvKt(*RsG34H1ROo?esyU z@3U*qEAN_BpQyC+;6L&wZj*0pFAyI*ef(*zRwZz!DW>k0im^Y9cW|~QtUeR?<30d=CI;78Qs_0j!i2xjyYTo zy^{V@S%yw~HRnGLY*zi%qMqE~@4jpz>a}B2$t{^MEI?rJJF?-5Wyp;!(<&j_)o*+% zc>8y@u#;OjEE7jA?9*&3)roe;Df~z2lYgBL9yb2H=oSDindWb0)o>-O zGa!agn;hUnp@0!A=w>Txa`d0yvHI;lkAKcF_0ra0)&fj~7bdR-3KljyT>$yuhF=x6-k$|d*rhYqc->;bUnlPPF8spp zP{pt*pEa8GOSq#$SK{c^pFNc%uTKqsuRb+k&;S*A3LDsNlO_MTEBmD_%_-_gsm5$a&Y zsnu1hlZD?-v`T3gIr1K1pO_w*@->Cx?D@{D%h9V7SAL-yXXv1Kc@uN&ssN1S-GH2m z0WlQClt0m>gNO$O#$qjiUlqZP;qE9gD}Nt06+N1&HMH%>A?ex1HW>3&Mfvt9<(mcR zGG?~ycixm1;_B6ZWoDn<+2VZv6!&L>7H{f8d*w-c5~?S$Sly@kh4@Epgbk!6)m2Bf zBHt%}#eX}?hIy)6VzJC`%*t=9{Ql==8CQFw%15Ca0hR{GGe0k@i|t3Z(HJq(J165j zIu<#n{`}^CREL4lJG1L49ZQtu3D@!OtW!hF`*QRrh56x%itDK~wYGtuJN$`d&ne}qvh1QOo{m@}8VZQ)(f!dvx z`hle5P5J}V$%8+|*GT2we!1+LY1<(XHd}mlw$#T}<@?^|UVKs1v0)i;M}ebD_4U)Y z3uK8C64Qe|&-#az-=@b@*#r-oyYc+|G9W-Jctz#$`E?cHbx(;iV_ZU9UtXO5;_rmn@1Lk^s&hULn>hjD%ffcDms7aX4y58A+^^3JX%P8`^VlTW<1 z_jIMOGGUXU2{+)feE+V->wxa)?b1-1=Zd#EL^I_3Egp|xMGg+5xLj~f;0+IvH0^sI zZ_B%K?+>qB>)aG8FLhmUGp;ORHh*!n82jnCjk_?Q(2ca>Iw9{1KCMU-vp@Uv+d;Q= zrgf`6+?P8GeXk(Y(1*gJxHMB4>R>7Z2`W-(Ljpb*rJ3^ms%B_hH8p21m(5WWC}qo; z*4LdJ(b9f)M5!KqTsX>PESVV1n-yw9!F8wgYgqb%m9P+96GN6PS8ldG5&4UozgF-5 zsk`Rim~1lkK=rVvLeg&~&#d1&^vV6On0#-;;K5U(M(nL(6?L4F@?DIpV&p*!*?qI> z3zSEXn9t5_)8c(T+HdHKlGmxO-@zi5Bu&kG5qNF;Gf*! z6>EA<_ng;<>C6!SwzZGLPx=h=hi@^Bw2xvYuTBz6aMkP)oJuY%%)+iN z9J`wZ2nMj3hV9(L>xyr24am%GN-dJ2`F`RFF2Cho)vp5&YP;(UVXD_ME&F9DMXY}K zJ7lGitvWRPIm_6|E})Z6&9Y_a<7U0OmS-ZpiVxuKMAE~B&<8KKH$CUx^{L1{P0p3Q z_@T&SLUXA)b>L>S%sIa?i<&FLSZu(2!}_6LPMF#GjlJl4TE_LKB!UkJqE~dUkjokx zHf7>uGCeqJAX4y`)e95#5?^uknRXlI>u>X2Q=8lqWS5FVD+lsd+$ZgIiL>rH^>MEG zhIuw7ol{=*PYmNddhl?8>aFbOsKyWV4@jBlzRY`{uygXsDUe$?Z1Z6$-pzYR^J1;o z;yC|h#-k3F zRqo3y)Rx@oPde0X*Lz-3Y4H_~WfI~eLMq?!a_v$G@X<7q)Qo%Q?D{Fo_#={D0#d9449c8DFx*|&-pEws;akl#$sq_QUNgYcF3fdK3XDJcBl(s| zCMNyY17h`*6Ta!Pg_lR!2?zpKebX99D~$~^0jZ3Ewkd=G;?h)Q?23e^n5C%@i8gfh zM+?;{3zXQ|s{x6ud`B6S!zd^zYao8x`Z4i-)eVFOSlnAoLH!Qj%y)_U0C;gh{on$c zg9D@kV8s}jkz%+`!z4^1A>cR~1p*?hI4F=v0rUDv5F_X#ID0=3#G&Y!NwJC0jid)k zRYWwok=lOH3yFE|fav4ZYA52WyxUr-?8Fv41(l*jiQhL#oqUD^X^hmL$fozvZ2 zg7B{Jwp?G~8|3!pP9UvMp!DqlXl^)=`yd*9=<(H!&Z8g0Mk8XB(x*?lKyW1jP^pj} zCkN&87=r#56ydtZtiP4O6jBU>I59}cyaG6lBUFI&2}wZj68%bk295qSXv=HC1T;Vl z7vM{PM*5=koo}J|Bs3jgy%?C;(d#55=nT@#h@lg~B{;((Ce6fGM9qI=4!Xu^mwanS z^R%h8vD7g7${k9EM5j5`MWs2}`9i}$^BS!NAMnYe{~r<5qFW_F+XV2b7 zUv-KGv~$s~G6iVpBXk}UDEp$F1o5cR;%kh6L1sj-MzXF|GW3&t$)8=(f1BU@gXBGZ zF0m9S)ZyIWs^fp4T72q3%@ z7*?{TLWoJc(40U_i|k%2=;Wg=j(NJqmj6h*$uEZ{^gE|FO8lPMBYh zKpgXcoJs@Yb$FsX0C@`T{+dCGiBu{g|FLW0uRz?6l$wzmh0~`>2n6`P0DC5P>)l^* za9kOgiLtdXpuPy0Gju3{hXQikQLcZ-7p;d<&#PBfFvcf&fA2h4G~V;iagZD5-+b=v z15jd61+(;uK*qVW1FZH|Al!yH`e9I)7BYi&gsuZ9W)Dc+yPz*ZfMi7Pjt&-Ddia@q z-GorsVpg=ne1NZwjEqDqSbjS{Zh@JA(Juq^%dp;o9Hi6Eqz;CmBLwK~Uhz++)?NQ2r&r*hrRz(Ue(vg za!2~n@S!0ME>kph_QOa!Y58q-G_;_Jn5DhsA!0(UtiAhk1xlQ7IQYbYBMlA{s6$f# zEGhK;S25{AKNrxuMGs$xlYrJVAEZT2(Tn1t;kzdwD1p9I)M7pbS$sqZ4e0T_0&(^l z`(YLU4uI}75rplk0HhEB6jIjZfSLc;yapG*HqiotZ$tp&kZ47Q?(f?R$cKPFTclRD zG;)FzSgiX>_T8@U+g4E62OCrkhh_P%t>_5C>@?8yhanFDN_mKg3FQWW`9}T${PzF& zKuyQbt>S2i5&*Dq7jRGi27BcI{R;rrih-Y3hB-R{07J%r-Li>@jDn{vi7^DNQuM2= z2zU}=VLEFOsGg9b9_Tg%GTwecj`%y^#>1oz+WyB-xLUs!XRZS{&;m}OVXIf^===wM z0CxERN@0C2o!`RCuvw*`pUf(|sp~o@(@8gz$Y#J#+fb;@Bc&MJ7 zqb+U_3m^io+5=+HZa@$IKil;Y30eYz$qFQJO{EGMWB~{P&JTFE&%;M?0z9}I(Q?Cm zf~1PjDO=(sa%BarqB}^w^Z#{wMVz_|Qb0(X6p6Wln3{;&oIDakfuU1TX)#!d{PSgH zsINW_`YJDvkM66x0Vs)YoCsV}8=9suxxm!EL=)$-vjgCZ?v+@>~M-le-{2E-qat zt&YWd{hDDeD_a1FafpDY&fC^GM6QB#IN$|5=1%Ac_7woQ4qX+@cK_d=9wadTAD*62 zM@MJ8+VTYYV#g0W|4u{MBP3_YEaPnf;Aw%$kK}0P8i9gfsy0EzBwspE&F-IZ`Es*0*>v&l^FUdP^!K5}2 zIs$qk3J_L8NXgd;(Nj3=C_+rAv_Ck6Ka1eQ`L7S&z6uHNKek6e;~T;_B*p@$^_v%> z_z@BtCdlcT*x+en252(?xR3ty1)%Lz!}Xpb`B-!`FAQI@27g5aROPY2Oqd5aL!aNT zxxtG>@Dcs*gC2v10Dw;uLGBzm3p9#=YT-~7L0pOLhdY_0Y_NwqvSQBT=MggHjO-Q} z93W@-t}bX!tb-q$kG(hp;;)4e-r%>G3IU*m5Y+enuRFPn^Pe4{y{c^6F-C?5Fz7Cr z^;(CRW&ubHQ~`yF928HK)xQI#AOGJW6m)q2c!QoCxlY6j2jK{NnazK{ zONYExpaA9{4BH>bBBufCjZo@Ww6tD9xPm<7zk{4F{T5<5@aQmL0phGdQ)?2^g~s-9 zHW0_pjQ{S&X>Hp>VTXBD&K?J1eykb`ObQWQC#q;Unm~JO6zm|1Au{!(nY{s zbG+DkrwNwmge(Xa9SvJUwDw=qfL-~&nFjm+E@3)^VP+k7@M5lq&%W&fxbNfB+SAmu}DqnMMF<%^bK%B@jAAhIkDeDH<_=7Wxy-6E%NDwO&klV{$5aM2q4Y4c*73{vrd zC)L2@TR4D_>5!TrOzNRKc@-Mah-h>JuFi$pL7@xCG^~=y6zQ1p;N+;lj4p?W2ssFL z%&QZDi|9l%5CF-vny9r!BDpZU5dy}>#>LgUI)ZN2l+8c)o7Wnrs&CIC6|6H3AD^X< zvcdR6D#<7F09kNHh_V0xdUVVb*bXq2kvjY9=xjpd2?Y`MvXlP}2$Yk{z-a+V%NZo_ z1tzcnE7T3-KM!Gq6JZ`z!_{E_8qz@L38PzgAL4aV=A#7ia+7;nKPf@FAqFjXWdV?v}8~Fop7;sIfu& z>eW+ddIfZoQC6dk9a~Ls3`N&EdNq`DK$gt_XCUzX*PdL3kdYD{4$xBqK2LgP3UVyv ze?#sP4L~L%;UR#wcfZY+87g%(B^{2@9B zu%ZL22_?8Nd=Un&ZoZ;v2HJ0w=xRCDQIv#Ui$T_JOC`Dy17n8};+R}R&R@qDR3*25 z%_2$kJ(vV>8x(A^0EdIzB`?G@h_u|L6XAg6hpW^0vn7}zQK3GB%+9P z58oybc+5js-U}t;H~B7tyTHGKYzoQ8MK>yM)7eA#p;G|^{^ij>Bkd(J-C=vc!(z>~ zk<+pSp$8Piqtz=cD$27TenNNo!6mS9+()l%ynN8loLE{}SuD_5uKXj~vObj%wcH$>(O+^z)wKPifSHxh=1C=huqAjH5`F~OjD zt(QlColX>#-$#)kgbX5(T++BWNyYbtz(MbDmaqn2BQQxZ=84>`PKCJN)@n6njdoN% zx=qKJ(C%Q*8KsQESTV>Tu(Tf^$-w3Q5CRtth@xQrtQSmKV_O=+LU=gf6e<@Y;I;b+ z6$ue27p*uHYpGO-p3hq0oQY`oFBYK20z|A&su=tMkoS3rGR0gb>$MI|x5tnQEvQFX z1LXrq$DaqUB}$j7agIITcn#u#SHRyK_2VuhIe8F}mjLoPgq;JdwJZUoAW+5$6lZ(T z&l#yOxri1GPP34^Hws7GfC!-g;spdsh9p>bNQV;a4(l$R{ZEYxu8Wc~08WBt z;yW6{g`pl;R|v%vKvx@?4kZ{q8cla4Z%X;Pu zF$jM{v<7uB6^H{)#btrt;L{)sg3%E?6zjpDEL1C^{IdiGQIYEbXec_yRsTj_F5vLH z`3As$-0qba{{%@)HPE0$sRT%v0+1r24LKex`qRPq^t$Pc*+CqS>B6vjB` z`r$z((&&6ak*Eu_RjUCBhX|x$#)ce8IQq2BbS%PpflN7sK_O@~r2`pVNiE>zP=giZ zGH6-VDK4>GuZf3!pLK(>*9}iE>Rmvh=Rp%3={*8V$w4=uI&fi{*$u{#3Lr;9KKq|z zCD%FK_0L^>d=3*S@K<46(!a?3Yz|R@8dAO=4`j!HHtPV>N28LQoSbMgEaAv$Q{h9E z5BNFmWgCj3B2xV&3lPN{2k;Y|EFAevTgCyanhygLu`qVu2g$#PMF-|hhWH?QlNV;f z56_$>g|i6^CN&P4$}0Z~6%8{`ZNd#RsrnQRwJFAbXOg}`EuLi+uJy=4E}$3684id4 zvi^nMy6dY?(jFOqJ?l)K;&{sB#QmvDCI-E2r-v>?s16Y zQ&cE{2nGoRjY2sICG`vusKQjX4K&{Cmyb6uV*;UGgPNr$QFNdz-ihEF;~IIKiiB6Q zrKutIDK9QT&zDBt9Ex*2;CatH|IA{T&VS(oCA?5r=V-DPa1SCH3jh}*p8~*WbZ5Xa zg`mnY3@oaEw?cP@BhSA}c1%mYgQLF9?nM^~J~5_4a5|{3MDg^cVosL%pumqY6^A~8 zEYEjEVgkG_vG^a2c33;V>rKt7xk8gxIJat2ZWD$_Bx+;G#gFL_NVg0wElfoh9D@VQ zO0PnGPFpvxI@A%{)Aa+Sq+UaGH!vJB(O3cu*$woUm?g2e**yy;a?o zM0L?lcKoKS1U7<~7rRf@6&|{7Wg+{MKpNyA*ky@a1Li!WW*ytwe)qo7xbB4lA5@e} zIJRUxYQ2IE^i&?;Wy2iju2Jr`f@zuT$@+;-@Fm?~Q79A617Bu)P+EGbo_vtWoo>PUXf>ZXaux{XuJ7S~YU?72UzZQUjbC?AG0bz|mRwgL zC#K>FdXzpA_j+LY?cK$%gE_Ar3m3Eg`Syj+_YCX!#I2M!=etiCC0PdH)4ay5vk~%O zFQ)ZhOJY9v8t=lJYIO-iP7>!NLAOyE1@w&`s09MGwy-hBuza2(V+x%lP81pft|YwI zE=bL%>o;4~`biHq+2akOoD>GHcIHZ+cGay+sL#!u;R@w0Du z!f3?hl)LBj$T=v;173h$)H&(&jn@p#t5V1V8vO}9P z;p@KiD{(p9Qv@>)#b=1&fqyS?B7KR%bLCfWb*jmMx{bfgXY29{%av&{< z#t?94X)oe7HqYvm$cL8^@=A7-U`ysNgyr4o|Mtth6t_{cS!hz-3Eo!W)*}~7mCqy5 zN*;JxU)T!?mHWxF))XNofanUu5Ib5nR}!8i$C0GdqBid4$}qD;TMLD zer!&8-;UmwYdy0=cdusG1lDuy<7Vapak9i~n*JP2htRF6r)LguyEZxCFbLdgxjvsR znK}?1bx+H(h?nkOD7SNNHapc`uB_Uyd!WTzs*KxTLk_mG)N@L|kh8cnQgm%{Qac)M zJeT}?itD+}nJ*f7VK)!0QrCjweiHKHdK>L)Ks`zCWk$S!ILU;ggvXfamr~z;z0HL3 zWp?u+VUNn&u)8~*3w5m9pY?lG`>gt9m2h2}W-2qu-~D34C*Y)(+ZCGrN%QILHIf!Ajn&#&N2TnZm9}QH*+s zSuGj%4AeNVUL^d^&9(?dn^Um2Do{~bhbjv8`+$(Lz6?tL^`lF)=k>Guv7Yl(TJVmR zVMb5Co#On9@2HTNn1ADS6d^DB_-m|UP_>&{+KkkV_avcmIaN0}J6z`<8u&z0y-~8? zrfS)?WD5xXxgIL3wycB(JY_rH|?v201uZ0_=4 zJ@lJ@t4EZSLh`!veqZWh2>0NLyK#(_&a}j}#M%ir1EFGBpjO3V`6mINrZPzt>%>&vwu1H^{c-Y@UlN!FwkXKQ&YR8m;xFO8OZKuU zOYgr?n^pGWVW;P!Ze7M&j3Q}@*em2TRt|N%5 zuR5pa$yvUXNCkz;m^(x^KS@}LzArhpZp4;XC%pakT$`K0p2TzK6}gH#fq{f3%dbnN zqu-Q}whfg^cN6b{^h!O`>F_UvF(YHw9j(8lbvPrZ{4HPcw3qxh=10DcELmk25@^4k z_@F4osb;97CEQPK=6HVVUfFZ1JUkChS#DygZ6)HrLSy((-MV(bbl`sJTc z8BfP16_5$4Z61TaBDN`?kX(@o_u`V(el~QY4#z>0_~K(m_K$@_Jf{UURA1|yR5QD< z7b<-Igp|o^Qqy7G+Ju5-%*e^jzRZOaVbgeexD4qG?k2%}`8>o(dkT3C2wK!2Nk-AT zBN0ls$|7;`;hk%fonb|cMJw!_vJ)L2%!T5O><~mJ)dw3FGSROJ5Vx^#^qp@h)^#Vj zYe6O-mqAHKn0x%|>!&+^kIkR)(ujCmwRl}*sOLO)91pK9K$XXO9dDDhO>jWR6Spah zRIFCLQ9e(=D>re5bb^!7ldX(OZk}I4n3!39j^=0dvPPn=jRnRO{-#lnEw0ptbL?fq zm%2i{xR_TSdrB_Jggu&h;!~d$FXLsJLPlZ{@2h%#BCBp#(;b zG(tSI33)bi!5%pF$#rgJlfPc%m9oJqydLrvi0c52kqzmomHlCNf9MS9z?XYj|Gr@!{!v(v1yLl-CNzy z!=03?8ujpEC3si$oi_Z3g+1Gt6uo3o|ciDSW4csTdLaPDD-yk z?OcqcqktNtf+1Q_RB5qA zWhFiWxR_FYz1FR($E`>TViM;bv7{7K3#V?#UvdD4CGbYKqL7g5Swi{otUX^k*U@ZW z`oajjXJoOm5bqUbeKj6!T;KQ^npJ#be|l@ms}bV8`FYdlt79x3@=|=s##C_Gt6L+@ zK8#&vOn0=i7^I{Zwfd4KuhWF~tN(O@g+`!~H{F3A899~|CrIz5-j&T_wxQIAo-aMg z$Y2}Udy|4WJt;EMGS-_7x=XYZD+?Fve~D@BY0ZW1;+b~ghyNIfYF?(QudQF0U88`T z?E)&|q9Pkd{3R>Y>Lfva)r;tleJEwJ)l z+qGXyz3ifX3HaVbFb$=#l$&7H36+He(!3l?S6oW@rATAn#5PY;gMZPMBpA>ZbyH}= zsPH7PIfc9<7A!w&AGNrVT|!4pWy5RKuPuseQVeIUIoFi%nX?t#FGUKA*ESq%97C1$ z*oXO{(m+Ngxh4~<^h8PWi)`q9@w15@oM5~Tz^{8F<;Jx4(-d+t$*QbA-dWzP-`QOv zzeIe(Xkp>uTNP!TWW>b8#iZXb*h1>k3`Be)P}&qQZ5}~3o?->IUA4fH$FE~XZs=V(&&4`Jb#`wO%;KCIuTuWN zoPKuD@MrvO+;{$8n{&+qA@19kJ(or?(mzcYdo6afXBto9wVl_vvNG)PX0c_v{pC2n z_%6X|2WQ6^iH{P^Z#?Lu{qDqE-*bC&_f)uSxO>k%JlA>Ed|vWY6XCw(kNn^LEsvl8 zhNdC^vDYKo+KD$6g%Kt9!L0NB_`Qhe4wDL&<%2_g^e$zjWwLfYCTp(t3@!11K$rG0 zNs!`CsU@bjf8Htt;fDW^*VB71&(>5^DzYmH*@TVO82$L*kCgL2Yc5SBa)&QX|T)Rc1u{ z|McG*+GK=)gERe+Tg$dbePg|9J(G)63KblpzfJ&$uClP@$0!oMO>3plLbXZ zwrx(2fc|H+?cQCUs9?x|*d$Uy-T|EC-?uHj@L=hC(U-7%t($)76l4OKHcFJ9loi@G zj#1~9&sA&OC{W@mGoa#;{Qlm~FB>f9){gU{qEwz0oDN* z^6teg$)7TDaQcF}u4nNIoxc|!b~b-f;jEAQ$GZ~iW021T(GI;CO0ZH_(DT%L8^xWk zakuL(uFOrD#N}&Bp-e&i6$bfj4YKwhKYB)KyN%zY+n?TdgP$Os2y$}%lp9i^)JBI{ z-S%^bWY-!xCjT16Nl8{-@CJkEeBQ~>lZ3zPeN@9sF-a^pQ__hc!J$NFEme5l&u&$H zC0n>8*JPN-HM!M>g09u(rMJ)<8ye?^72&7ybF=e3)NFQ}zQ@$(-{%g$!42^yiC%q~ zlQZ+tXwL_{*rC|(DryWmAS{_sYO?_D@~Qt*^n(+Q-g6gbr>B{augswEeGBbJZ!k6) zQyI6(y9}?FZA_ioX(|LNBZ#U=_s0lx67 zT$H!uTv%Tb%@V;GKYi`Ad-{@SeO)75fd6{Yryjv;C+w0Ptsew!4)|i^tv#&^)AZ1W zB=JUS4pWX%N;ztc&z*))Lug{O>m9C3h0AEyG_GCb{!jAJqU^2go=;a!X$VyFSufu=_~HHQp_SRD2VW!9 zWESWB(K{;=Znj{vXR@#waO;D8NTf(O+`1KM<0)$Yfr1>vdQ)93 zy`F0hPA*PfhRIgY8{M0lJ$i^>GC)ED01WmrCG-`>n(}iIyM#Nfy9;T%bXSvzDg-M= z-%gSW3J5maoY9eGV|5$2OH3e3;NI^^h@X$SHgwHBd5y2Wu72^<1@oPWe)gp+1>Jm2(4Vyi>VE_>f$pXyy3qQn z%M_Fw;;!$l*X`R2yfzEo_Whox*jtgJ&gh)1qx2=xmlZ)qB9WfA|I1kN6sZ2yyw^_)T=C9g^Ky^b3 zZp-3>Yle>-2rsujP=OnCe_ z6lo_zwA>9Ps%{o@T^a5{D4$Ux;2G593-pIu^kvRELdmBY24S2Vg+c3!Oc6= zsLKo0G)Aa?_o>YOf+ZI66rgpQ+Wy3UJ0=XP=883aWBXc)k0V?#_V+>T!2X4s-wp?o z&Kfj8V#w^wd|tqh?p1G`Qd5L$|BbqhTR)%fv96prSUAF$o4+8Y$}aj47vChyq_hLQ!%g)ySKEec+o4Z`a%wV6YtVi(n8kf0e0;3@P`G=w zx{D`@oh9JF9kd5~;F|3PV+nizl`1_weE|xyRH%B2kHL|L#o_qT0#YzEm>vKyY2H5^ zA0KBQo~p4{n-k~0nx?(r*>rnWXkl?NdfIGeSMaB=Ym>>3nKlyulw8A*#mnv(Mpp5L zl0lX5OwUW`@>lPJU9lq3P46jatKea30IE?vr54A;i%6UGzYQ;L{^@~ewkJc}NjaWH z77yb-EV~&V0eyrO z)UooRF~BY&qH`ZEB(7IP@>^?DyZM*({QO$spip3X0N&$UYOc^QsQ0_ad&OJivgb=5 z{!PJ+>`j^Z8=t{*D(jzn+V-?JV_JNnA?8!hyB|eXRZdmwB`k1gt)P6am}0vDjg=^9 z7DfjL9s5~eh z=#P)}n7M1_{Cbvs+4e0Zi70KvS&|1-W(|AC;I{7lPQG7r$-d>^$AquMJKmd(s`nrJ zeDt`9dF+7ut>T@oH@vX7mGW9mxN`L>6|5k? z$XO2dGM=}{mClF$!b@2e=xxHE&ChON{u$ds+a&3#prof%phU8XX2*e>1r^HwY4O0) zLj{&F=C3K>%0Rz9QX{}TbLipTo)5xTK+&^&>yxk`Fx-JUAL=wi+YCusLm52E|5;fX z>Iu66AO{yS6L5U^?bLP>RN5IXy2c>QWq>)N+IbBKyu`4`PL8Bg6#ZeoygTiQKnIA* z?FFeqVS_7ZT;Bm5FwLwQJPdleuC6ZMq5U%f zh|ybBy?WbfcJrg#NFLldjymHZ*MT#PQ=r7b-dcD`{EYdRfS`btBSx0_&W@6xW{zdj z`lg0|cdA($LhHa6p;NdH?1%+GTLx;u2#fP1;K=u2?REhFwo@-a{=nrUU?M)0)S=?t ztZQ}u@7Jdr(DqnF9ZTSL4n@@O5}Bug3=Kh001RlJ3nwV~x0!0MgR(1jG^?QaOLZRK z-wV_?QVzzi5EbKXd2RKe_in3@^=|dHQh!VFWB12JKuwidY0dXM_053@oQ_(S7%sx{ zwKniEV~smcMWMBV zq^BpJe>SV!1(qB>??_1iIs(QPP7#7)K%HLT)A!VEe@(z}1jCO4P-H&UJnDK!J8D6971z(w0_HDYTpbpy zfXyX_-U$DgwdP;uvq0F7aCQjO3s@7XeN)i?HZb?6ZfR-pS#Sk<>WV^YqyLXTqk7VY`eZ~b1(=wOp_v+jv)mRWX1nWEzZ zzK=^4A$oThm>I~iIMjS{!~0B8+ULa_9U4gEgl|vT>+kC&dT;5vco{uzT6-3Czaqb~ z$vpli`R9#>O(&)emeQSF;ppjU)9DBMYv(hE(10-+z0tkh6|Ve@c&J8~)ll(_Cp6(a z|NPwj(c-zS_;2xsQXkRR0lRZaSrlMK&9~f7GlNz*FjAu zh}0YU4-vos^|I@4>B-(>!Jd3>qjp{G`l&dUm`5)k?cM#^o>;Za$V>ymqrXUA_R;<^ z&#h<>{29?wFu9Xb9swTW1V&d+FS_j*>h!7*K&6{q@VY~y&i8qyjjLg^XlT^6dHy6J z8=vitveDGeKtxTeXZgT@R2e(O0}Ds0$=er_zv%vPzqXLTy!v%Dl6;f{Whjf&@rjj> z*F3K(i_bz#I|nJ>VZmPx-O3q7ec!2Um!HaB%XTl?*0`U3%tfrM z(9j-m%cso@!4H7%Q2{<3LK##C{3Z!?z!FsovOR%c7qTEBSTC7hb@=Y!btQERAjt$6 zX!a3wTcO5)+xLp51pw^y0#e?=kO`19lAzvXWo0!2EjjjGdm9@IxB-x029AS@qP$Fc z>1#l6kz!C2dVbsQbZk-K><0Y*r*plI!~a^pgz^OYE`VOpr3PRXh)mBs7l!%L+b=dw zLR71hc((IAB&IPjEJQd#Sl{wF>Q_gCkr7_zGVQOlK4~4?{&Kt!z;vv)n4&E7+WhD@ zt=O%1crf9j2%z^3=qV~-$B5gO;hf@Q9A;n2T3Pc;xLqF}1*6FzZqve+ImD=bxsjag zi4o@xuXvMFTCKU%Cys@rIVOre?4-wu`x*PZwI6DS0=e@u_zi}7g+2*Qm-6E|{uc{C z=gt9n|Jc#dlFPoM$-W*I&Wd#voRr$>g=T0<1+U>x#gY~gLK@h9`~V0HnR5b;q=0|# z7D@xp{PTwIhJWUul=DQv$^4p@n$h{k1K>MxFz)W|)PC8Z7NnR|SUm`kD2;7Xqm&x2 zuevb7KL@S0UQlf*U-G{L&C$!p2N!-eFOouE5&_Jh`K`jTi(q{~Q7I2VAq)oSM1p#) zIuT$9;8V$8Wy^oB@IC{K76y|uZ16L&q_=k)EH<pVYt1K=Md|Av+uJmGbtX2(-}o zc8-AiyZ~Y@)V8k<2yhFigMf-s_TEkp2*eqEYj(f7iS9wQ4#%V)yd`utG4TOS+D{~!POV9{*n5^eT9ZcvNc77E&q$mf(u_4fdf~*EH z;JG2^s2J}{F3SEi)$*=Bc1dTnk-5YtW-QT!`bN5xnu^ExJD#=K648KjH*ak&X1qB! zah}JK%<5Xr-lbojgb|vTq00S2_NQz_0*71dP+HJ6v`>2bC-iSJ-uyVuf5E)m`R|VE zzU=-yjcfM;&s&HK|H=L?4I~H2MnQ3$0Z^s-i#*!ZgAF9vKeD093NQc-K`-_81te|bOfmFkEA-UANm5WyRD-?|Y{oypDS(YjpBT*So?asa&4Om6vkUPZ znmRxLjwt`P;Kt9=*_QQ9SD9Z11n+$)f)wp5l&`L|q-h?;4l;f!RDUG&H|zI7oaXaq zUwT;(h6Hf7idZbt1HxdQzK=v#5x^U4O3mAgqml~Tz}^11`%A4d!wDsZ!!CDSP<3qd zKOn;H zgo&bR=xYKTvJaIlSx{--F^gmXA39TekJhfMhU=aKR2)Wo;p!VWQS^$0C?6ZJ{yN#f zkLV*2nqqH#o`IfT5NQwRMK2%#{jgg zK~?yo5e*bOER(KE&dUJViL!qDQdtYsdfgh<91E06$smq}Y}jfjL%hGgzXLMd^8nX2 zZFa+fgV_mbRJ6aDgUnM<#d!a|2C&wEwJOqGcsC`*vE#yD5!K_M?~0v(g>I8_cIW$U z&*${O)C9`#S8599(st8E^T>4Yi3m-#g>q|NH&eeIfE6y@c`7}*TKmdu=6*#PglG(D z4A2(&+U|4*9YNFqp*8bit9~O+u5;%<%ZrQE6lG58p1U%z4Dc{q%mKvb$w!mN!!z08 zYS@{3nByn5jXy}(h{$$0m6~nYj3%`BpSQ>`ZNo*HS*|IHF;EN-W+MI z$IAD%eyI4+kdGf!O+fKco;5Tf!9_HEDQk1)^0^CdY&e2Axd(SQFKu2;lX|q7sov!~ zyzf7|dmo@ZXfWDjI|E(v;H^-aSp#Sw(g_G;{Wk!Hj-bY!kFLu_!d!va_%i56C;@FY z!av)w4ujMb2BE3|zL~ApX74GKV}1DPL0C1n+<|pKB5ob6gif+-4Ys5DF)tcVTr#4f<*x88>&QkHJ zWtgf@>0l9lq#IICC~KUN|8(aCT!3q>!^Lr%LDq|a%9^@!oM-ImOz^f!wQll;%jac6 zhiD0BO|hK|j`6!6l6Kq;D7e%*xyD`DzkL(SQ;_dqZ}{x%;*|Zpri!0AK>8bmdOJq7{dgf9hq_YjVXfSRXmu)?`D(WE2>aUGy zn(-^Ymh!=c1W?Pwq8Bb~z_3EYzNjw(G6Ru`WGLBbhGu|hAwVf~#bzy9q~X2-JS8UE z^J9f2U8hrC_V?f6E=4WFJ^;OfAq@agxa{0R8^y!N*9E5(K<3AGO-K}woRKjapefb} z(SG^Cfp2^G+b%9sHwLX9UU$1xMP*sTED8c53N1(OA)%$L`v5<`qUGxM>MhJm;b4HC zni;E`)={(J%$x|Xa@oenb(4$2WWm%)tj=YO#U&1NVX|6&zwPPrr0dNg^)=3gC7-%M z*8EMIM1krnG#}{1i^tsl4`J^ek9EKQfnWCCTjmuSM###D5FtX8?7erWlx!}tDy8gE z64`r{S(0obdnB?Vi6VZlxBHy)``zDve%IqX&f}cB?(6z|-s3f&ujjL<{Y{bg-nT`Y zpP!w-udGU9;MWI^dAW|)(4jFjur2F>(D}>#1W&^fYJy$znf)U3EdS-miu(b7_*g&S z#y239#7axE1n#tQCy(n4Z(W~khq)jV->&<4dB;&YrebT$2bzW9)MMXQK9`I6tr#KA zQ#AG#8XpK?VZi6Gh`iaERkPT>XR(Km0cOW!KQs2?%I_o?ByfSisb~fVP}>tak19F;;wrfdvcyM7%1oAl}q~;2u@Q%iE4~@Yf!P9BrX;}+s!bF z_i54P$L8h+;7zRncg8B^Y7{xhw)DS+4ytl)t-5mi&5K-E>5jYK?83)Y!pGl2icLP5cyOXCsldO zmPUL3%uXW>ov&t+jL5mHV%n7P)pA?++qa;Yx1MqEI|F4>>u9+k3h=Bo1rpJ>Aoqb1 zVjI9%=`ucVwHLOxvy;3fK48wL(EU}R1YKu`4088->;Lefa#0(9P_9GP6E8|Kiay~Ua()-ha5`#47(9R$TGs4h9qh)5} zrmmh|FkBK=n7TO!ItM5}XbvT*b__(?H1LOgUo;%9`ZV3ZjE#?pp0O5Z)DWxZz%I=Q zs9#ijq!)h5CWwB?5`T#mLFaBjt)GfiYb))(3tdVr9j3{LW@q?$9rIKBQRI zhIng{3@O6i0kSTRTQLs#cQhXdfS(Njllr}6?{YV(R8KkD6eA_nd-wax+A5Q)y4gw7 z6vHg6c1Obb_&Zj-ad}j>M&h2mw|fV#RWJD8StD=fJ{{L5{PJ~q)v(`9KOVI>G2t2o zm`u3)<6#DZ&EABn7l{6y@TH~0!w}Nx9jk18tpWnAP8%M>jp4kM<(*ECQd2olx8@$; zOGzVJd4VMDf`$ei7(fQd^H~77LOym@TwEXH*yje`PMMS!@bW{`wJR$t0xor%-E!xx zt!Hn2uYNh)l_po+eD=k~r~QlD$ueHnp>8zXXU8q;VNi!Rj27}Q|D358AdNFI8PBJI zm6Eyw6S$h=AmWQXcI-t*&o5W@-TmP0PszintEbcDZ+VYgPm%Uu2E_M0G)n^{v{+eL zV;J)=hm79Tz`!8YH$(Av$ED=L($bzSu=F+*XX!RqH&*C+((himW42lO`8h2e5z|eI zw(IjfQSteT^jxhrerJSpm+N-G9JawwQX4?R5i~k1Kfigd8$?+}fC#z8d|<>&wz0M9o8K4b>jrkyx4|{7(2OwJO{%0DqPaV?fxZ)RH?cRowrIb5srg5vm--k!p zDJUqkT}&jeTz47eaO;b3i@N@sEp7R>vvXjfTfOfUqDlM><=+&uua~yN1SHBkd9$Um z*^+M-&Pr~)+`L?_8gV{U;Mo{Dwkb;R{nhZi0&#@KTe{a54+UT z&~neirSW{xF_yX2IkC@TpI2ZapoP)t{7&0%G6RjbkM3X1E*>3*f0`HhgN*x4@n0@E zc{$N>S&pRh=EOv%&%^TMPOLLct1Lv;2+fMeRK!Zub1VhJ*H#xyMQE2<`Tcagus8zo z%7+i@Ioy9qlXI;geT3QR8YR8MMw0z`h%4FKG?J84LHM zM1FT}3>EP)rMpE$Y+_t(3%R(u7n{hPZ-3|`??fiJYq#6B+d`0JpLAYTAuOngtB1?g z(<4Yg;$rNR=!-77pY7=MjpsK2E1?4QW5CI9-ZP#{zZ2>^-z5Cp5mFUY@tfisq z;QRgtsp8;%5dCYy)>o~b8g2Zz1nftVd$`3{)VtI+0jvH7OOM`{*jqLP$kRVkE$_r; zyK6?qy-t7q-fJQALte{;u?rWyFNUaiKQUvct1S00ow7`FV9AxqwR{!u>hruVjjo-+ zjLkxOo|v;|z|Sqt$#+}+uhC>P=<7s7gXrk#hXjeZyiH5=n3|P(vBGP@@3+3Rh>VGi zO0gd;JW9uVIxH*hn1+KzivvWQH^1ChA8lkMpM$2^##%FV54FJ}6RR_4G{q`Qc2a-m zN?R)zq^}(5uedpVTYD|8&{H)>~XaK@9 zQ#JFx%HgO^-06A=?2=NwLOnWal$F$P=joDKvDZF|MAf~V8}+)gw8u#2O?a1itDM^6 zn%b~0N@P*C46`4CF-N3}RJJdv`beQ8q2v|y7?j}GGwxn|4nB8M zZoNBo_si`~y+y$=>~PUbww@3sz6+xo=z(prOPG9W0v=YSZ&$D z&=(sM|2Uw=;!k@x+?o4BjIM@NR}+7nmh9eW&fwoKP<%IAy&)PF+!5FDzRd2aemfYt zb*SadLXoEliYRWHRH~{Dtq@(-Q6+g=H4bynruXVJiF_7o5^oB;OyYUQF5A83sQmGt zOtUyYLZUbLGE~RlJlh(bhKFBSw*$odM*}MZ%f=glMz|Dv4VC2Ni2cX=05SO}avygw zn}YMaKOK2MxJ*9h`KT-SP%(wgd}cBrro@Rkum4fxAx`#X>zme{q-6_FGM0BE@8I|g zVflU)=q|%XmUO%(duuGFHmWvj-TpS0s>B=y54i$<>Y?R_>_PH5F*f@#x&jmW;E@R? z31qT4o4uwW{p-{E#zg78n-`E7l*XuP797+BA!VGiy56*)Qt1^+%!Mlt#d^hQRfJS- zt{P*pm`7^-)c!QHd47!Tm2X`&o$mtJg*4Szz0lW_ zufh0a_vf|gF6&+_xuo>qfvvL{s;aNO-ZtOsIoP8?RkF)2y#Ki=a|UdNGD~txG~qw3 z6PM>PL4^Ex=)E2pK(vm#I(rLWc@Qr@=45KG4xz_${}Ys~fSF6k&&`JS2g8I+sun+X zsSIwY&8Qgst({P=zkGLE0K;_7zxENELZi;NmqgU@M z?5$(mC}$r*UeXFIr_sOwGQHh+pnyV4@ZMNwI%EXqZiTbJp^dJB)&LG3!0M3A z@Es?EQ`cwmEtZd;jJdyBv zPIwlpL>iWXVHd3N*3D1;(5Q_SKVNGer!c87GB-hxG@~5yAjn5cR=n_O8nz_oSB^?M zTpNyGobS#~ogHMaykK})44ggqwoJ|Z&;0lp#0jwXBdM_s#$TeLJv9O`D9$*h86dX` z#FUUh9PiVF+%#POH6v^nAe6}HXA@=kPH0@ve~^&Jhc%Bii?kzXfS?H+dd>pB(AMDv=%=FzEO`$8ynpS1eQND+7%|54LY$@2 znASH4?a4MY3n&?Abt2*R$}>5xfsNwFtohtJmzsU#I;`Drt2=$AF|TBon-W^ z3=+&Eg?uj|d#Z69seMD>WMS;+{K!%?hz`{G)Q2?c-B8u+#9+KxpObMBL zo_IclGgKk3543cXy?P+&s;jc7 zkR&URy_SFRluFhWT+W*unIg`}t2gQR)rpdBU((Z0cqUM4@r(i11I$LI(YA%Uf+tz5 zD!&+O!?xjWi@@iPB9+(Rjkypd34#zow@MrmzwGNR;3xCaz;ZR;-(vDVFS?#Do*$w` zt(gGvLQDA`^6I@Qq@82f!D*Vd%pd$6?Ac3~rE>6;dW1dE zJkCP$lA3VhIx$U3G=A~nK7^PM zv%)mV#XHi2m&r(LC|TfZJp|cAWWpH?>khVMJSjdV2i$3yJ1%D&G06M!Jx5B^{W&$P zoZOLz$1bXAs*;cW1Ovq;>ZvamrCiv{P3!#DlR}#DI9!f|>}NdJwAHd7;0XDHt=#4E z#hi6>lV%d{k|SfbWexAZcj1Bo{r&9R%;HfNFv9S%<(+P&VC5-MxdSyRoWSAvo;t#T5HHv`hq-nA89is%JAh!H$U_ZcL^9gpC z`8AD08$lEZXAtTk@XtU7k48h0IGwKT~ffaHctebhN5O=Cz+(pgpeVe=8p2%m}3 z!gH7{QI=&`8ReIQ5EUk98pKvs8wd%(&{li49+mezvS!J1gw(+-qH_w5?T1lbInhCI zvD~gVOnwYrmjF?-yLrqt#Z$~>7nmWHf%7zC7kK-4?>?CuH&l>cJz(CnUiqBqpkO`|*2rHulSxFN7XQ zbrZyb7|)-xw-*4$lKapnM??FdvjhXPjs@{xA+^LU!-!&oOG^9m2&XM7g%KRBH=r>~sALcz*cSL- z@@w{rEOfqZXzl7mVHxadLO2bBi&Y%x2tyTeq-qjPjsv9G&pd*-E-U^sznpE-mM|FOXd#rm?XBlWv zQ7kT#Y-g?JG|h1;Trar$r2f{XeJX0&B>?FOR9dFppyB`x?xo&8IGpU!;`Qv7Jf-L6 z-x_Jij-^GMu1Uk5z&%zLQRG+08pl!ZA8`9$1P945r8hvy+AO72!f7)|O!7kxtWahn z+#QP-nkQ#%12Z`b+K3ye3CAXe5Y-EC`@E?6n(TtO1&)(D*fQu1wh`bi6H+KU zQ^dj~!wDL4ImHVvL(S+e*nu@i--6+}0RPESVd_3El3BKt3(c zGY*2U68KKM3SeZVWf`fud*nU#S~3+o0l{jrch%?-3RQyDm%UY&dBTYHPFoNZZ?JNa z;w)1>9J|xoSJxv{0UI)9l)&|;M#WpgQQePet92Zjq0`VQ$FN7#!i24ore<^p69b(u zS8^}7HKMCR*V((Lg$A3P?JCvWLg!2@b$zCHtRA}RW)a6vZIRe^BpeBQy+u;8I~~f~ zz0w{;w{nS;GxHgl@Ey^I>qJ-M9bGZihGoQ8BOu0YalijSF?B5}N!l3LS&HhGP9nKn z#L%DuiF zU~Rx_eTt;d!$(oIZP(#xdf{f--Qz-9-lDG5t43}@MpYV87ZO@z*$g$@M0ekvyq2Xr z|H>9dp4^{FmaD6bsRr{f$S`C_RK?@3p3JmbI2AN4`7ODBJX11rLsZ5fQ+Qy|Wu+_- zbIoz&m9heZ+HhqdKEV+Fx$BEU^V1l`ZhiMFw{D$*YHKV01n}!AlhRRMC+HL+c>|O4 zxkSWek-|9^)%xm22gDK(XPup~5EHCu%-&a81ugSn8?!v6sdJf)ygy}F>!Pn&(mpV& ziY%nJN?L7bGdzkY1klPLJSO6nGh9s$t;XTlQ7((C3kNN7m}#E@3JJtbg#t7*0IY3z z<%%`nSFNnv&CR(eTa`>rIe?a+#eN|UXt^G=oeKqP`Fd}T`=Dv-o`7=2f3X0=7V$91 zJ`Kb{L2vv2Ece3R+as%!XM%E1_$X*YkIHXlgs$r24=8I-Z~4-Dx2+0GT&GWDTl=!lM81df@{z0noOvNS&4jZVQ;(hR!+= zyj>g-?}W1#)b(yYAAb1yZD1cmq>1C8Cy8j`&d`Dp6#myYIj812z3=Ivq42JD8zWBY zB!aFxO!k*NtpzFxpuVzC(pFU^#GszMd+j{)xK}$TVg$Q+0)t)pba>FJo6u^)!p$#5 z*53ZL(hQ!`3&^+t;1d%QQ^IotTqZ6iMxx#oi(RrZ2Z2aXc_u}i9SBK!m=fLi*E;#^ zgT`r#{nve{hs*dbF&_F0dw4Y@zzEHdE|I6OdoKYpFoQ<_p$o8)GPU;(zbNEG7pN*DNp6RW>t}l`WNW#=Ls?>TLO6rLbj|!=f(!QTlPt? z%vS$?vAM7a^kU}#jRZI`f=sI?a)6%(g1BT;G1xGoZ_Zfa#qsCMOrs^pW;UIJ`6ijc; zKRW!jnSXs--sa1Eh-TB|T3g0}UWGLx7|1qaIL?T>`mI6#inp`uvmFDS9*Ll!U@P?J zyr!G*?m*cYv;spu^V88iRhF#B0HMO+XDJ;3Jfe0V7=d?!f9DBs)WFdS)e>6x@?{zt zQNR;&4hU{Qa*T=jD>a~pqO+guh`@d;01Y20G$tg+-KF3B{bd5kqK~LTe6ba=f(#0K zzB{Dh)El1P{0+Q6Z{SR!zE1rF3Z7(r9F3mH0sG>Jt5kU>T=mTg@L}k(LSG-DOnLzf zQLcr>iZlIdOMOoz=kh8lDhj=y03tV_ViaPgfSx%l1N2dVRpaoxn1S>Tb=G15-!cP8 zne#xPboknFkc!gzQlR4opE^aeVMNmg_Yqhobgx_?HZ%n0L^|d#05D~S|8;oyw;FzY z5Uhd5h1X`6v<)CbN{oaKcjN@RjM?tN=sRKFyT{PLfKlr74d{d%KXC#N1Lq?myq3kx zhYm>o?7ZKC0eDD@5A7zKj06TN5F1oz z{1DA`3;%EYj4Uh!j;vo%%MrL`qzdj}v$>k*y=Rc*5|C8gILtTqes6Z6?;DtjIlKmk z)E@Aq-MP@UbcN1)DhJYsQ^pZnxdZ<%F%6e1)E87IT7X6g1)Lo6H)#WR$EMc7xQ(E# zl>N8a$-WMDCK#3HySlqNJ43Bl5!n-PJhb3XKp>~|fDbMIlDOa6coblmTAeFrp+}-- zZ=Z`+-`DtG*Id=@Iq*LK=AV+{`sU_l*0L<%?!~;nye|>G0oaWMyU#0S5bvg;*+dk~ zLF)w}BY^DYsTugU7w-;@I1#dD@EJ@8bs1=Awm!Z#2|ShZTr`Lw7IDJZJywrpCn^|n zM)xcC7Tom`00AS+A|l%Wg|EXc7_dP`dIBFEHux+#LPH$b(a|W;ExHRKF476L640Q5c&o68f)`mUp^Wf(j_8tgP1HZs}dV zOzJ-82@Fnv%58ieK~;S6tO>aE5-`kwtO~CMQA0$U2A=pM*nj^Z(6KcQ{JVv4Oo&QFu(+ZBaH-_~y;SMX zKpGNowB&Hee*CaxB?dx}gh!8(_+^m0{nuwl*|60h{_ildH$VP?NqI2&xj(0F0a2a*e``(*DbU z(Mf*U@-GcM*e4$D@~xjhw1&{sg<}ii0~A)3#$6&QkmOa5#fDR`SOd>fLpoH?`Ak2ikbf$p${QNn*ur*$chf`Wpp{Tjd&tg6S*w_Id|M*)x$Vw5xWdJB~qWR?HD z(tWi9|L0)-#{_Cm*JsvXo`nC*GtCZ!i|80ho`)%6cA6x@WIL#HC* z1QxFb4n)d?njT}r-jB{2pu&{PJ9%iFu+BQ52@aHd;E-V`s#%m0j3O_%dRIS@R@3Y% zfGw=oPyMC7B)_4W6L=ZGAFVKAk?`!a`5B{D>UIx3Vq}R4Pe`Az><(HVh0h_&eXwQ z3sl!Z(BIbdU6@DM*vvTK01T^9y`M0|4tDyFR8^1@k6T3WM-iqG* zaYmp=0Ry#vR&JqnVbcnrUSMpmdwWm&)zdLCg~OCgm~grL|3ZePM6{Krz-dgY48(zm z@6;O{IKA>tXaMvbhE7S3fG-NJgY=(NJ`DtP5QCVGx+waemmLlL z|BZuf^P{85(bfT$q}LaSTv0p*8u4f1Yi=N0;OaX<*8}&_VbehtdcdKfIzaDxL(R_&?onVU`P57$JLWi zVo&{N{jL}p;ec;T;)&NTFx}1O7Zi!V{Lg`0a)sC*fJF!*gW-Yt82k$OYcv4zP*6bj z20DTeCQSRt9{Kqcvp+2bU?vn%J3Hr-F@ZC;`R5m;Z~d@EFs%qH3oh z|6Q)9L@nb@;+?_8!4X!-&arvwC4ogp%I1hu(n^bO*rC+Ovx7fr8n!=(PlMA4C}kzX z4|n30;MJlw(CErsmW7ZJk^KV}dUB=gKWCjHKQFHdaE7h+3-I48%A{@W?UBOescC7k z5ZQ?S%+{F)!Q-aDzr%qvey7~@!weI&<*{cSf^Io1reh$D#R%q8o(D@Y9zG&`wsFI z(2tFU;UFvUd7MUIi~jR=6pDYpT`Gm?6^J@#VQDy4FaC4JRzH06K`h4LO+7xB5driF zk-91P`#|&!^tZ>Oy}Nf|PzS1Q~B9f?f<+$$NUn-ya(f19BWLnE`G(sN;kIDgFPl22=yp zH8G)p$uDREK~Q~|eF`~F&Xc#M=Gw@)fZ0p;o&Kf1_t6| z9PxXV|8PjO9vEF8|MPi4`LiuqSL}%-{w8*DuhA*#nS;^%3kl2SE*|GUH3EYrK!*u1 z28Q9eP9>jRp8%C4%pnB36x9;LdkY@`HSFNbVOZULPm91=5-;hi;8_dQd(_v3EO=2jrDW(?vcSm&0P?C9tn5(>_sc7qtSkC)K@`OmkB8QpD(f`Jia z4^N%H7^Wa&G$Ej+YZrK+R$?(Xek=si%Oi(DvlS(tOaT7So73AO+L>1foR^eGjaNU~ zY|&t&8A)aMN0<&4^-{3S?DTg=mvuy6c~6jDCQ6u5+(_U%AXA?{+f*c#9u(1?5P%e# z0rxz;>*)8`-E8J8LGSs+*D{+Pb06op%u>lRsRBs>z5A3>et0A*(+m$gSSNaQE3%gE zB<)L0Tm`0&nXHeQ=fkX`*MINarD0#-l@1p!Zvf%v#7B?L85-K!+J+I;!jM@z^vl@) zn&;=E$Y2NZ9bCrW6$j2eot9g%r$g&qmZ^SHr>jH~R=9I|y6m5u)ZWr3xzbg3LcgS^ z*?5@6^77t7fBuT%0X1b4arZ|9s-JQg-_Y{qE?X)p)!@2)T)EI&->RXyu=U2CuRD}@ z3O>0W7n(SBp|Qda7xW+ah+5w{@nk=OdS&i^Ct; zWNVslou%P~byW#(IMgSUd;_^78yiEjPSNR&SwlED*lMs#cv4;|{A%Wh<%8;hW4fzE zsmV&Qr|#@t&@x-k!_Yl$a@7wcWy|`caAn)09{+Nyy7oY3{#P@iro1CF%j9I$W}{E9 zbyTuX_Y;|(J+P5X4x;mB^vhF9Jjpw{MB|+!tW;sBoC^P;!j)b~Z9XhwsSawhMZnMi zHHy5fs(<|OeqTn}>L}|=A+PAWWFUXAx5;|;&dsqwzP*K_p-DIs3U_pGh(0S!;XI;w zzxyZ4V8#p^DM1Q3xp3KFzFo*my9VF#rwS24CUOkVNZwEreoIeiUJ6cleT9Ll#p0Us z$Ojub-q25+`C)l=%}aXBff*zug$#6(@nF>Tq-{v2E7UW`uM1=ru9F(v3?`2c4C9}s zF|sM#kGNhje^EuYZc-t%<=0WnAfbcQu7mXO&R%d``C3@b=&=wjjZS)6n@6+`M6<3A z_!BY(Vdj46dqCa}A76Du(drSnYk~;z%!{i(y9qN>P_{Oi-IxeRnhh{wqwT)jAEf#H zY4f<`=+n*qrhr)H{bVIk7Sj1Wg4&)iUusEPsa!0PL!JKiOhJmFSwX9!s2NN1=b=j9 z&|x#)(Bb7vv?YSP=iHBOdtKq_#|BU6sSaL7@%d7=4_@MJLd}W&psGRPkm@GVtM&b& z)0+oJaFwNWSgN*Fvm#BlcgDxIQ&##6I9Gm|6yXQowf&(!b!G80E9y6Jq^FWqyO!zsWv?JAV z)88#}wvBHds98??Pj8pr&A1Zth=B^1w|jWrF?zwxgxb)H*(Fb`4{5{r!ut{p3x4gXk%F5nhphwvQsx#%hI^|HuN>pp>a z3hy4TyWIrOR({=X)3D*2(|M z49aE?X5c;N_I&uj!nfircf)hl3yXH!Jw-9qUWvStd>8|NLe1rt@rRZBQ_sEQ4{n_3 z_ZE1s9hJ~~N^!0z%RyM8d2RR?V08ekMV28Nv`QR+4=638H{r&Mk(g@0)mfkG3 z_wO&LUwNk+!<8O4DMm+GmS^JmCnz8KPyNdlQEL_Lia`^G)vv0tzprL!Rs23C(>AQ_ zccJY1I~h7(DwJDX{Mr}HAQBwnOwgXX-*km#-_GMQ_L*hPV|L!7{nmb!gG0A`GoO7@ zbdeJk&HT8U@tV`&VehH_z$2`y79szvDo!?T;D$ZMy|lBjuK(TE)bw+rt4(wakzeq> zu|5&Q4~?XJTk?_8)-KoPV@cLx3agvnH`Ux9i~Bs%o=;yk&9~{)6E*mr_9X~#3)Z^$ zTy=-QoZ6KqyE_csJCaQ{rE`_RDu(#sI)O*^@e{rzBrx;y3hOI39%s{|bb1+D<2(K2 z^0ZNGu=0z>>q;#9^Wpv3e3a4mMP-std;hbHqxxXE^4eYe*G8DJ*L(l957Nu&9v2*_;y!uc{b?gIv=xh4<7d>xHZ4O>^8z=X&DofB}Px& z{vJ2Ia()ThAnRG<{&=VPB!N!Gfqy5P7k$~R-OngnpfEunM)*ecwEa#jXCd=(uU&`j z^Co*%x>FYp0-{wyPNtX%)8Pg2?w$6&XS$Ea-0nj7L1BM~uUQ}~Ffl9`enr*GP#o*5 zhz`(b!T`yNuylfnJ6u#Sa-#A&EeS?!f3f`UKUU`*Iqvt{A>q5QwC)l!u3F=LbW*}2 zo}=l*Zx2O7vbiphX4YKE%ru_%d=xwNeaD0)`oU5U(70;a>Gn`bgWmv zQIF}I#OgJ%&RSfYGWu>iBu)mq4quFIEtM)_ti0&^ZR|vRbyOEnxZiiCKRnQHHJ6@% zzY?Dyhd*YO-{wNhN4vPZb~=2SS;i4_drOP(V8?rkO`H#pw|-z?K8zWb1Ss(s4R){c zj9NG~xtSW4RVpsDa+ELo z%AsY{RK|>TQts7{D8&lEn!gM05P!faf95Fu-Z9}6Ey@+4(>xkYJA7;pA26lAIy`fF zNrw7@C53}Z=HbD{RErEJtZt^pSZ$c@Kf&#d%a#AsqDWCa7Vv2mh9w{= zIO19jf?wnQ%Y`6N%mYd-kYkBLJ}qQYMG4Ibhe8JcHiL4+Lji4PKRK9w0{IHlI~#97 zz$6?ZPr$u<0$KT7?LxZBxpU38+_;&ThNk~Y`Hq2X*FAHG>M=w$h9Uq`&MBW}B9@Aq z77zHWK>8+j%>j@>3tO9x%TwW1%r1{SZz&Qrayd0Wvn4XoVcQunr@Fo*XZpsg$Qu&nFW2b;Z-+adgUQgNuv8DeR+FL%+*~I-$MY0)t=oKzS@hTqUEddyA7kEKof?C z0m5!FUe%mx;9+5Y-3{V3z-)kvibA5*Xl522MiO0Aek#0Am<=eo58R3 zICZ!uM>vpW^r0D^h~{Ijc2WvrRgInLlDKMW$Gr7*q42|9ldW#>CMaGTT5q=Eq{|Px zrD8ZPru_DqEn6w)2up8jm29BMsZ;IHYmI@DHG+KX01HZTKy1%~3ba|#APn@ekSIs> zgdg;EuCDt+(M%2M3DEJw!=R$^Bplr7O+*cS_V*WtXD?plq!*fm)WlhR3^r=`;?*BNA;4WBr>F)otvUU0Ze zMBR0=;TrU??mu~Q9D{=aAL+UYXeOybOD(jW`}T?$o)VNe%ld|g1_yCa`lI9I6b3%^ zu|=u6qI-xE9=3}dV+}R5Sodluz~djX6I*x~xnb24>*w)4^aK)tEbMB7P7mOto-j$lWNq3FB4Wbs3w# zZ>4_!uB^@mc7P*grc(lM4Lt2w8^+6UpgdsR{mAg<;sZ9{F3X$#-v!>gaT1Fq~Ezs^<)DG*bo~5`*TqA0YgksvHhiXjCC z@lv5m1ne~$P-|`nrWp5e(5I|{dt_p0W3#ZdkX=$jiwQX$GUmTqlv$f$;_wR?CiyRu9*GUkRX= z%5O!2Z_qfgvJ2Y$qGh5UT8VD?`{kHoGmu8bKn3z+xD22WbWA`U#kJ z2toWEz_rp2bAram)GG=)*2R*(fSU5EFD{2`1z;YsUV}hc2DHV`A5M8e*~YTW>1&r$QIxJCvwUi zAX?wX=bTFK_0lVg`OS7xA1mu%d8C(Xp$Ge=uJpm+kL^<$^vuG>gc#KIW0!A)M}`vL z9He+hkV?^=^=6WhHvw{Bh(6{2SsK1|c44WmsCxOAS@Y++?rBhV0}hE;>TVkOUqI#M z=crxC0Jib*S~Znx`Q5*NO4@GCI+^?IUj<&MS!>BV-6=HftqO_Al^;(<&|~szIG2?N|OyobJ|FAZ^-#P49pk7 z91Hm_s)QI6-1=im(McJ3BOX ziL^?f&LHI2aQ4bWUF=QG!*a8LA!ON3R>)_X9ClM>oBB90L~0)RH12akb`QP_f8xBwG{x}602ip z9`IGx%y3Ubp%jG`pfdr`1cc6^WndV{|K6wXwy{a-xcXh$0mUpv1z{f1H|>F(9X?-2 z{6927BwJ2gu*f|WC5Kr$Gqt&(YiMYQ6u}Tn7O+_Zt8I^s|Juqh0o#2SJRVd5XaOY}mVF!(G&^gJzO&$JG17et1+W$> z^1~@^LSj!>&2K&L3lIj$4m2koeed1|ViSY*TN~;sq7VzYJx_Qr`5*6(BK6o3s4ZRz zNXLu)J8o=z3UdhHg0`5b+o%KrMTCckABtkZt0Q*8=2c+Fz~?1IKO0co%qV7q{-ZZl9!gdU|y85re{SAGrTwawS6g8v?@I4D9} z3ief+z2Pp1eU3B+Dx%AW77-0c1LDXN{xBQ5$y7x-{iCZYU7)I@j4K&~nsCn_E)@a` zxJnRVWP|=F5Z%$ZgUDm~oBca!Jv~PUkulYH9CT0Lc4hbA*P24r%gr@{o$WL2)otCe ze1!DM6cxQvJk$L1Wrn9HZ?=z~d*N)pbykaWvY`PFhpV=Nxx(Vbk0jSD^0h>1l^{3eq_M7zR?(3_bgJ zZ9-`KD~MGRX8LE88JGOB6D{>OG-LvK*)Y^iMd&hsfIt|H5Lrr^w=VnV`Xl5A6!>i& z9Bi6Hh;V8-KwbbGDoi5g4LF2vfCiB&wCX_SH4Z3>IFVj3jPiOyV4S$B0Lq0=q&>I* z>cj;>9ZVA+YI}jV5CszkqPIws3TDJLUJhgM;>$pkuaUHiHXL1Pgs=buKMih>^V8p-5`&xfyOoN=?^_!e5ns+1d;U*F$36FJX4omLSiR%V zwgUw-543wy+6-M?U8vpa1)WjzVK39y{!ADk+0!#HNEAn7$>>lcR3N5l`_1<2yC&zU z1+FN;tEaKOEvH4Bf zXC&?aT@#0MPsq%2PcZe5ps`IrT1H5+5BjdJiCKWGfjH>dhME6$(9Xi-e|=^LlC|Ja zVYfA;dk_u`GYx<(@ZG8zW0jv>L38y4>i?l0eT3CCz%AIT=5Ob}eAx`LHY5#qu3ck8 z%`Hn1s)JP{fvI}QXUKCjvgM7PRZ{(JGC@+ z(m>rC<2ln3ZeFbjYm~^bn=h@BmkUnfeV1_lE6G$Evv77wgj;u9ws(6HXuE| zeyxrI(=RYv$omrR;@S06R$;w_32qGQ>Zb$vR1=*JFF=9~3oT|;Ip@^$HK7I+D)w{1&0r;soqQm1>C2+B&!RAW85-RgmV>S38ZE+}jA412jSCLWe= z`WE%34SJ}8`&bU*6L;7!7YEur?rt8zAdbk(Uk_lz+7LjsvN(VWgZh+TzJ8qrw|*4h zCKA(se=--yrRhM+vDLnumpA=-&moDiB z+>!zAHhe$SgW_;)G7h=%VL0*FCYmfEYq`(Q1Fq3 zgy~S<9UxSi^|3`oA}Cw}UwIQ1M+T;DEpRe2G0kXM{LvrX0?JM@OcNxvvlE+|C;CQ4 zaBwG!orX)D-vd&0yY4Y}3{3i;ZQuUp1Vl_vKspR^*yy9`ag_dn1Y(JseHr^j;rC}v z3!+?)i1Mbu_=iGN`*AYzdu-tUO7IQ)1X3CVR1p9e6H@6S6jXQ5oi2}|*HRq|*hn-#(8axcd z{}a!?W$BUvA=!DrMP7Mjt_GkmA|(#p_y%_wiOE7VsVUu)(`-@1<~bJh zGRJXI3R@?(b2SKeJofjT=8mdHd5nt6x!S&NIQp- zyctxcVaNdSg!cCK1_5l`1{C@>wxA*u3faL{-2@a05Vtkl;C5)MJp38}c+Pi-9p%p- z|1f3VJNv&E@`{SyL3S2@YxC<2ki>EK|Bw!$#Rs-i0*osNiMqM<&Un6Fu;GF8E?%f0 zZy2!|vx_%ZvoB)Me1L9|s zH)p9aKw*OFQUDu$;Zt9K_pd*~zQV1%x%Bb{al`jX>n*6eA^lB+5j~cPjq=^02I=q-6N_u}kTRQ@^`! ze1S1h0Z!`3j~yK_5%tI$Hllxd>s?Ykq^SL8S%i!d$_l}mF~2Q!)KY4*Vf!TJyp`>F@l%R0|4goCjg>p87~}}+EKe> zZen6Gdh-vU$l3K@P4@R=t6e{15uxC!U%ils$YYDYOIPQCm~D0$YBoHpZ{oQX(|>Jl zSMCAb;6S(5i`v?2?oeOTc`AN>bk*-^Qqr-juZ(zs-Q810Kth#cI)eFSj>B4FXr{7kQXd*l;v!Ud$oIA#^mefH@!HkA@pJ#VKM{XhU1le= zh@(yM3)~&pFnzHohJ+KE1Lk!g@`2a>@pZ){s=b2Nw%I6I=Eo)14Y2x8P+M4~SC=gJ zab_FAL*I|@7ql7sbO(3&sqeZgh33=V?`fe$`-NraH4dTwZYti(n2;y*sl+jaIw}2I z4z|u$)Qf_ZUS`O4_7oMdX^0V@Ao<1HT zs?4wX!Kb?fJ}BVROuC24oo=N#?2prJeMoGYGP%f6@2sS0X_SOtx& zw@@Dy_feIOmloRCwr6lKxu~jb>6aBj#Lw=%vS*^K`b`YvZY4+~2z4a#*DjX1;XiuI zZqMTES+dNR&6i7f*6FlYcAu(^uC@F9h=bJk?(Yr*C`TW%l%`r{28U#A2@-zIGQu^H zUe6oBmL8_6iC3;N?z|XoQyjf$x|X;;LiCl{>B;41yeWm-QF+{GG0h_5O4_E_weO5r zE3-7EVyWOKMzVMd-aKCcrMKXwru0hX3X za{~Xyf=f+-QppxaA1jLleaEO)8hssR?frn~rQoItQ!4fYRoXtx;kyx@BLE7xwr>Ii z!FhGO1*|XJ-}_7^^s(}0k&AX$=VQ*34sBhsD~&Myq;w3OkZhBf6GNVw85K`!dflIKq^9euiAnJ@O!PR#NJxtP&s?DC2Hxj5*nNs4!|bI9|?o2Cl+*tuc)K3}WZ z$2dn;)>3yXMQ2H`&&Os4gX_s93>Y1cZ;Kk|m|VWBGM(~QkB_qY6g}7`pJYa6#_V2m%Sy&(~s(Yv987R6=o{9@;md3{5I&k zUCsIAL5`JkQ4?n^hfXXmA`S&DR$uR3xHFz>%q>OC=go;f;B6>4KITp6GS-)8rfqb&$k3zNT7hykd}6&Ob-k^RIbyivbiaOr2I%ol<|hflmNuU; zeK>o~OfjB~aEt6WS_-#S=zkf#jTyTxaj}E$_}5-tRf&)27S;tPhtMB5Ue+jz5Ftw; zzW6JTZ>_>K_|7qpHAmY`_29r8Pj+6J`Tk`P5AxCpmis}NyWsSsjd}iXmsOoK$V^us z)Qmgv2VUGc8YB?3aSb0@#{I6r`qfH!og_H%{L}QiY47MOsbI>1!E?!3ei{C-gUgV* zWu_0esAdg|zbNo68b3)+d#}K3)?zivxccGvQm)4Xlc75P56`+ubr-JMln?%9V4@bN zHFWEj+axskbm+S2%wBZkqRW@|=zY`Zsqms4h0YjE8%&(M^d6RgU-Ya=Q}g3m)z%M* zN-h_+u%9?|8=E6UqPj_W2z3`@{t}lPUNh6E!f2htE!v~UI8N|N#G%+n)AXAJtl7|P zXBFNZY>ixFt#Eh+Y$*WM@Uo-#2N)quI zE7Ru^y0Ytj(YNz>D`Kc;ZT)zfwNf?F3*En1Os;CfyVXZJQL>FuN)na1+%Dt&TjG4Z zj0NYNhXmZnFR;>=xF|g};dkm($lv8=#{Z}NZx<)c*Txjd?Jg!u9i9& z|Cneuzi9Uf-9>}%n;iHdT?9^)8|MwYtAzRb*l$-52LCG2?8RT&)?d*#OEihce-ZR< zikvQ1>F`l>Cv~ySpL(B%R45q`InJ5pOIc=V4N(ilD9F4cz9y-ef=^$_%QRh0Xc+5u z8K0W!c*hmVszP$Sa2?`b{~Vd4X>`l8m6FH%m^B;RsWg1f4~f@dASV7z{ivjT!9^_FvNRh1#QDsNbjSPVi}b7u1{3k|*UOlM>0(6= zpA5S?qe@@RpZCCf(uhi#H|S0zj^BHzE1&7ryo?N2d*M57Ju+htqio^heH?_w)_C>2 zHfGLe=sN-gugP`4bqW3_(Y(SSVJ%E;<7Kr?m~;wj^$0U2!84qm`mxIk!&R@jV*>e@^F!0SMzFBpL>?bwj`c@ zM&6wqdh%&Ox?v`B?8Nwz^2EqjIYaMZ&Bd>>gx)Lo?w@Knz3}xiPoM1LispB;39goY z_Mq}U*Fx2Ct<2u2k#cfl8Ii-eEEsmv=l3X7eIgCW+~pX)4>TAihj$FMr4H5F{5L10 zw$64E+kWG)kJNukzZi`loaaoocJIPYPAQ=q-|sX1t91j`!)8S)kId%Zon(Qv?n?iP za}+|4xyby9O(WyyX2f7@`P;fP-K7L)N;8Gpd8bQXesOZeHO>FCkT?AajFJ z<^MC!+Kmg2iU+>0W;>fFJ>j{?#wFECKj%FUFkO1{tRXlv2=cmK@R%R*`pv|G*K(_w zvMlE5%+7i{BR6>cS|gUPawo2_&M`Z%lF={rz{$L9_udZ97M{)t3)cy1OG+Cwtn&b- zk-gfhroHtOZ?Fz~c4aSnO=D4`}`sOq$=O15ur|EyOs$AmX+{QgQ& zuxDyv#8X+@(=804`zBAB(LYr%_2o&Hs3tTomSl18kV4zbWn_8M^f!wi?2tDl*DFq%DrBGH*eOhT@xb;CY4of|6g

dDdcXeXb7wSBqnxnG*{#;wJg0z>JSrW@vmcH4>39PIjV_Pr8QawT!T27Sl znXkYj>2Sg)Rxf9nzg*dJ&a0oUuj70XwP?*juP;oUpICiYq!gV0xz42a!>(Uhk~+WU z$-h&5DLH@sv*O67!oYGVXKD3Kw_QKOBwbHT(0nSpSEg)DQEk?uJEGNZFI^5lQ~vUe z+-zV03rb-fZL!}UXy-5}25K&)8DP_cPQ#W$f6qnwOS>4}KJXCr+lPnY1f5CWP80vR(RpRx%CAL{s8B09BW ztK3wBC0f-SvpZGPF6dfn2|wjt#k25ujmmU;hP~4rk39b#B$oJctz Jmvv4FO#r}H5Pkpv literal 0 HcmV?d00001 diff --git a/pyproject.toml b/pyproject.toml index b09e2d28e..338339c31 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,6 +30,7 @@ dynamic = ["version"] [project.optional-dependencies] test = ["pytest"] code_style = ["isort", "black", "flake8"] +graph_generation = ["pygraphviz", "networkx"] [project.scripts] pyspdxtools = "spdx.clitools.pyspdxtools:main" diff --git a/src/spdx/clitools/pyspdxtools.py b/src/spdx/clitools/pyspdxtools.py index e5ee38166..e2461767d 100644 --- a/src/spdx/clitools/pyspdxtools.py +++ b/src/spdx/clitools/pyspdxtools.py @@ -18,6 +18,7 @@ import click +from spdx.graph_generation import export_graph_from_document from spdx.model.document import Document from spdx.parser.error import SPDXParsingError from spdx.parser.parse_anything import parse_file @@ -32,7 +33,8 @@ @click.option( "--outfile", "-o", - help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion).", + help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion). " + "If you add the option --graph to the command the generated graph will be written to this file.", ) @click.option( "--version", @@ -41,7 +43,15 @@ default=None, ) @click.option("--novalidation", is_flag=True, help="Don't validate the provided document.") -def main(infile: str, outfile: str, version: str, novalidation: bool): +@click.option( + "--graph", + is_flag=True, + default=False, + help="Generate a relationship graph from the input file. " + "The generated graph is saved to the file specified with --outfile. " + "Note: You need to install the optional dependencies 'networkx' and 'pygraphviz' for this feature.", +) +def main(infile: str, outfile: str, version: str, novalidation: bool, graph: bool): """ CLI-tool for validating SPDX documents and converting between RDF, TAG-VALUE, JSON, YAML and XML formats. Formats are determined by the file endings. @@ -50,9 +60,6 @@ def main(infile: str, outfile: str, version: str, novalidation: bool): try: document: Document = parse_file(infile) - if outfile == "-": - tagvalue_writer.write_document(document, sys.stdout) - if not novalidation: if not version: version = document.creation_info.spdx_version @@ -72,7 +79,20 @@ def main(infile: str, outfile: str, version: str, novalidation: bool): else: logging.info("The document is valid.") - if outfile and outfile != "-": + if outfile == "-": + tagvalue_writer.write_document(document, sys.stdout) + + elif graph: + try: + export_graph_from_document(document, outfile) + except ImportError: + logging.error( + "To be able to draw a relationship graph of the parsed document " + "you need to install 'networkx' and 'pygraphviz'. Run 'pip install \".[graph_generation]\"'." + ) + sys.exit(1) + + elif outfile: write_file(document, outfile, validate=False) except NotImplementedError as err: diff --git a/src/spdx/document_utils.py b/src/spdx/document_utils.py index 73c603feb..a050ee5a2 100644 --- a/src/spdx/document_utils.py +++ b/src/spdx/document_utils.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Union +from typing import Dict, List, Union from spdx.model.document import Document from spdx.model.file import File @@ -17,9 +17,15 @@ def get_contained_spdx_element_ids(document: Document) -> List[str]: def get_element_from_spdx_id(document: Document, spdx_id: str) -> Union[Package, File, Snippet, None]: - elements = [file_ for file_ in document.files] - elements.extend([package_ for package_ in document.packages]) - elements.extend([snippet_ for snippet_ in document.snippets]) - for element in elements: - if element.spdx_id == spdx_id: - return element + contained_spdx_elements: Dict[str, Union[Package, File, Snippet]] = get_contained_spdx_elements(document) + if spdx_id not in contained_spdx_elements: + return None + return contained_spdx_elements[spdx_id] + + +def get_contained_spdx_elements(document: Document) -> Dict[str, Union[Package, File, Snippet]]: + contained_spdx_elements = {package.spdx_id: package for package in document.packages} + contained_spdx_elements.update({file.spdx_id: file for file in document.files}) + contained_spdx_elements.update({snippet.spdx_id: snippet for snippet in document.snippets}) + + return contained_spdx_elements diff --git a/src/spdx/graph_generation.py b/src/spdx/graph_generation.py new file mode 100644 index 000000000..40d673315 --- /dev/null +++ b/src/spdx/graph_generation.py @@ -0,0 +1,76 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import Dict, List, Union + +from spdx.model.file import File +from spdx.model.package import Package +from spdx.model.snippet import Snippet + +try: + from networkx import DiGraph +except ImportError: + DiGraph = None +from spdx.document_utils import get_contained_spdx_elements +from spdx.model.document import Document +from spdx.model.relationship import Relationship + + +def export_graph_from_document(document: Document, file_name: str) -> None: + from networkx.drawing import nx_agraph + + graph = generate_relationship_graph_from_spdx(document) + _color_nodes(graph) + attributes_graph = nx_agraph.to_agraph(graph) # convert to a pygraphviz graph + attributes_graph.draw(file_name, prog="dot") + + +def generate_relationship_graph_from_spdx(document: Document) -> DiGraph: + from networkx import DiGraph + + graph = DiGraph() + graph.add_node(document.creation_info.spdx_id, element=document.creation_info) + + contained_elements: Dict[str, Union[Package, File, Snippet]] = get_contained_spdx_elements(document) + contained_element_nodes = [(spdx_id, {"element": element}) for spdx_id, element in contained_elements.items()] + graph.add_nodes_from(contained_element_nodes) + + relationships_by_spdx_id: Dict[str, List[Relationship]] = dict() + for relationship in document.relationships: + relationships_by_spdx_id.setdefault(relationship.spdx_element_id, []).append(relationship) + + for spdx_id, relationships in relationships_by_spdx_id.items(): + if spdx_id not in graph.nodes(): + # this will add any external spdx_id to the graph where we have no further information about the element, + # to indicate that this node represents an element we add the attribute "element" + graph.add_node(spdx_id, element=None) + for relationship in relationships: + relationship_node_key = relationship.spdx_element_id + "_" + relationship.relationship_type.name + graph.add_node(relationship_node_key, comment=relationship.comment) + graph.add_edge(relationship.spdx_element_id, relationship_node_key) + # if the related spdx element is SpdxNone or SpdxNoAssertion we need a type conversion + related_spdx_element_id = str(relationship.related_spdx_element_id) + + if related_spdx_element_id not in graph.nodes(): + # this will add any external spdx_id to the graph where we have no further information about + # the element, to indicate that this node represents an element we add the attribute "element" + graph.add_node( + related_spdx_element_id, + element=None, + ) + graph.add_edge(relationship_node_key, related_spdx_element_id) + + return graph + + +def _color_nodes(graph: DiGraph) -> None: + for node in graph.nodes(): + if "_" in node: + # nodes representing a RelationshipType are concatenated with the spdx_element_id, + # to only see the RelationshipType when rendering the graph to a picture we add + # a label to these nodes + graph.add_node(node, color="lightgreen", label=node.split("_", 1)[-1]) + elif node == "SPDXRef-DOCUMENT": + graph.add_node(node, color="indianred2") + else: + graph.add_node(node, color="lightskyblue") diff --git a/tests/spdx/test_document_utils.py b/tests/spdx/test_document_utils.py index 873af1a1a..a81a39bd8 100644 --- a/tests/spdx/test_document_utils.py +++ b/tests/spdx/test_document_utils.py @@ -5,7 +5,7 @@ import pytest -from spdx.document_utils import get_contained_spdx_element_ids, get_element_from_spdx_id +from spdx.document_utils import get_contained_spdx_element_ids, get_contained_spdx_elements, get_element_from_spdx_id from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture, snippet_fixture @@ -26,3 +26,11 @@ def test_get_element_from_spdx_id(variables): assert get_element_from_spdx_id(document, file.spdx_id) == file assert get_element_from_spdx_id(document, snippet.spdx_id) == snippet assert get_element_from_spdx_id(document, "unknown_id") is None + + +def test_get_contained_spdx_elements(variables): + document, package, file, snippet = variables + contained_elements = get_contained_spdx_elements(document) + assert contained_elements[package.spdx_id] == package + assert contained_elements[file.spdx_id] == file + assert contained_elements[snippet.spdx_id] == snippet diff --git a/tests/spdx/test_graph_generation.py b/tests/spdx/test_graph_generation.py new file mode 100644 index 000000000..6c28d1d41 --- /dev/null +++ b/tests/spdx/test_graph_generation.py @@ -0,0 +1,155 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from pathlib import Path +from typing import List +from unittest import TestCase + +import pytest + +from spdx.graph_generation import generate_relationship_graph_from_spdx +from spdx.model.document import Document +from spdx.model.relationship import Relationship, RelationshipType +from spdx.parser.parse_anything import parse_file +from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture + +try: + import networkx # noqa: F401 + import pygraphviz # noqa: F401 +except ImportError: + pytest.skip("Skip this module as the tests need optional dependencies to run.", allow_module_level=True) + + +@pytest.mark.parametrize( + "file_name, nodes_count, edges_count, relationship_node_keys", + [ + ( + "SPDXJSONExample-v2.3.spdx.json", + 22, + 22, + ["SPDXRef-Package_DYNAMIC_LINK", "SPDXRef-JenaLib_CONTAINS"], + ), + ( + "SPDXJSONExample-v2.2.spdx.json", + 20, + 19, + ["SPDXRef-Package_DYNAMIC_LINK", "SPDXRef-JenaLib_CONTAINS"], + ), + ( + "SPDXRdfExample-v2.3.spdx.rdf.xml", + 22, + 22, + ["SPDXRef-Package_DYNAMIC_LINK", "SPDXRef-JenaLib_CONTAINS"], + ), + ( + "SPDXRdfExample-v2.2.spdx.rdf.xml", + 20, + 17, + ["SPDXRef-Package_DYNAMIC_LINK", "SPDXRef-JenaLib_CONTAINS"], + ), + ( + "SPDXTagExample-v2.3.spdx", + 22, + 22, + ["SPDXRef-Package_DYNAMIC_LINK", "SPDXRef-JenaLib_CONTAINS"], + ), + ], +) +def test_generate_graph_from_spdx( + file_name: str, + nodes_count: int, + edges_count: int, + relationship_node_keys: List[str], +) -> None: + document = parse_file(str(Path(__file__).resolve().parent.parent / "spdx" / "data" / "formats" / file_name)) + graph = generate_relationship_graph_from_spdx(document) + + assert document.creation_info.spdx_id in graph.nodes() + assert graph.number_of_nodes() == nodes_count + assert graph.number_of_edges() == edges_count + assert "SPDXRef-DOCUMENT_DESCRIBES" in graph.nodes() + for relationship_node_key in relationship_node_keys: + assert relationship_node_key in graph.nodes() + + +def test_complete_connected_graph() -> None: + document = _create_minimal_document() + + graph = generate_relationship_graph_from_spdx(document) + + TestCase().assertCountEqual( + graph.nodes(), + [ + "SPDXRef-DOCUMENT", + "SPDXRef-Package-A", + "SPDXRef-Package-B", + "SPDXRef-File", + "SPDXRef-DOCUMENT_DESCRIBES", + "SPDXRef-Package-A_CONTAINS", + "SPDXRef-Package-B_CONTAINS", + ], + ) + TestCase().assertCountEqual( + graph.edges(), + [ + ("SPDXRef-DOCUMENT", "SPDXRef-DOCUMENT_DESCRIBES"), + ("SPDXRef-DOCUMENT_DESCRIBES", "SPDXRef-Package-A"), + ("SPDXRef-DOCUMENT_DESCRIBES", "SPDXRef-Package-B"), + ("SPDXRef-Package-A", "SPDXRef-Package-A_CONTAINS"), + ("SPDXRef-Package-A_CONTAINS", "SPDXRef-File"), + ("SPDXRef-Package-B", "SPDXRef-Package-B_CONTAINS"), + ("SPDXRef-Package-B_CONTAINS", "SPDXRef-File"), + ], + ) + + +def test_complete_unconnected_graph() -> None: + document = _create_minimal_document() + document.packages += [package_fixture(spdx_id="SPDXRef-Package-C", name="Package without connection to document")] + + graph = generate_relationship_graph_from_spdx(document) + + TestCase().assertCountEqual( + graph.nodes(), + [ + "SPDXRef-DOCUMENT", + "SPDXRef-Package-A", + "SPDXRef-Package-B", + "SPDXRef-File", + "SPDXRef-DOCUMENT_DESCRIBES", + "SPDXRef-Package-A_CONTAINS", + "SPDXRef-Package-B_CONTAINS", + "SPDXRef-Package-C", + ], + ) + TestCase().assertCountEqual( + graph.edges(), + [ + ("SPDXRef-DOCUMENT", "SPDXRef-DOCUMENT_DESCRIBES"), + ("SPDXRef-DOCUMENT_DESCRIBES", "SPDXRef-Package-A"), + ("SPDXRef-DOCUMENT_DESCRIBES", "SPDXRef-Package-B"), + ("SPDXRef-Package-A", "SPDXRef-Package-A_CONTAINS"), + ("SPDXRef-Package-A_CONTAINS", "SPDXRef-File"), + ("SPDXRef-Package-B", "SPDXRef-Package-B_CONTAINS"), + ("SPDXRef-Package-B_CONTAINS", "SPDXRef-File"), + ], + ) + + +def _create_minimal_document() -> Document: + packages = [ + package_fixture(spdx_id="SPDXRef-Package-A", name="Package-A"), + package_fixture(spdx_id="SPDXRef-Package-B", name="Package-B"), + ] + files = [ + file_fixture(spdx_id="SPDXRef-File", name="File"), + ] + relationships = [ + Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package-A"), + Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package-B"), + Relationship("SPDXRef-Package-A", RelationshipType.CONTAINS, "SPDXRef-File"), + Relationship("SPDXRef-Package-B", RelationshipType.CONTAINS, "SPDXRef-File"), + ] + document = document_fixture(packages=packages, files=files, relationships=relationships, snippets=[]) + + return document From 01b8a7561787626350f2073736b55c5d6b578930 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 6 Apr 2023 14:36:24 +0200 Subject: [PATCH 043/354] [issue-394] add tests for tag_value writer Signed-off-by: Meret Behrens --- .../writer/tagvalue/test_annotation_writer.py | 28 +++++ .../writer/tagvalue/test_checksum_writer.py | 26 +++++ .../test_extracted_licensing_info_writer.py | 28 +++++ .../spdx/writer/tagvalue/test_file_writer.py | 38 +++++++ .../writer/tagvalue/test_package_writer.py | 51 +++++---- .../tagvalue/test_relationship_writer.py | 46 ++++++++ .../writer/tagvalue/test_snippet_writer.py | 37 +++++++ .../writer/tagvalue/test_tagvalue_writer.py | 103 +++++++++++++++++- .../test_tagvalue_writer_helper_functions.py | 33 +++++- 9 files changed, 362 insertions(+), 28 deletions(-) create mode 100644 tests/spdx/writer/tagvalue/test_annotation_writer.py create mode 100644 tests/spdx/writer/tagvalue/test_checksum_writer.py create mode 100644 tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py create mode 100644 tests/spdx/writer/tagvalue/test_file_writer.py create mode 100644 tests/spdx/writer/tagvalue/test_relationship_writer.py create mode 100644 tests/spdx/writer/tagvalue/test_snippet_writer.py diff --git a/tests/spdx/writer/tagvalue/test_annotation_writer.py b/tests/spdx/writer/tagvalue/test_annotation_writer.py new file mode 100644 index 000000000..1af76c342 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_annotation_writer.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx.writer.tagvalue.annotation_writer import write_annotation +from tests.spdx.fixtures import annotation_fixture + + +def test_annotation_writer(): + annotation = annotation_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_annotation(annotation, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call(f"Annotator: Person: {annotation.annotator.name} ({annotation.annotator.email})\n"), + call("AnnotationDate: 2022-12-01T00:00:00Z\n"), + call(f"AnnotationType: {annotation.annotation_type.name}\n"), + call(f"SPDXREF: {annotation.spdx_id}\n"), + call(f"AnnotationComment: {annotation.annotation_comment}\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_checksum_writer.py b/tests/spdx/writer/tagvalue/test_checksum_writer.py new file mode 100644 index 000000000..535b56088 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_checksum_writer.py @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx.model.checksum import ChecksumAlgorithm +from spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value +from tests.spdx.fixtures import checksum_fixture + + +@pytest.mark.parametrize( + "checksum, expected_string", + [ + (checksum_fixture(), "SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c"), + (checksum_fixture(algorithm=ChecksumAlgorithm.SHA3_256, value="fdsef"), "SHA3-256: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.SHA3_384, value="fdsef"), "SHA3-384: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.SHA3_512, value="fdsef"), "SHA3-512: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.BLAKE2B_256, value="fdsef"), "BLAKE2b-256: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.BLAKE2B_384, value="fdsef"), "BLAKE2b-384: fdsef"), + (checksum_fixture(algorithm=ChecksumAlgorithm.BLAKE2B_512, value="fdsef"), "BLAKE2b-512: fdsef"), + ], +) +def test_checksum_writer(checksum, expected_string): + checksum_string = write_checksum_to_tag_value(checksum) + + assert checksum_string == expected_string diff --git a/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py b/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py new file mode 100644 index 000000000..55354835a --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx.writer.tagvalue.extracted_licensing_info_writer import write_extracted_licensing_info +from tests.spdx.fixtures import extracted_licensing_info_fixture + + +def test_extracted_licensing_info_writer(): + extracted_licensing_info = extracted_licensing_info_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_extracted_licensing_info(extracted_licensing_info, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call(f"LicenseID: {extracted_licensing_info.license_id}\n"), + call(f"ExtractedText: {extracted_licensing_info.extracted_text}\n"), + call(f"LicenseName: {extracted_licensing_info.license_name}\n"), + call(f"LicenseCrossReference: {extracted_licensing_info.cross_references[0]}\n"), + call(f"LicenseComment: {extracted_licensing_info.comment}\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_file_writer.py b/tests/spdx/writer/tagvalue/test_file_writer.py new file mode 100644 index 000000000..27eb7ef49 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_file_writer.py @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx.writer.tagvalue.file_writer import write_file +from tests.spdx.fixtures import file_fixture + + +def test_file_writer(): + spdx_file = file_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_file(spdx_file, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call("## File Information\n"), + call(f"FileName: {spdx_file.name}\n"), + call(f"SPDXID: {spdx_file.spdx_id}\n"), + call(f"FileType: {spdx_file.file_types[0].name}\n"), + call("FileChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), + call(f"LicenseConcluded: {spdx_file.license_concluded}\n"), + call(f"LicenseInfoInFile: {spdx_file.license_info_in_file[0]}\n"), + call(f"LicenseInfoInFile: {spdx_file.license_info_in_file[1]}\n"), + call(f"LicenseInfoInFile: {spdx_file.license_info_in_file[2]}\n"), + call(f"LicenseComments: {spdx_file.license_comment}\n"), + call(f"FileCopyrightText: {spdx_file.copyright_text}\n"), + call(f"FileComment: {spdx_file.comment}\n"), + call(f"FileNotice: {spdx_file.notice}\n"), + call(f"FileContributor: {spdx_file.contributors[0]}\n"), + call(f"FileAttributionText: {spdx_file.attribution_texts[0]}\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_package_writer.py b/tests/spdx/writer/tagvalue/test_package_writer.py index 8cb492b34..38873984a 100644 --- a/tests/spdx/writer/tagvalue/test_package_writer.py +++ b/tests/spdx/writer/tagvalue/test_package_writer.py @@ -20,32 +20,35 @@ def test_package_writer(): handle.write.assert_has_calls( [ call("## Package Information\n"), - call("PackageName: packageName\n"), - call("SPDXID: SPDXRef-Package\n"), - call("PackageVersion: 12.2\n"), - call("PackageFileName: ./packageFileName\n"), - call("PackageSupplier: Person: supplierName (some@mail.com)\n"), - call("PackageOriginator: Person: originatorName (some@mail.com)\n"), - call("PackageDownloadLocation: https://download.com\n"), + call(f"PackageName: {package.name}\n"), + call(f"SPDXID: {package.spdx_id}\n"), + call(f"PackageVersion: {package.version}\n"), + call(f"PackageFileName: {package.file_name}\n"), + call(f"PackageSupplier: Person: {package.supplier.name} ({package.supplier.email})\n"), + call(f"PackageOriginator: Person: {package.originator.name} ({package.originator.email})\n"), + call(f"PackageDownloadLocation: {package.download_location}\n"), call("FilesAnalyzed: True\n"), - call("PackageVerificationCode: 85ed0817af83a24ad8da68c2b5094de69833983c (excludes: ./exclude.py)\n"), + call(f"PackageVerificationCode: {package.verification_code.value} (excludes: ./exclude.py)\n"), call("PackageChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), - call("PackageHomePage: https://homepage.com\n"), - call("PackageSourceInfo: sourceInfo\n"), - call("PackageLicenseConcluded: MIT AND GPL-2.0-only\n"), - call("PackageLicenseInfoFromFiles: MIT\n"), - call("PackageLicenseInfoFromFiles: GPL-2.0-only\n"), - call("PackageLicenseInfoFromFiles: NOASSERTION\n"), - call("PackageLicenseDeclared: MIT AND GPL-2.0-only\n"), - call("PackageLicenseComments: packageLicenseComment\n"), - call("PackageCopyrightText: packageCopyrightText\n"), - call("PackageSummary: packageSummary\n"), - call("PackageDescription: packageDescription\n"), - call("PackageComment: packageComment\n"), - call("ExternalRef: PACKAGE-MANAGER maven-central org.apache.tomcat:tomcat:9.0.0.M4\n"), - call("ExternalRefComment: externalPackageRefComment\n"), - call("PackageAttributionText: packageAttributionText\n"), - call("PrimaryPackagePurpose: SOURCE\n"), + call(f"PackageHomePage: {package.homepage}\n"), + call(f"PackageSourceInfo: {package.source_info}\n"), + call(f"PackageLicenseConcluded: {package.license_concluded}\n"), + call(f"PackageLicenseInfoFromFiles: {package.license_info_from_files[0]}\n"), + call(f"PackageLicenseInfoFromFiles: {package.license_info_from_files[1]}\n"), + call(f"PackageLicenseInfoFromFiles: {package.license_info_from_files[2]}\n"), + call(f"PackageLicenseDeclared: {package.license_declared}\n"), + call(f"PackageLicenseComments: {package.license_comment}\n"), + call(f"PackageCopyrightText: {package.copyright_text}\n"), + call(f"PackageSummary: {package.summary}\n"), + call(f"PackageDescription: {package.description}\n"), + call(f"PackageComment: {package.comment}\n"), + call( + f"ExternalRef: PACKAGE-MANAGER {package.external_references[0].reference_type} " + f"{package.external_references[0].locator}\n" + ), + call(f"ExternalRefComment: {package.external_references[0].comment}\n"), + call(f"PackageAttributionText: {package.attribution_texts[0]}\n"), + call(f"PrimaryPackagePurpose: {package.primary_package_purpose.name}\n"), call("ReleaseDate: 2022-12-01T00:00:00Z\n"), call("BuiltDate: 2022-12-02T00:00:00Z\n"), call("ValidUntilDate: 2022-12-03T00:00:00Z\n"), diff --git a/tests/spdx/writer/tagvalue/test_relationship_writer.py b/tests/spdx/writer/tagvalue/test_relationship_writer.py new file mode 100644 index 000000000..2d0a129f1 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_relationship_writer.py @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +import pytest + +from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx.model.spdx_none import SpdxNone +from spdx.writer.tagvalue.relationship_writer import write_relationship +from tests.spdx.fixtures import relationship_fixture + + +@pytest.mark.parametrize( + "relationship, expected_calls", + [ + ( + relationship_fixture(), + [ + call("Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-File\n"), + call("RelationshipComment: relationshipComment\n"), + ], + ), + ( + relationship_fixture(related_spdx_element_id=SpdxNoAssertion(), comment=None), + [call("Relationship: SPDXRef-DOCUMENT DESCRIBES NOASSERTION\n")], + ), + ( + relationship_fixture( + spdx_element_id="DocumentRef-External:SPDXRef-DOCUMENT", + related_spdx_element_id=SpdxNone(), + comment=None, + ), + [call("Relationship: DocumentRef-External:SPDXRef-DOCUMENT DESCRIBES NONE\n")], + ), + ], +) +def test_relationship_writer(relationship, expected_calls): + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_relationship(relationship, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls(expected_calls) diff --git a/tests/spdx/writer/tagvalue/test_snippet_writer.py b/tests/spdx/writer/tagvalue/test_snippet_writer.py new file mode 100644 index 000000000..39e661c87 --- /dev/null +++ b/tests/spdx/writer/tagvalue/test_snippet_writer.py @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +from spdx.writer.tagvalue.snippet_writer import write_snippet +from tests.spdx.fixtures import snippet_fixture + + +def test_snippet_writer(): + snippet = snippet_fixture() + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_snippet(snippet, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call("## Snippet Information\n"), + call(f"SnippetSPDXID: {snippet.spdx_id}\n"), + call(f"SnippetFromFileSPDXID: {snippet.file_spdx_id}\n"), + call("SnippetByteRange: 1:2\n"), + call("SnippetLineRange: 3:4\n"), + call(f"SnippetLicenseConcluded: {snippet.license_concluded}\n"), + call(f"LicenseInfoInSnippet: {snippet.license_info_in_snippet[0]}\n"), + call(f"LicenseInfoInSnippet: {snippet.license_info_in_snippet[1]}\n"), + call(f"LicenseInfoInSnippet: {snippet.license_info_in_snippet[2]}\n"), + call(f"SnippetLicenseComments: {snippet.license_comment}\n"), + call(f"SnippetCopyrightText: {snippet.copyright_text}\n"), + call(f"SnippetComment: {snippet.comment}\n"), + call(f"SnippetName: {snippet.name}\n"), + call(f"SnippetAttributionText: {snippet.attribution_texts[0]}\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py index b6d3b4ece..6aeda9030 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py @@ -3,12 +3,17 @@ # SPDX-License-Identifier: Apache-2.0 import os +from unittest.mock import MagicMock, call, mock_open, patch import pytest +from spdx.model.file import File +from spdx.model.package import Package +from spdx.model.relationship import Relationship, RelationshipType +from spdx.model.snippet import Snippet from spdx.parser.tagvalue import tagvalue_parser -from spdx.writer.tagvalue.tagvalue_writer import write_document_to_file -from tests.spdx.fixtures import document_fixture +from spdx.writer.tagvalue.tagvalue_writer import write_document, write_document_to_file +from tests.spdx.fixtures import checksum_fixture, document_fixture @pytest.fixture @@ -26,3 +31,97 @@ def test_write_tag_value(temporary_file_path: str): parsed_document = tagvalue_parser.parse_from_file(temporary_file_path) assert parsed_document == document + + +def test_correct_order_of_elements(): + packages = [ + Package(name="Test Package A", spdx_id="SPDXRef-Package-A", download_location=""), + Package(name="Test Package B", spdx_id="SPDXRef-Package-B", download_location=""), + ] + files = [ + File(name="Test File A", spdx_id="SPDXRef-File-A", checksums=[checksum_fixture()]), + File(name="Test File B", spdx_id="SPDXRef-File-B", checksums=[checksum_fixture()]), + ] + snippets = [ + Snippet(spdx_id="SPDXRef-Snippet-A", file_spdx_id="DocumentRef-External:SPDXRef-File", byte_range=(1, 2)), + Snippet(spdx_id="SPDXRef-Snippet-B", file_spdx_id="SPDXRef-File-A", byte_range=(1, 2)), + Snippet(spdx_id="SPDXRef-Snippet-C", file_spdx_id="SPDXRef-File-B", byte_range=(3, 4)), + ] + relationships = [Relationship("SPDXRef-Package-A", RelationshipType.CONTAINS, "SPDXRef-File-B")] + document = document_fixture( + files=files, + packages=packages, + snippets=snippets, + relationships=relationships, + annotations=[], + extracted_licensing_info=[], + ) + + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_document(document, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call("## Document Information\n"), + call("SPDXVersion: SPDX-2.3\n"), + call("DataLicense: CC0-1.0\n"), + call("SPDXID: SPDXRef-DOCUMENT\n"), + call("DocumentName: documentName\n"), + call("DocumentNamespace: https://some.namespace\n"), + call("DocumentComment: documentComment\n"), + call("\n## External Document References\n"), + call( + "ExternalDocumentRef: DocumentRef-external https://namespace.com " + "SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n" + ), + call("\n"), + call("## Creation Information\n"), + call("LicenseListVersion: 3.19\n"), + call("Creator: Person: creatorName (some@mail.com)\n"), + call("Created: 2022-12-01T00:00:00Z\n"), + call("CreatorComment: creatorComment\n"), + call("\n"), + call("## Snippet Information\n"), + call("SnippetSPDXID: SPDXRef-Snippet-A\n"), + call("SnippetFromFileSPDXID: DocumentRef-External:SPDXRef-File\n"), + call("SnippetByteRange: 1:2\n"), + call("\n"), + call("## File Information\n"), + call("FileName: Test File A\n"), + call("SPDXID: SPDXRef-File-A\n"), + call("FileChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), + call("\n"), + call("## Snippet Information\n"), + call("SnippetSPDXID: SPDXRef-Snippet-B\n"), + call("SnippetFromFileSPDXID: SPDXRef-File-A\n"), + call("SnippetByteRange: 1:2\n"), + call("\n"), + call("## Package Information\n"), + call("PackageName: Test Package A\n"), + call("SPDXID: SPDXRef-Package-A\n"), + call("PackageDownloadLocation: \n"), + call("FilesAnalyzed: True\n"), + call("\n"), + call("## File Information\n"), + call("FileName: Test File B\n"), + call("SPDXID: SPDXRef-File-B\n"), + call("FileChecksum: SHA1: 71c4025dd9897b364f3ebbb42c484ff43d00791c\n"), + call("\n"), + call("## Snippet Information\n"), + call("SnippetSPDXID: SPDXRef-Snippet-C\n"), + call("SnippetFromFileSPDXID: SPDXRef-File-B\n"), + call("SnippetByteRange: 3:4\n"), + call("\n"), + call("## Package Information\n"), + call("PackageName: Test Package B\n"), + call("SPDXID: SPDXRef-Package-B\n"), + call("PackageDownloadLocation: \n"), + call("FilesAnalyzed: True\n"), + call("\n"), + call("\n"), + ] + ) diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py index b6b36a81a..4d2446213 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py @@ -1,9 +1,15 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from unittest.mock import MagicMock, call, mock_open, patch + +import pytest + +from spdx.model.actor import ActorType from spdx.model.relationship import RelationshipType -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import scan_relationships -from tests.spdx.fixtures import file_fixture, package_fixture, relationship_fixture +from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import scan_relationships, write_actor +from tests.spdx.fixtures import actor_fixture, file_fixture, package_fixture, relationship_fixture def test_scan_relationships(): @@ -31,3 +37,26 @@ def test_scan_relationships(): assert relationships_to_write == [] assert contained_files_by_package_id == {first_package_spdx_id: files, second_package_spdx_id: files} + + +@pytest.mark.parametrize( + "element_to_write, expected_calls", + [ + (actor_fixture(), [call("ActorTest: Person: actorName (some@mail.com)\n")]), + ( + actor_fixture(actor_type=ActorType.ORGANIZATION, name="organizationName"), + [call("ActorTest: Organization: organizationName (some@mail.com)\n")], + ), + (actor_fixture(actor_type=ActorType.TOOL, name="toolName", email=None), [call("ActorTest: Tool: toolName\n")]), + (SpdxNoAssertion(), [call("ActorTest: NOASSERTION\n")]), + ], +) +def test_write_actor(element_to_write, expected_calls): + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_actor("ActorTest", element_to_write, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls(expected_calls) From bbccaa12f0f52acb79f17e563d52727f8ac3e331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 11 Apr 2023 14:45:58 +0200 Subject: [PATCH 044/354] [issue-570] change fixture dates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx/fixtures.py | 8 ++++---- tests/spdx/writer/json/expected_results/expected.json | 8 ++++---- tests/spdx/writer/tagvalue/test_annotation_writer.py | 2 +- tests/spdx/writer/tagvalue/test_package_writer.py | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/spdx/fixtures.py b/tests/spdx/fixtures.py index 5d58b9fbf..3065bc824 100644 --- a/tests/spdx/fixtures.py +++ b/tests/spdx/fixtures.py @@ -140,9 +140,9 @@ def package_fixture( external_references=None, attribution_texts=None, primary_package_purpose=PackagePurpose.SOURCE, - release_date=datetime(2022, 12, 1), - built_date=datetime(2022, 12, 2), - valid_until_date=datetime(2022, 12, 3), + release_date=datetime(2022, 11, 1), + built_date=datetime(2022, 11, 2), + valid_until_date=datetime(2022, 11, 3), ) -> Package: checksums = [checksum_fixture()] if checksums is None else checksums license_info_from_files = ( @@ -235,7 +235,7 @@ def annotation_fixture( spdx_id="SPDXRef-File", annotation_type=AnnotationType.REVIEW, annotator=actor_fixture(name="annotatorName"), - annotation_date=datetime(2022, 12, 1), + annotation_date=datetime(2022, 12, 24), annotation_comment="annotationComment", ) -> Annotation: return Annotation( diff --git a/tests/spdx/writer/json/expected_results/expected.json b/tests/spdx/writer/json/expected_results/expected.json index b6a364b35..0d444ba52 100644 --- a/tests/spdx/writer/json/expected_results/expected.json +++ b/tests/spdx/writer/json/expected_results/expected.json @@ -29,7 +29,7 @@ "SPDXID": "SPDXRef-File", "annotations": [ { - "annotationDate": "2022-12-01T00:00:00Z", + "annotationDate": "2022-12-24T00:00:00Z", "annotationType": "REVIEW", "annotator": "Person: annotatorName (some@mail.com)", "comment": "annotationComment" @@ -77,7 +77,7 @@ "attributionTexts": [ "packageAttributionText" ], - "builtDate": "2022-12-02T00:00:00Z", + "builtDate": "2022-11-02T00:00:00Z", "checksums": [ { "algorithm": "SHA1", @@ -112,11 +112,11 @@ "packageVerificationCodeValue": "85ed0817af83a24ad8da68c2b5094de69833983c" }, "primaryPackagePurpose": "SOURCE", - "releaseDate": "2022-12-01T00:00:00Z", + "releaseDate": "2022-11-01T00:00:00Z", "sourceInfo": "sourceInfo", "summary": "packageSummary", "supplier": "Person: supplierName (some@mail.com)", - "validUntilDate": "2022-12-03T00:00:00Z", + "validUntilDate": "2022-11-03T00:00:00Z", "versionInfo": "12.2" } ], diff --git a/tests/spdx/writer/tagvalue/test_annotation_writer.py b/tests/spdx/writer/tagvalue/test_annotation_writer.py index 1af76c342..5b36f5c32 100644 --- a/tests/spdx/writer/tagvalue/test_annotation_writer.py +++ b/tests/spdx/writer/tagvalue/test_annotation_writer.py @@ -20,7 +20,7 @@ def test_annotation_writer(): handle.write.assert_has_calls( [ call(f"Annotator: Person: {annotation.annotator.name} ({annotation.annotator.email})\n"), - call("AnnotationDate: 2022-12-01T00:00:00Z\n"), + call("AnnotationDate: 2022-12-24T00:00:00Z\n"), call(f"AnnotationType: {annotation.annotation_type.name}\n"), call(f"SPDXREF: {annotation.spdx_id}\n"), call(f"AnnotationComment: {annotation.annotation_comment}\n"), diff --git a/tests/spdx/writer/tagvalue/test_package_writer.py b/tests/spdx/writer/tagvalue/test_package_writer.py index 38873984a..958ff9931 100644 --- a/tests/spdx/writer/tagvalue/test_package_writer.py +++ b/tests/spdx/writer/tagvalue/test_package_writer.py @@ -49,8 +49,8 @@ def test_package_writer(): call(f"ExternalRefComment: {package.external_references[0].comment}\n"), call(f"PackageAttributionText: {package.attribution_texts[0]}\n"), call(f"PrimaryPackagePurpose: {package.primary_package_purpose.name}\n"), - call("ReleaseDate: 2022-12-01T00:00:00Z\n"), - call("BuiltDate: 2022-12-02T00:00:00Z\n"), - call("ValidUntilDate: 2022-12-03T00:00:00Z\n"), + call("ReleaseDate: 2022-11-01T00:00:00Z\n"), + call("BuiltDate: 2022-11-02T00:00:00Z\n"), + call("ValidUntilDate: 2022-11-03T00:00:00Z\n"), ] ) From d17188db54280731b7ba680564b5a20d2d47b877 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 6 Apr 2023 15:12:48 +0200 Subject: [PATCH 045/354] [issue-558] add test for optional feature to GitHub Action Signed-off-by: Meret Behrens --- .github/workflows/install_and_test.yml | 5 +++++ tests/spdx/test_graph_generation.py | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/install_and_test.yml b/.github/workflows/install_and_test.yml index 982c9089d..a23887e4b 100644 --- a/.github/workflows/install_and_test.yml +++ b/.github/workflows/install_and_test.yml @@ -33,3 +33,8 @@ jobs: run: pytest - name: Run CLI run: pyspdxtools -i ./tests/spdx/data/formats/SPDXJSONExample-v2.3.spdx.json + + - name: Install optional dependencies + run: python -m pip install networkx + - name: Run tests for graph generation + run: pytest tests/spdx/test_graph_generation.py diff --git a/tests/spdx/test_graph_generation.py b/tests/spdx/test_graph_generation.py index 6c28d1d41..9128625f2 100644 --- a/tests/spdx/test_graph_generation.py +++ b/tests/spdx/test_graph_generation.py @@ -15,7 +15,6 @@ try: import networkx # noqa: F401 - import pygraphviz # noqa: F401 except ImportError: pytest.skip("Skip this module as the tests need optional dependencies to run.", allow_module_level=True) @@ -44,7 +43,7 @@ ( "SPDXRdfExample-v2.2.spdx.rdf.xml", 20, - 17, + 19, ["SPDXRef-Package_DYNAMIC_LINK", "SPDXRef-JenaLib_CONTAINS"], ), ( From 780c94f761fe722c71eb89d212faf0c7cd12d9f2 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 11 Apr 2023 14:45:10 +0200 Subject: [PATCH 046/354] [issue-558] add installation group for development Signed-off-by: Meret Behrens --- CONTRIBUTING.md | 6 +++--- pyproject.toml | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 653b366fa..4c4a04341 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,8 +34,10 @@ Here's the process to make changes to the codebase: git checkout -b fix-or-improve-something python -m venv ./venv ./venv/bin/activate - pip install -e . + pip install -e ".[development]" ``` + Note: By using the group `[development]` for the installation, all dependencies (including optional ones) will be + installed. This way we make sure that all tests are executed. 5. Make some changes and commit them to the branch: ```sh git commit --signoff -m 'description of my changes' @@ -49,14 +51,12 @@ Here's the process to make changes to the codebase: retroactively signs a range of past commits. 6. Test your changes: ```sh - pip install pytest pytest -vvs # in the repo root ``` 7. Check your code style. When opening a pull request, your changes will automatically be checked with `isort`, `black` and `flake8` to make sure your changes fit with the rest of the code style. ```sh - pip install .[code_style] # run the following commands in the repo root isort src tests black src tests diff --git a/pyproject.toml b/pyproject.toml index 338339c31..7acbb7ffa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,6 +31,7 @@ dynamic = ["version"] test = ["pytest"] code_style = ["isort", "black", "flake8"] graph_generation = ["pygraphviz", "networkx"] +development = ["black", "flake8", "isort", "networkx", "pytest"] [project.scripts] pyspdxtools = "spdx.clitools.pyspdxtools:main" From bfcd5e2d60aa2487ea4fb6a2309715e01fec27a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 12 Apr 2023 12:51:51 +0200 Subject: [PATCH 047/354] [issue-402] change write_document() to write_document_to_file() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx/writer/json/json_writer.py | 4 +++- src/spdx/writer/write_anything.py | 2 +- tests/spdx/writer/json/test_json_writer.py | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/spdx/writer/json/json_writer.py b/src/spdx/writer/json/json_writer.py index 68f435cd8..6a11671ce 100644 --- a/src/spdx/writer/json/json_writer.py +++ b/src/spdx/writer/json/json_writer.py @@ -10,7 +10,9 @@ from spdx.validation.validation_message import ValidationMessage -def write_document(document: Document, file_name: str, validate: bool = True, converter: DocumentConverter = None): +def write_document_to_file( + document: Document, file_name: str, validate: bool = True, converter: DocumentConverter = None +): """ Serializes the provided document to json and writes it to a file with the provided name. Unless validate is set to False, validates the document before serialization. Unless a DocumentConverter instance is provided, diff --git a/src/spdx/writer/write_anything.py b/src/spdx/writer/write_anything.py index 06ca4aa11..87a8e08a2 100644 --- a/src/spdx/writer/write_anything.py +++ b/src/spdx/writer/write_anything.py @@ -13,7 +13,7 @@ def write_file(document: Document, file_name: str, validate: bool = True): output_format = file_name_to_format(file_name) if output_format == FileFormat.JSON: - json_writer.write_document(document, file_name, validate) + json_writer.write_document_to_file(document, file_name, validate) elif output_format == FileFormat.YAML: yaml_writer.write_document_to_file(document, file_name, validate) elif output_format == FileFormat.XML: diff --git a/tests/spdx/writer/json/test_json_writer.py b/tests/spdx/writer/json/test_json_writer.py index d17484e04..ee6013275 100644 --- a/tests/spdx/writer/json/test_json_writer.py +++ b/tests/spdx/writer/json/test_json_writer.py @@ -6,7 +6,7 @@ import pytest -from spdx.writer.json.json_writer import write_document +from spdx.writer.json.json_writer import write_document_to_file from tests.spdx.fixtures import document_fixture @@ -19,7 +19,7 @@ def temporary_file_path() -> str: def test_write_json(temporary_file_path: str): document = document_fixture() - write_document(document, temporary_file_path, validate=True) + write_document_to_file(document, temporary_file_path, validate=True) with open(temporary_file_path) as written_file: written_json = json.load(written_file) @@ -35,7 +35,7 @@ def test_document_is_validated(): document.creation_info.spdx_id = "InvalidId" with pytest.raises(ValueError) as error: - write_document(document, "dummy_path") + write_document_to_file(document, "dummy_path") assert "Document is not valid" in error.value.args[0] @@ -43,4 +43,4 @@ def test_document_validation_can_be_overridden(temporary_file_path: str): document = document_fixture() document.creation_info.spdx_id = "InvalidId" - write_document(document, temporary_file_path, validate=False) + write_document_to_file(document, temporary_file_path, validate=False) From 85e8783ed14e4e86a02890203905942e55164819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 12 Apr 2023 12:02:56 +0200 Subject: [PATCH 048/354] [issue-573] unify parse_from_file tests for all formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../data/formats/SPDXTagExample-v2.2.spdx | 329 +++++++++++++ .../data/formats/SPDXXMLExample-v2.2.spdx.xml | 443 +++++++++++++++++ .../data/formats/SPDXXMLExample-v2.3.spdx.xml | 460 ++++++++++++++++++ .../formats/SPDXYAMLExample-v2.2.spdx.yaml | 390 +++++++++++++++ .../formats/SPDXYAMLExample-v2.3.spdx.yaml | 406 ++++++++++++++++ .../parser/{json => all_formats}/__init__.py | 0 .../all_formats/test_parse_from_file.py | 61 +++ tests/spdx/parser/json/test_json_parser.py | 44 -- tests/spdx/parser/rdf/test_rdf_parser.py | 48 -- .../parser/tagvalue/test_tag_value_parser.py | 18 - 10 files changed, 2089 insertions(+), 110 deletions(-) create mode 100644 tests/spdx/data/formats/SPDXTagExample-v2.2.spdx create mode 100644 tests/spdx/data/formats/SPDXXMLExample-v2.2.spdx.xml create mode 100644 tests/spdx/data/formats/SPDXXMLExample-v2.3.spdx.xml create mode 100644 tests/spdx/data/formats/SPDXYAMLExample-v2.2.spdx.yaml create mode 100644 tests/spdx/data/formats/SPDXYAMLExample-v2.3.spdx.yaml rename tests/spdx/parser/{json => all_formats}/__init__.py (100%) create mode 100644 tests/spdx/parser/all_formats/test_parse_from_file.py delete mode 100644 tests/spdx/parser/json/test_json_parser.py delete mode 100644 tests/spdx/parser/rdf/test_rdf_parser.py diff --git a/tests/spdx/data/formats/SPDXTagExample-v2.2.spdx b/tests/spdx/data/formats/SPDXTagExample-v2.2.spdx new file mode 100644 index 000000000..e8f32ebfd --- /dev/null +++ b/tests/spdx/data/formats/SPDXTagExample-v2.2.spdx @@ -0,0 +1,329 @@ +SPDXVersion: SPDX-2.2 +DataLicense: CC0-1.0 +DocumentNamespace: http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 +DocumentName: SPDX-Tools-v2.0 +SPDXID: SPDXRef-DOCUMENT +DocumentComment: This document was created using SPDX 2.0 using licenses from the web site. + +## External Document References +ExternalDocumentRef: DocumentRef-spdx-tool-1.2 http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759 +## Creation Information +Creator: Tool: LicenseFind-1.0 +Creator: Organization: ExampleCodeInspect () +Creator: Person: Jane Doe () +Created: 2010-01-29T18:30:22Z +CreatorComment: This package has been shipped in source and binary form. +The binaries were created with gcc 4.5.1 and expect to link to +compatible system run time libraries. +LicenseListVersion: 3.9 +## Annotations +Annotator: Person: Jane Doe () +AnnotationDate: 2010-01-29T18:30:22Z +AnnotationComment: Document level annotation +AnnotationType: OTHER +SPDXREF: SPDXRef-DOCUMENT +Annotator: Person: Joe Reviewer +AnnotationDate: 2010-02-10T00:00:00Z +AnnotationComment: This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses +AnnotationType: REVIEW +SPDXREF: SPDXRef-DOCUMENT +Annotator: Person: Suzanne Reviewer +AnnotationDate: 2011-03-13T00:00:00Z +AnnotationComment: Another example reviewer. +AnnotationType: REVIEW +SPDXREF: SPDXRef-DOCUMENT +## Relationships +Relationship: SPDXRef-DOCUMENT CONTAINS SPDXRef-Package +Relationship: SPDXRef-DOCUMENT COPY_OF DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement +Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-File +Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-Package + +FileName: ./package/foo.c +SPDXID: SPDXRef-File +FileComment: The concluded license was taken from the package level that the file was included in. +This information was found in the COPYING.txt file in the xyz directory. +FileType: SOURCE +FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2758 +FileChecksum: MD5: 624c1abb3664f4b35547e7c73864ad24 +LicenseConcluded: (LGPL-2.0-only OR LicenseRef-2) +LicenseInfoInFile: GPL-2.0-only +LicenseInfoInFile: LicenseRef-2 +LicenseComments: The concluded license was taken from the package level that the file was included in. +FileCopyrightText: Copyright 2008-2010 John Smith +FileNotice: Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the �Software�), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED �AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +FileContributor: The Regents of the University of California +FileContributor: Modified by Paul Mundt lethal@linux-sh.org +FileContributor: IBM Corporation +## Annotations +Annotator: Person: File Commenter +AnnotationDate: 2011-01-29T18:30:22Z +AnnotationComment: File level annotation +AnnotationType: OTHER +SPDXREF: SPDXRef-File +## Relationships +Relationship: SPDXRef-File GENERATED_FROM SPDXRef-fromDoap-0 +## Package Information +PackageName: glibc +SPDXID: SPDXRef-Package +PackageVersion: 2.11.1 +PackageFileName: glibc-2.11.1.tar.gz +PackageSupplier: Person: Jane Doe (jane.doe@example.com) +PackageOriginator: Organization: ExampleCodeInspect (contact@example.com) +PackageDownloadLocation: http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz +PackageVerificationCode: d6a770ba38583ed4bb4525bd96e50461655d2758(./package.spdx) +PackageChecksum: MD5: 624c1abb3664f4b35547e7c73864ad24 +PackageChecksum: SHA1: 85ed0817af83a24ad8da68c2b5094de69833983c +PackageChecksum: SHA256: 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd +PackageHomePage: http://ftp.gnu.org/gnu/glibc +PackageSourceInfo: uses glibc-2_11-branch from git://sourceware.org/git/glibc.git. +PackageLicenseConcluded: (LGPL-2.0-only OR LicenseRef-3) +## License information from files +PackageLicenseInfoFromFiles: GPL-2.0-only +PackageLicenseInfoFromFiles: LicenseRef-2 +PackageLicenseInfoFromFiles: LicenseRef-1 +PackageLicenseDeclared: (LGPL-2.0-only AND LicenseRef-3) +PackageLicenseComments: The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change. +PackageCopyrightText: Copyright 2008-2010 John Smith +PackageSummary: GNU C library. +PackageDescription: The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems. +PackageAttributionText: The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually. +ExternalRef: SECURITY cpe23Type cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:* +ExternalRef: OTHER LocationRef-acmeforge acmecorp/acmenator/4.1.3-alpha +ExternalRefComment: This is the external ref for Acme +## Annotations +Annotator: Person: Package Commenter +AnnotationDate: 2011-01-29T18:30:22Z +AnnotationComment: Package level annotation +AnnotationType: OTHER +SPDXREF: SPDXRef-Package +## Relationships +Relationship: SPDXRef-Package CONTAINS SPDXRef-JenaLib +Relationship: SPDXRef-Package DYNAMIC_LINK SPDXRef-Saxon + +## File Information +FileName: ./lib-source/commons-lang3-3.1-sources.jar +SPDXID: SPDXRef-CommonsLangSrc +FileComment: This file is used by Jena +FileType: ARCHIVE +FileChecksum: SHA1: c2b4e1c67a2d28fced849ee1bb76e7391b93f125 +LicenseConcluded: Apache-2.0 +LicenseInfoInFile: Apache-2.0 +FileCopyrightText: Copyright 2001-2011 The Apache Software Foundation +FileNotice: Apache Commons Lang +Copyright 2001-2011 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + +This product includes software from the Spring Framework, +under the Apache License 2.0 (see: StringUtils.containsWhitespace()) +FileContributor: Apache Software Foundation +## Relationships +Relationship: SPDXRef-CommonsLangSrc GENERATED_FROM NOASSERTION + +FileName: ./lib-source/jena-2.6.3-sources.jar +SPDXID: SPDXRef-JenaLib +FileComment: This file belongs to Jena +FileType: ARCHIVE +FileChecksum: SHA1: 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 +LicenseConcluded: LicenseRef-1 +LicenseInfoInFile: LicenseRef-1 +LicenseComments: This license is used by Jena +FileCopyrightText: (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP +FileContributor: Apache Software Foundation +FileContributor: Hewlett Packard Inc. +## Relationships +Relationship: SPDXRef-JenaLib CONTAINS SPDXRef-Package + +FileName: ./src/org/spdx/parser/DOAPProject.java +SPDXID: SPDXRef-DoapSource +FileType: SOURCE +FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 +LicenseConcluded: Apache-2.0 +LicenseInfoInFile: Apache-2.0 +FileCopyrightText: Copyright 2010, 2011 Source Auditor Inc. +FileContributor: Protecode Inc. +FileContributor: SPDX Technical Team Members +FileContributor: Open Logic Inc. +FileContributor: Source Auditor Inc. +FileContributor: Black Duck Software In.c + +## Package Information +PackageName: Apache Commons Lang +SPDXID: SPDXRef-fromDoap-1 +PackageDownloadLocation: NOASSERTION +PackageHomePage: http://commons.apache.org/proper/commons-lang/ +PackageLicenseConcluded: NOASSERTION +PackageLicenseDeclared: NOASSERTION +PackageCopyrightText: NOASSERTION +FilesAnalyzed: false + +## Package Information +PackageName: Jena +SPDXID: SPDXRef-fromDoap-0 +PackageVersion: 3.12.0 +PackageDownloadLocation: https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz +PackageHomePage: http://www.openjena.org/ +PackageLicenseConcluded: NOASSERTION +PackageLicenseDeclared: NOASSERTION +PackageCopyrightText: NOASSERTION +ExternalRef: PACKAGE-MANAGER purl pkg:maven/org.apache.jena/apache-jena@3.12.0 +FilesAnalyzed: false + +## Package Information +PackageName: Saxon +SPDXID: SPDXRef-Saxon +PackageVersion: 8.8 +PackageFileName: saxonB-8.8.zip +PackageDownloadLocation: https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download +PackageChecksum: SHA1: 85ed0817af83a24ad8da68c2b5094de69833983c +PackageHomePage: http://saxon.sourceforge.net/ +PackageLicenseConcluded: MPL-1.0 +PackageLicenseDeclared: MPL-1.0 +PackageLicenseComments: Other versions available for a commercial license +PackageCopyrightText: Copyright Saxonica Ltd +PackageDescription: The Saxon package is a collection of tools for processing XML documents. +FilesAnalyzed: false + +## Snippet Information +SnippetSPDXID: SPDXRef-Snippet +SnippetFromFileSPDXID: SPDXRef-DoapSource +SnippetByteRange: 310:420 +SnippetLineRange: 5:23 +SnippetLicenseConcluded: GPL-2.0-only +LicenseInfoInSnippet: GPL-2.0-only +SnippetLicenseComments: The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. +SnippetCopyrightText: Copyright 2008-2010 John Smith +SnippetComment: This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0. +SnippetName: from linux kernel + + +## License Information +LicenseID: LicenseRef-1 +ExtractedText: /* + * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +LicenseID: LicenseRef-2 +ExtractedText: This package includes the GRDDL parser developed by Hewlett Packard under the following license: +� Copyright 2007 Hewlett-Packard Development Company, LP + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +LicenseID: LicenseRef-4 +ExtractedText: /* + * (c) Copyright 2009 University of Bristol + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +LicenseID: LicenseRef-Beerware-4.2 +ExtractedText: "THE BEER-WARE LICENSE" (Revision 42): +phk@FreeBSD.ORG wrote this file. As long as you retain this notice you +can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp +LicenseName: Beer-Ware License (Version 42) +LicenseCrossReference: http://people.freebsd.org/~phk/ +LicenseComment: The beerware license has a couple of other standard variants. + +LicenseID: LicenseRef-3 +ExtractedText: The CyberNeko Software License, Version 1.0 + + +(C) Copyright 2002-2005, Andy Clark. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by Andy Clark." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + +4. The names "CyberNeko" and "NekoHTML" must not be used to endorse + or promote products derived from this software without prior + written permission. For written permission, please contact + andyc@cyberneko.net. + +5. Products derived from this software may not be called "CyberNeko", + nor may "CyberNeko" appear in their name, without prior written + permission of the author. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +LicenseName: CyberNeko License +LicenseCrossReference: http://people.apache.org/~andyc/neko/LICENSE, http://justasample.url.com +LicenseComment: This is tye CyperNeko License + diff --git a/tests/spdx/data/formats/SPDXXMLExample-v2.2.spdx.xml b/tests/spdx/data/formats/SPDXXMLExample-v2.2.spdx.xml new file mode 100644 index 000000000..80e0527a2 --- /dev/null +++ b/tests/spdx/data/formats/SPDXXMLExample-v2.2.spdx.xml @@ -0,0 +1,443 @@ + + + SPDXRef-DOCUMENT + SPDX-2.2 + + This package has been shipped in source and binary form. +The binaries were created with gcc 4.5.1 and expect to link to +compatible system run time libraries. + 2010-01-29T18:30:22Z + Tool: LicenseFind-1.0 + Organization: ExampleCodeInspect () + Person: Jane Doe () + 3.9 + + SPDX-Tools-v2.0 + CC0-1.0 + This document was created using SPDX 2.0 using licenses from the web site. + + DocumentRef-spdx-tool-1.2 + + SHA1 + d6a770ba38583ed4bb4525bd96e50461655d2759 + + http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 + + + LicenseRef-1 + /* + * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + LicenseRef-2 + This package includes the GRDDL parser developed by Hewlett Packard under the following license: +� Copyright 2007 Hewlett-Packard Development Company, LP + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + LicenseRef-4 + /* + * (c) Copyright 2009 University of Bristol + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + LicenseRef-Beerware-4.2 + The beerware license has a couple of other standard variants. + "THE BEER-WARE LICENSE" (Revision 42): +phk@FreeBSD.ORG wrote this file. As long as you retain this notice you +can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp + Beer-Ware License (Version 42) + http://people.freebsd.org/~phk/ + + + LicenseRef-3 + This is tye CyperNeko License + The CyberNeko Software License, Version 1.0 + + +(C) Copyright 2002-2005, Andy Clark. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by Andy Clark." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + +4. The names "CyberNeko" and "NekoHTML" must not be used to endorse + or promote products derived from this software without prior + written permission. For written permission, please contact + andyc@cyberneko.net. + +5. Products derived from this software may not be called "CyberNeko", + nor may "CyberNeko" appear in their name, without prior written + permission of the author. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + CyberNeko License + http://people.apache.org/~andyc/neko/LICENSE + http://justasample.url.com + + + 2010-01-29T18:30:22Z + OTHER + Person: Jane Doe () + Document level annotation + + + 2010-02-10T00:00:00Z + REVIEW + Person: Joe Reviewer + This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses + + + 2011-03-13T00:00:00Z + REVIEW + Person: Suzanne Reviewer + Another example reviewer. + + http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 + SPDXRef-File + SPDXRef-Package + + SPDXRef-Package + + 2011-01-29T18:30:22Z + OTHER + Person: Package Commenter + Package level annotation + + The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually. + + MD5 + 624c1abb3664f4b35547e7c73864ad24 + + + SHA1 + 85ed0817af83a24ad8da68c2b5094de69833983c + + + SHA256 + 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd + + Copyright 2008-2010 John Smith + The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems. + http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz + + SECURITY + cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:* + cpe23Type + + + This is the external ref for Acme + OTHER + acmecorp/acmenator/4.1.3-alpha + http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge + + true + SPDXRef-CommonsLangSrc + SPDXRef-JenaLib + SPDXRef-DoapSource + http://ftp.gnu.org/gnu/glibc + The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change. + (LGPL-2.0-only OR LicenseRef-3) + (LGPL-2.0-only AND LicenseRef-3) + GPL-2.0-only + LicenseRef-2 + LicenseRef-1 + glibc + Organization: ExampleCodeInspect (contact@example.com) + glibc-2.11.1.tar.gz + + ./package.spdx + d6a770ba38583ed4bb4525bd96e50461655d2758 + + uses glibc-2_11-branch from git://sourceware.org/git/glibc.git. +

GNU C library. + Person: Jane Doe (jane.doe@example.com) + 2.11.1 + + + SPDXRef-fromDoap-1 + NOASSERTION + NOASSERTION + false + http://commons.apache.org/proper/commons-lang/ + NOASSERTION + NOASSERTION + Apache Commons Lang + + + SPDXRef-fromDoap-0 + NOASSERTION + https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz + + PACKAGE_MANAGER + pkg:maven/org.apache.jena/apache-jena@3.12.0 + purl + + false + http://www.openjena.org/ + NOASSERTION + NOASSERTION + Jena + 3.12.0 + + + SPDXRef-Saxon + + SHA1 + 85ed0817af83a24ad8da68c2b5094de69833983c + + Copyright Saxonica Ltd + The Saxon package is a collection of tools for processing XML documents. + https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download + false + http://saxon.sourceforge.net/ + Other versions available for a commercial license + MPL-1.0 + MPL-1.0 + Saxon + saxonB-8.8.zip + 8.8 + + + SPDXRef-DoapSource + + SHA1 + 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 + + Copyright 2010, 2011 Source Auditor Inc. + Protecode Inc. + SPDX Technical Team Members + Open Logic Inc. + Source Auditor Inc. + Black Duck Software In.c + ./src/org/spdx/parser/DOAPProject.java + SOURCE + Apache-2.0 + Apache-2.0 + + + SPDXRef-CommonsLangSrc + + SHA1 + c2b4e1c67a2d28fced849ee1bb76e7391b93f125 + + This file is used by Jena + Copyright 2001-2011 The Apache Software Foundation + Apache Software Foundation + ./lib-source/commons-lang3-3.1-sources.jar + ARCHIVE + Apache-2.0 + Apache-2.0 + Apache Commons Lang +Copyright 2001-2011 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + +This product includes software from the Spring Framework, +under the Apache License 2.0 (see: StringUtils.containsWhitespace()) + + + SPDXRef-JenaLib + + SHA1 + 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 + + This file belongs to Jena + (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + Apache Software Foundation + Hewlett Packard Inc. + ./lib-source/jena-2.6.3-sources.jar + ARCHIVE + This license is used by Jena + LicenseRef-1 + LicenseRef-1 + + + SPDXRef-File + + 2011-01-29T18:30:22Z + OTHER + Person: File Commenter + File level annotation + + + SHA1 + d6a770ba38583ed4bb4525bd96e50461655d2758 + + + MD5 + 624c1abb3664f4b35547e7c73864ad24 + + The concluded license was taken from the package level that the file was included in. +This information was found in the COPYING.txt file in the xyz directory. + Copyright 2008-2010 John Smith + The Regents of the University of California + Modified by Paul Mundt lethal@linux-sh.org + IBM Corporation + ./package/foo.c + SOURCE + The concluded license was taken from the package level that the file was included in. + (LGPL-2.0-only OR LicenseRef-2) + GPL-2.0-only + LicenseRef-2 + Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the �Software�), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED �AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + SPDXRef-Snippet + This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0. + Copyright 2008-2010 John Smith + The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. + GPL-2.0-only + GPL-2.0-only + from linux kernel + + + 420 + SPDXRef-DoapSource + + + 310 + SPDXRef-DoapSource + + + + + 23 + SPDXRef-DoapSource + + + 5 + SPDXRef-DoapSource + + + SPDXRef-DoapSource + + + SPDXRef-DOCUMENT + SPDXRef-Package + CONTAINS + + + SPDXRef-DOCUMENT + DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement + COPY_OF + + + SPDXRef-DOCUMENT + SPDXRef-File + DESCRIBES + + + SPDXRef-DOCUMENT + SPDXRef-Package + DESCRIBES + + + SPDXRef-Package + SPDXRef-JenaLib + CONTAINS + + + SPDXRef-Package + SPDXRef-Saxon + DYNAMIC_LINK + + + SPDXRef-CommonsLangSrc + NOASSERTION + GENERATED_FROM + + + SPDXRef-JenaLib + SPDXRef-Package + CONTAINS + + + SPDXRef-File + SPDXRef-fromDoap-0 + GENERATED_FROM + + diff --git a/tests/spdx/data/formats/SPDXXMLExample-v2.3.spdx.xml b/tests/spdx/data/formats/SPDXXMLExample-v2.3.spdx.xml new file mode 100644 index 000000000..e42b54e0f --- /dev/null +++ b/tests/spdx/data/formats/SPDXXMLExample-v2.3.spdx.xml @@ -0,0 +1,460 @@ + + + SPDXRef-DOCUMENT + SPDX-2.3 + + This package has been shipped in source and binary form. +The binaries were created with gcc 4.5.1 and expect to link to +compatible system run time libraries. + 2010-01-29T18:30:22Z + Tool: LicenseFind-1.0 + Organization: ExampleCodeInspect () + Person: Jane Doe () + 3.17 + + SPDX-Tools-v2.0 + CC0-1.0 + This document was created using SPDX 2.0 using licenses from the web site. + + DocumentRef-spdx-tool-1.2 + + SHA1 + d6a770ba38583ed4bb4525bd96e50461655d2759 + + http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301 + + + LicenseRef-1 + /* + * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + LicenseRef-2 + This package includes the GRDDL parser developed by Hewlett Packard under the following license: +© Copyright 2007 Hewlett-Packard Development Company, LP + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + LicenseRef-4 + /* + * (c) Copyright 2009 University of Bristol + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + LicenseRef-Beerware-4.2 + The beerware license has a couple of other standard variants. + "THE BEER-WARE LICENSE" (Revision 42): +phk@FreeBSD.ORG wrote this file. As long as you retain this notice you +can do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp + Beer-Ware License (Version 42) + http://people.freebsd.org/~phk/ + + + LicenseRef-3 + This is tye CyperNeko License + The CyberNeko Software License, Version 1.0 + + +(C) Copyright 2002-2005, Andy Clark. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. The end-user documentation included with the redistribution, + if any, must include the following acknowledgment: + "This product includes software developed by Andy Clark." + Alternately, this acknowledgment may appear in the software itself, + if and wherever such third-party acknowledgments normally appear. + +4. The names "CyberNeko" and "NekoHTML" must not be used to endorse + or promote products derived from this software without prior + written permission. For written permission, please contact + andyc@cyberneko.net. + +5. Products derived from this software may not be called "CyberNeko", + nor may "CyberNeko" appear in their name, without prior written + permission of the author. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + CyberNeko License + http://people.apache.org/~andyc/neko/LICENSE + http://justasample.url.com + + + 2010-01-29T18:30:22Z + OTHER + Person: Jane Doe () + Document level annotation + + + 2010-02-10T00:00:00Z + REVIEW + Person: Joe Reviewer + This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses + + + 2011-03-13T00:00:00Z + REVIEW + Person: Suzanne Reviewer + Another example reviewer. + + SPDXRef-File + SPDXRef-File + SPDXRef-Package + http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 + + SPDXRef-Package + + 2011-01-29T18:30:22Z + OTHER + Person: Package Commenter + Package level annotation + + The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually. + 2011-01-29T18:30:22Z + + MD5 + 624c1abb3664f4b35547e7c73864ad24 + + + SHA1 + 85ed0817af83a24ad8da68c2b5094de69833983c + + + SHA256 + 11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd + + + BLAKE2b-384 + aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706 + + Copyright 2008-2010 John Smith + The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems. + http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz + + SECURITY + cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:* + cpe23Type + + + This is the external ref for Acme + OTHER + acmecorp/acmenator/4.1.3-alpha + http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge + + true + http://ftp.gnu.org/gnu/glibc + The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change. + (LGPL-2.0-only OR LicenseRef-3) + (LGPL-2.0-only AND LicenseRef-3) + GPL-2.0-only + LicenseRef-2 + LicenseRef-1 + glibc + Organization: ExampleCodeInspect (contact@example.com) + glibc-2.11.1.tar.gz + + ./package.spdx + d6a770ba38583ed4bb4525bd96e50461655d2758 + + SOURCE + SPDXRef-Specification + SPDXRef-Specification + SPDXRef-CommonsLangSrc + SPDXRef-Specification + SPDXRef-CommonsLangSrc + SPDXRef-JenaLib + SPDXRef-Specification + SPDXRef-CommonsLangSrc + SPDXRef-JenaLib + SPDXRef-DoapSource + SPDXRef-Specification + SPDXRef-CommonsLangSrc + SPDXRef-JenaLib + SPDXRef-DoapSource + 2012-01-29T18:30:22Z + uses glibc-2_11-branch from git://sourceware.org/git/glibc.git. + GNU C library. + Person: Jane Doe (jane.doe@example.com) + 2014-01-29T18:30:22Z + 2.11.1 + + + SPDXRef-fromDoap-1 + NOASSERTION + NOASSERTION + false + http://commons.apache.org/proper/commons-lang/ + NOASSERTION + NOASSERTION + Apache Commons Lang + + + SPDXRef-fromDoap-0 + https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz + + PACKAGE-MANAGER + pkg:maven/org.apache.jena/apache-jena@3.12.0 + http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#purl + + false + http://www.openjena.org/ + Jena + 3.12.0 + + + SPDXRef-Saxon + + SHA1 + 85ed0817af83a24ad8da68c2b5094de69833983c + + Copyright Saxonica Ltd + The Saxon package is a collection of tools for processing XML documents. + https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download + false + http://saxon.sourceforge.net/ + Other versions available for a commercial license + MPL-1.0 + MPL-1.0 + Saxon + saxonB-8.8.zip + 8.8 + + + SPDXRef-DoapSource + + SHA1 + 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12 + + Copyright 2010, 2011 Source Auditor Inc. + Protecode Inc. + SPDX Technical Team Members + Open Logic Inc. + Source Auditor Inc. + Black Duck Software In.c + ./src/org/spdx/parser/DOAPProject.java + SOURCE + Apache-2.0 + Apache-2.0 + + + SPDXRef-CommonsLangSrc + + SHA1 + c2b4e1c67a2d28fced849ee1bb76e7391b93f125 + + This file is used by Jena + Copyright 2001-2011 The Apache Software Foundation + Apache Software Foundation + ./lib-source/commons-lang3-3.1-sources.jar + ARCHIVE + Apache-2.0 + Apache-2.0 + Apache Commons Lang +Copyright 2001-2011 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + +This product includes software from the Spring Framework, +under the Apache License 2.0 (see: StringUtils.containsWhitespace()) + + + SPDXRef-JenaLib + + SHA1 + 3ab4e1c67a2d28fced849ee1bb76e7391b93f125 + + This file belongs to Jena + (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP + Apache Software Foundation + Hewlett Packard Inc. + ./lib-source/jena-2.6.3-sources.jar + ARCHIVE + This license is used by Jena + LicenseRef-1 + LicenseRef-1 + + + SPDXRef-Specification + + SHA1 + fff4e1c67a2d28fced849ee1bb76e7391b93f125 + + Specification Documentation + ./docs/myspec.pdf + DOCUMENTATION + + + SPDXRef-File + + 2011-01-29T18:30:22Z + OTHER + Person: File Commenter + File level annotation + + + SHA1 + d6a770ba38583ed4bb4525bd96e50461655d2758 + + + MD5 + 624c1abb3664f4b35547e7c73864ad24 + + The concluded license was taken from the package level that the file was included in. +This information was found in the COPYING.txt file in the xyz directory. + Copyright 2008-2010 John Smith + The Regents of the University of California + Modified by Paul Mundt lethal@linux-sh.org + IBM Corporation + ./package/foo.c + SOURCE + The concluded license was taken from the package level that the file was included in. + (LGPL-2.0-only OR LicenseRef-2) + GPL-2.0-only + LicenseRef-2 + Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + SPDXRef-Snippet + This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0. + Copyright 2008-2010 John Smith + The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz. + GPL-2.0-only + GPL-2.0-only + from linux kernel + + + 420 + SPDXRef-DoapSource + + + 310 + SPDXRef-DoapSource + + + + + 23 + SPDXRef-DoapSource + + + 5 + SPDXRef-DoapSource + + + SPDXRef-DoapSource + + + SPDXRef-DOCUMENT + CONTAINS + SPDXRef-Package + + + SPDXRef-DOCUMENT + COPY_OF + DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement + + + SPDXRef-Package + DYNAMIC_LINK + SPDXRef-Saxon + + + SPDXRef-CommonsLangSrc + GENERATED_FROM + NOASSERTION + + + SPDXRef-JenaLib + CONTAINS + SPDXRef-Package + + + SPDXRef-Specification + SPECIFICATION_FOR + SPDXRef-fromDoap-0 + + + SPDXRef-File + GENERATED_FROM + SPDXRef-fromDoap-0 + + diff --git a/tests/spdx/data/formats/SPDXYAMLExample-v2.2.spdx.yaml b/tests/spdx/data/formats/SPDXYAMLExample-v2.2.spdx.yaml new file mode 100644 index 000000000..d58cf229c --- /dev/null +++ b/tests/spdx/data/formats/SPDXYAMLExample-v2.2.spdx.yaml @@ -0,0 +1,390 @@ +--- +SPDXID: "SPDXRef-DOCUMENT" +spdxVersion: "SPDX-2.2" +creationInfo: + comment: "This package has been shipped in source and binary form.\nThe binaries\ + \ were created with gcc 4.5.1 and expect to link to\ncompatible system run time\ + \ libraries." + created: "2010-01-29T18:30:22Z" + creators: + - "Tool: LicenseFind-1.0" + - "Organization: ExampleCodeInspect ()" + - "Person: Jane Doe ()" + licenseListVersion: "3.9" +name: "SPDX-Tools-v2.0" +dataLicense: "CC0-1.0" +comment: "This document was created using SPDX 2.0 using licenses from the web site." +externalDocumentRefs: +- externalDocumentId: "DocumentRef-spdx-tool-1.2" + checksum: + algorithm: "SHA1" + checksumValue: "d6a770ba38583ed4bb4525bd96e50461655d2759" + spdxDocument: "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301" +hasExtractedLicensingInfos: +- licenseId: "LicenseRef-1" + extractedText: "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,\ + \ 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n\ + \ *\n * Redistribution and use in source and binary forms, with or without\n *\ + \ modification, are permitted provided that the following conditions\n * are met:\n\ + \ * 1. Redistributions of source code must retain the above copyright\n * notice,\ + \ this list of conditions and the following disclaimer.\n * 2. Redistributions\ + \ in binary form must reproduce the above copyright\n * notice, this list of\ + \ conditions and the following disclaimer in the\n * documentation and/or other\ + \ materials provided with the distribution.\n * 3. The name of the author may\ + \ not be used to endorse or promote products\n * derived from this software\ + \ without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED\ + \ BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING,\ + \ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS\ + \ FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE\ + \ LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\ + \ DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\ + \ OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\ + \ CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\ + \ OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\ + \ USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ + */" +- licenseId: "LicenseRef-2" + extractedText: "This package includes the GRDDL parser developed by Hewlett Packard\ + \ under the following license:\n� Copyright 2007 Hewlett-Packard Development Company,\ + \ LP\n\nRedistribution and use in source and binary forms, with or without modification,\ + \ are permitted provided that the following conditions are met: \n\nRedistributions\ + \ of source code must retain the above copyright notice, this list of conditions\ + \ and the following disclaimer. \nRedistributions in binary form must reproduce\ + \ the above copyright notice, this list of conditions and the following disclaimer\ + \ in the documentation and/or other materials provided with the distribution.\ + \ \nThe name of the author may not be used to endorse or promote products derived\ + \ from this software without specific prior written permission. \nTHIS SOFTWARE\ + \ IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\ + \ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\ + \ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE\ + \ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\ + \ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\ + \ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\ + \ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\ + \ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\ + \ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +- licenseId: "LicenseRef-4" + extractedText: "/*\n * (c) Copyright 2009 University of Bristol\n * All rights reserved.\n\ + \ *\n * Redistribution and use in source and binary forms, with or without\n *\ + \ modification, are permitted provided that the following conditions\n * are met:\n\ + \ * 1. Redistributions of source code must retain the above copyright\n * notice,\ + \ this list of conditions and the following disclaimer.\n * 2. Redistributions\ + \ in binary form must reproduce the above copyright\n * notice, this list of\ + \ conditions and the following disclaimer in the\n * documentation and/or other\ + \ materials provided with the distribution.\n * 3. The name of the author may\ + \ not be used to endorse or promote products\n * derived from this software\ + \ without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED\ + \ BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING,\ + \ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS\ + \ FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE\ + \ LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\ + \ DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\ + \ OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\ + \ CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\ + \ OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\ + \ USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ + */" +- licenseId: "LicenseRef-Beerware-4.2" + comment: "The beerware license has a couple of other standard variants." + extractedText: "\"THE BEER-WARE LICENSE\" (Revision 42):\nphk@FreeBSD.ORG wrote\ + \ this file. As long as you retain this notice you\ncan do whatever you want with\ + \ this stuff. If we meet some day, and you think this stuff is worth it, you can\ + \ buy me a beer in return Poul-Henning Kamp" + name: "Beer-Ware License (Version 42)" + seeAlsos: + - "http://people.freebsd.org/~phk/" +- licenseId: "LicenseRef-3" + comment: "This is tye CyperNeko License" + extractedText: "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright\ + \ 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in source\ + \ and binary forms, with or without\nmodification, are permitted provided that\ + \ the following conditions\nare met:\n\n1. Redistributions of source code must\ + \ retain the above copyright\n notice, this list of conditions and the following\ + \ disclaimer. \n\n2. Redistributions in binary form must reproduce the above copyright\n\ + \ notice, this list of conditions and the following disclaimer in\n the documentation\ + \ and/or other materials provided with the\n distribution.\n\n3. The end-user\ + \ documentation included with the redistribution,\n if any, must include the\ + \ following acknowledgment: \n \"This product includes software developed\ + \ by Andy Clark.\"\n Alternately, this acknowledgment may appear in the software\ + \ itself,\n if and wherever such third-party acknowledgments normally appear.\n\ + \n4. The names \"CyberNeko\" and \"NekoHTML\" must not be used to endorse\n \ + \ or promote products derived from this software without prior \n written permission.\ + \ For written permission, please contact \n andyc@cyberneko.net.\n\n5. Products\ + \ derived from this software may not be called \"CyberNeko\",\n nor may \"CyberNeko\"\ + \ appear in their name, without prior written\n permission of the author.\n\n\ + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES,\ + \ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND\ + \ FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR\ + \ OR OTHER CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\ + \ EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\ + \ \nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS\ + \ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT,\ + \ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY\ + \ WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF\ + \ SUCH DAMAGE." + name: "CyberNeko License" + seeAlsos: + - "http://people.apache.org/~andyc/neko/LICENSE" + - "http://justasample.url.com" +annotations: +- annotationDate: "2010-01-29T18:30:22Z" + annotationType: "OTHER" + annotator: "Person: Jane Doe ()" + comment: "Document level annotation" +- annotationDate: "2010-02-10T00:00:00Z" + annotationType: "REVIEW" + annotator: "Person: Joe Reviewer" + comment: "This is just an example. Some of the non-standard licenses look like\ + \ they are actually BSD 3 clause licenses" +- annotationDate: "2011-03-13T00:00:00Z" + annotationType: "REVIEW" + annotator: "Person: Suzanne Reviewer" + comment: "Another example reviewer." +documentNamespace: "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301" +documentDescribes: +- "SPDXRef-File" +- "SPDXRef-Package" +packages: +- SPDXID: "SPDXRef-Package" + annotations: + - annotationDate: "2011-01-29T18:30:22Z" + annotationType: "OTHER" + annotator: "Person: Package Commenter" + comment: "Package level annotation" + attributionTexts: + - "The GNU C Library is free software. See the file COPYING.LIB for copying conditions,\ + \ and LICENSES for notices about a few contributions that require these additional\ + \ notices to be distributed. License copyright years may be listed using range\ + \ notation, e.g., 1996-2015, indicating that every year in the range, inclusive,\ + \ is a copyrightable year that would otherwise be listed individually." + checksums: + - algorithm: "MD5" + checksumValue: "624c1abb3664f4b35547e7c73864ad24" + - algorithm: "SHA1" + checksumValue: "85ed0817af83a24ad8da68c2b5094de69833983c" + - algorithm: "SHA256" + checksumValue: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd" + copyrightText: "Copyright 2008-2010 John Smith" + description: "The GNU C Library defines functions that are specified by the ISO\ + \ C standard, as well as additional features specific to POSIX and other derivatives\ + \ of the Unix operating system, and extensions specific to GNU systems." + downloadLocation: "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz" + externalRefs: + - referenceCategory: "SECURITY" + referenceLocator: "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*" + referenceType: "cpe23Type" + - comment: "This is the external ref for Acme" + referenceCategory: "OTHER" + referenceLocator: "acmecorp/acmenator/4.1.3-alpha" + referenceType: "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge" + filesAnalyzed: true + hasFiles: + - "SPDXRef-CommonsLangSrc" + - "SPDXRef-JenaLib" + - "SPDXRef-DoapSource" + homepage: "http://ftp.gnu.org/gnu/glibc" + licenseComments: "The license for this project changed with the release of version\ + \ x.y. The version of the project included here post-dates the license change." + licenseConcluded: "(LGPL-2.0-only OR LicenseRef-3)" + licenseDeclared: "(LGPL-2.0-only AND LicenseRef-3)" + licenseInfoFromFiles: + - "GPL-2.0-only" + - "LicenseRef-2" + - "LicenseRef-1" + name: "glibc" + originator: "Organization: ExampleCodeInspect (contact@example.com)" + packageFileName: "glibc-2.11.1.tar.gz" + packageVerificationCode: + packageVerificationCodeExcludedFiles: + - "./package.spdx" + packageVerificationCodeValue: "d6a770ba38583ed4bb4525bd96e50461655d2758" + sourceInfo: "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git." + summary: "GNU C library." + supplier: "Person: Jane Doe (jane.doe@example.com)" + versionInfo: "2.11.1" +- SPDXID: "SPDXRef-fromDoap-1" + copyrightText: "NOASSERTION" + downloadLocation: "NOASSERTION" + filesAnalyzed: false + homepage: "http://commons.apache.org/proper/commons-lang/" + licenseConcluded: "NOASSERTION" + licenseDeclared: "NOASSERTION" + name: "Apache Commons Lang" +- SPDXID: "SPDXRef-fromDoap-0" + copyrightText: "NOASSERTION" + downloadLocation: "https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz" + externalRefs: + - referenceCategory: "PACKAGE_MANAGER" + referenceLocator: "pkg:maven/org.apache.jena/apache-jena@3.12.0" + referenceType: "purl" + filesAnalyzed: false + homepage: "http://www.openjena.org/" + licenseConcluded: "NOASSERTION" + licenseDeclared: "NOASSERTION" + name: "Jena" + versionInfo: "3.12.0" +- SPDXID: "SPDXRef-Saxon" + checksums: + - algorithm: "SHA1" + checksumValue: "85ed0817af83a24ad8da68c2b5094de69833983c" + copyrightText: "Copyright Saxonica Ltd" + description: "The Saxon package is a collection of tools for processing XML documents." + downloadLocation: "https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download" + filesAnalyzed: false + homepage: "http://saxon.sourceforge.net/" + licenseComments: "Other versions available for a commercial license" + licenseConcluded: "MPL-1.0" + licenseDeclared: "MPL-1.0" + name: "Saxon" + packageFileName: "saxonB-8.8.zip" + versionInfo: "8.8" +files: +- SPDXID: "SPDXRef-DoapSource" + checksums: + - algorithm: "SHA1" + checksumValue: "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" + copyrightText: "Copyright 2010, 2011 Source Auditor Inc." + fileContributors: + - "Protecode Inc." + - "SPDX Technical Team Members" + - "Open Logic Inc." + - "Source Auditor Inc." + - "Black Duck Software In.c" + fileName: "./src/org/spdx/parser/DOAPProject.java" + fileTypes: + - "SOURCE" + licenseConcluded: "Apache-2.0" + licenseInfoInFiles: + - "Apache-2.0" +- SPDXID: "SPDXRef-CommonsLangSrc" + checksums: + - algorithm: "SHA1" + checksumValue: "c2b4e1c67a2d28fced849ee1bb76e7391b93f125" + comment: "This file is used by Jena" + copyrightText: "Copyright 2001-2011 The Apache Software Foundation" + fileContributors: + - "Apache Software Foundation" + fileName: "./lib-source/commons-lang3-3.1-sources.jar" + fileTypes: + - "ARCHIVE" + licenseConcluded: "Apache-2.0" + licenseInfoInFiles: + - "Apache-2.0" + noticeText: "Apache Commons Lang\nCopyright 2001-2011 The Apache Software Foundation\n\ + \nThis product includes software developed by\nThe Apache Software Foundation\ + \ (http://www.apache.org/).\n\nThis product includes software from the Spring\ + \ Framework,\nunder the Apache License 2.0 (see: StringUtils.containsWhitespace())" +- SPDXID: "SPDXRef-JenaLib" + checksums: + - algorithm: "SHA1" + checksumValue: "3ab4e1c67a2d28fced849ee1bb76e7391b93f125" + comment: "This file belongs to Jena" + copyrightText: "(c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,\ + \ 2009 Hewlett-Packard Development Company, LP" + fileContributors: + - "Apache Software Foundation" + - "Hewlett Packard Inc." + fileName: "./lib-source/jena-2.6.3-sources.jar" + fileTypes: + - "ARCHIVE" + licenseComments: "This license is used by Jena" + licenseConcluded: "LicenseRef-1" + licenseInfoInFiles: + - "LicenseRef-1" +- SPDXID: "SPDXRef-File" + annotations: + - annotationDate: "2011-01-29T18:30:22Z" + annotationType: "OTHER" + annotator: "Person: File Commenter" + comment: "File level annotation" + checksums: + - algorithm: "SHA1" + checksumValue: "d6a770ba38583ed4bb4525bd96e50461655d2758" + - algorithm: "MD5" + checksumValue: "624c1abb3664f4b35547e7c73864ad24" + comment: "The concluded license was taken from the package level that the file was\ + \ included in.\nThis information was found in the COPYING.txt file in the xyz\ + \ directory." + copyrightText: "Copyright 2008-2010 John Smith" + fileContributors: + - "The Regents of the University of California" + - "Modified by Paul Mundt lethal@linux-sh.org" + - "IBM Corporation" + fileName: "./package/foo.c" + fileTypes: + - "SOURCE" + licenseComments: "The concluded license was taken from the package level that the\ + \ file was included in." + licenseConcluded: "(LGPL-2.0-only OR LicenseRef-2)" + licenseInfoInFiles: + - "GPL-2.0-only" + - "LicenseRef-2" + noticeText: "Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is\ + \ hereby granted, free of charge, to any person obtaining a copy of this software\ + \ and associated documentation files (the �Software�), to deal in the Software\ + \ without restriction, including without limitation the rights to use, copy, modify,\ + \ merge, publish, distribute, sublicense, and/or sell copies of the Software,\ + \ and to permit persons to whom the Software is furnished to do so, subject to\ + \ the following conditions: \nThe above copyright notice and this permission notice\ + \ shall be included in all copies or substantial portions of the Software.\n\n\ + THE SOFTWARE IS PROVIDED �AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\ + \ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR\ + \ A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\ + \ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\ + \ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\ + \ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." +snippets: +- SPDXID: "SPDXRef-Snippet" + comment: "This snippet was identified as significant and highlighted in this Apache-2.0\ + \ file, when a commercial scanner identified it as being derived from file foo.c\ + \ in package xyz which is licensed under GPL-2.0." + copyrightText: "Copyright 2008-2010 John Smith" + licenseComments: "The concluded license was taken from package xyz, from which the\ + \ snippet was copied into the current file. The concluded license information\ + \ was found in the COPYING.txt file in package xyz." + licenseConcluded: "GPL-2.0-only" + licenseInfoInSnippets: + - "GPL-2.0-only" + name: "from linux kernel" + ranges: + - endPointer: + offset: 420 + reference: "SPDXRef-DoapSource" + startPointer: + offset: 310 + reference: "SPDXRef-DoapSource" + - endPointer: + lineNumber: 23 + reference: "SPDXRef-DoapSource" + startPointer: + lineNumber: 5 + reference: "SPDXRef-DoapSource" + snippetFromFile: "SPDXRef-DoapSource" +relationships: +- spdxElementId: "SPDXRef-DOCUMENT" + relatedSpdxElement: "SPDXRef-Package" + relationshipType: "CONTAINS" +- spdxElementId: "SPDXRef-DOCUMENT" + relatedSpdxElement: "DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement" + relationshipType: "COPY_OF" +- spdxElementId: "SPDXRef-DOCUMENT" + relatedSpdxElement: "SPDXRef-File" + relationshipType: "DESCRIBES" +- spdxElementId: "SPDXRef-DOCUMENT" + relatedSpdxElement: "SPDXRef-Package" + relationshipType: "DESCRIBES" +- spdxElementId: "SPDXRef-Package" + relatedSpdxElement: "SPDXRef-JenaLib" + relationshipType: "CONTAINS" +- spdxElementId: "SPDXRef-Package" + relatedSpdxElement: "SPDXRef-Saxon" + relationshipType: "DYNAMIC_LINK" +- spdxElementId: "SPDXRef-CommonsLangSrc" + relatedSpdxElement: "NOASSERTION" + relationshipType: "GENERATED_FROM" +- spdxElementId: "SPDXRef-JenaLib" + relatedSpdxElement: "SPDXRef-Package" + relationshipType: "CONTAINS" +- spdxElementId: "SPDXRef-File" + relatedSpdxElement: "SPDXRef-fromDoap-0" + relationshipType: "GENERATED_FROM" diff --git a/tests/spdx/data/formats/SPDXYAMLExample-v2.3.spdx.yaml b/tests/spdx/data/formats/SPDXYAMLExample-v2.3.spdx.yaml new file mode 100644 index 000000000..e0190e38b --- /dev/null +++ b/tests/spdx/data/formats/SPDXYAMLExample-v2.3.spdx.yaml @@ -0,0 +1,406 @@ +--- +SPDXID: "SPDXRef-DOCUMENT" +spdxVersion: "SPDX-2.3" +creationInfo: + comment: "This package has been shipped in source and binary form.\nThe binaries\ + \ were created with gcc 4.5.1 and expect to link to\ncompatible system run time\ + \ libraries." + created: "2010-01-29T18:30:22Z" + creators: + - "Tool: LicenseFind-1.0" + - "Organization: ExampleCodeInspect ()" + - "Person: Jane Doe ()" + licenseListVersion: "3.17" +name: "SPDX-Tools-v2.0" +dataLicense: "CC0-1.0" +comment: "This document was created using SPDX 2.0 using licenses from the web site." +externalDocumentRefs: +- externalDocumentId: "DocumentRef-spdx-tool-1.2" + checksum: + algorithm: "SHA1" + checksumValue: "d6a770ba38583ed4bb4525bd96e50461655d2759" + spdxDocument: "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301" +hasExtractedLicensingInfos: +- licenseId: "LicenseRef-1" + extractedText: "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,\ + \ 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n\ + \ *\n * Redistribution and use in source and binary forms, with or without\n *\ + \ modification, are permitted provided that the following conditions\n * are met:\n\ + \ * 1. Redistributions of source code must retain the above copyright\n * notice,\ + \ this list of conditions and the following disclaimer.\n * 2. Redistributions\ + \ in binary form must reproduce the above copyright\n * notice, this list of\ + \ conditions and the following disclaimer in the\n * documentation and/or other\ + \ materials provided with the distribution.\n * 3. The name of the author may\ + \ not be used to endorse or promote products\n * derived from this software\ + \ without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED\ + \ BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING,\ + \ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS\ + \ FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE\ + \ LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\ + \ DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\ + \ OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\ + \ CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\ + \ OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\ + \ USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ + */" +- licenseId: "LicenseRef-2" + extractedText: "This package includes the GRDDL parser developed by Hewlett Packard\ + \ under the following license:\n© Copyright 2007 Hewlett-Packard Development Company,\ + \ LP\n\nRedistribution and use in source and binary forms, with or without modification,\ + \ are permitted provided that the following conditions are met: \n\nRedistributions\ + \ of source code must retain the above copyright notice, this list of conditions\ + \ and the following disclaimer. \nRedistributions in binary form must reproduce\ + \ the above copyright notice, this list of conditions and the following disclaimer\ + \ in the documentation and/or other materials provided with the distribution.\ + \ \nThe name of the author may not be used to endorse or promote products derived\ + \ from this software without specific prior written permission. \nTHIS SOFTWARE\ + \ IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\ + \ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\ + \ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE\ + \ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\ + \ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\ + \ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\ + \ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\ + \ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\ + \ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +- licenseId: "LicenseRef-4" + extractedText: "/*\n * (c) Copyright 2009 University of Bristol\n * All rights reserved.\n\ + \ *\n * Redistribution and use in source and binary forms, with or without\n *\ + \ modification, are permitted provided that the following conditions\n * are met:\n\ + \ * 1. Redistributions of source code must retain the above copyright\n * notice,\ + \ this list of conditions and the following disclaimer.\n * 2. Redistributions\ + \ in binary form must reproduce the above copyright\n * notice, this list of\ + \ conditions and the following disclaimer in the\n * documentation and/or other\ + \ materials provided with the distribution.\n * 3. The name of the author may\ + \ not be used to endorse or promote products\n * derived from this software\ + \ without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED\ + \ BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING,\ + \ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS\ + \ FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE\ + \ LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\ + \ DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\ + \ OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\ + \ CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\ + \ OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE\ + \ USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\ + */" +- licenseId: "LicenseRef-Beerware-4.2" + comment: "The beerware license has a couple of other standard variants." + extractedText: "\"THE BEER-WARE LICENSE\" (Revision 42):\nphk@FreeBSD.ORG wrote\ + \ this file. As long as you retain this notice you\ncan do whatever you want with\ + \ this stuff. If we meet some day, and you think this stuff is worth it, you can\ + \ buy me a beer in return Poul-Henning Kamp" + name: "Beer-Ware License (Version 42)" + seeAlsos: + - "http://people.freebsd.org/~phk/" +- licenseId: "LicenseRef-3" + comment: "This is tye CyperNeko License" + extractedText: "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright\ + \ 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in source\ + \ and binary forms, with or without\nmodification, are permitted provided that\ + \ the following conditions\nare met:\n\n1. Redistributions of source code must\ + \ retain the above copyright\n notice, this list of conditions and the following\ + \ disclaimer. \n\n2. Redistributions in binary form must reproduce the above copyright\n\ + \ notice, this list of conditions and the following disclaimer in\n the documentation\ + \ and/or other materials provided with the\n distribution.\n\n3. The end-user\ + \ documentation included with the redistribution,\n if any, must include the\ + \ following acknowledgment: \n \"This product includes software developed\ + \ by Andy Clark.\"\n Alternately, this acknowledgment may appear in the software\ + \ itself,\n if and wherever such third-party acknowledgments normally appear.\n\ + \n4. The names \"CyberNeko\" and \"NekoHTML\" must not be used to endorse\n \ + \ or promote products derived from this software without prior \n written permission.\ + \ For written permission, please contact \n andyc@cyberneko.net.\n\n5. Products\ + \ derived from this software may not be called \"CyberNeko\",\n nor may \"CyberNeko\"\ + \ appear in their name, without prior written\n permission of the author.\n\n\ + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES,\ + \ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND\ + \ FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR\ + \ OR OTHER CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\ + \ EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\ + \ \nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS\ + \ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT,\ + \ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY\ + \ WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF\ + \ SUCH DAMAGE." + name: "CyberNeko License" + seeAlsos: + - "http://people.apache.org/~andyc/neko/LICENSE" + - "http://justasample.url.com" +annotations: +- annotationDate: "2010-01-29T18:30:22Z" + annotationType: "OTHER" + annotator: "Person: Jane Doe ()" + comment: "Document level annotation" +- annotationDate: "2010-02-10T00:00:00Z" + annotationType: "REVIEW" + annotator: "Person: Joe Reviewer" + comment: "This is just an example. Some of the non-standard licenses look like\ + \ they are actually BSD 3 clause licenses" +- annotationDate: "2011-03-13T00:00:00Z" + annotationType: "REVIEW" + annotator: "Person: Suzanne Reviewer" + comment: "Another example reviewer." +documentDescribes: +- "SPDXRef-File" +- "SPDXRef-Package" +documentNamespace: "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301" +packages: +- SPDXID: "SPDXRef-Package" + annotations: + - annotationDate: "2011-01-29T18:30:22Z" + annotationType: "OTHER" + annotator: "Person: Package Commenter" + comment: "Package level annotation" + attributionTexts: + - "The GNU C Library is free software. See the file COPYING.LIB for copying conditions,\ + \ and LICENSES for notices about a few contributions that require these additional\ + \ notices to be distributed. License copyright years may be listed using range\ + \ notation, e.g., 1996-2015, indicating that every year in the range, inclusive,\ + \ is a copyrightable year that would otherwise be listed individually." + builtDate: "2011-01-29T18:30:22Z" + checksums: + - algorithm: "MD5" + checksumValue: "624c1abb3664f4b35547e7c73864ad24" + - algorithm: "SHA1" + checksumValue: "85ed0817af83a24ad8da68c2b5094de69833983c" + - algorithm: "SHA256" + checksumValue: "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd" + - algorithm: "BLAKE2b-384" + checksumValue: "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706" + copyrightText: "Copyright 2008-2010 John Smith" + description: "The GNU C Library defines functions that are specified by the ISO\ + \ C standard, as well as additional features specific to POSIX and other derivatives\ + \ of the Unix operating system, and extensions specific to GNU systems." + downloadLocation: "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz" + externalRefs: + - referenceCategory: "SECURITY" + referenceLocator: "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*" + referenceType: "cpe23Type" + - comment: "This is the external ref for Acme" + referenceCategory: "OTHER" + referenceLocator: "acmecorp/acmenator/4.1.3-alpha" + referenceType: "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge" + filesAnalyzed: true + homepage: "http://ftp.gnu.org/gnu/glibc" + licenseComments: "The license for this project changed with the release of version\ + \ x.y. The version of the project included here post-dates the license change." + licenseConcluded: "(LGPL-2.0-only OR LicenseRef-3)" + licenseDeclared: "(LGPL-2.0-only AND LicenseRef-3)" + licenseInfoFromFiles: + - "GPL-2.0-only" + - "LicenseRef-2" + - "LicenseRef-1" + name: "glibc" + originator: "Organization: ExampleCodeInspect (contact@example.com)" + packageFileName: "glibc-2.11.1.tar.gz" + packageVerificationCode: + packageVerificationCodeExcludedFiles: + - "./package.spdx" + packageVerificationCodeValue: "d6a770ba38583ed4bb4525bd96e50461655d2758" + primaryPackagePurpose: "SOURCE" + hasFiles: + - "SPDXRef-Specification" + - "SPDXRef-Specification" + - "SPDXRef-CommonsLangSrc" + - "SPDXRef-Specification" + - "SPDXRef-CommonsLangSrc" + - "SPDXRef-JenaLib" + - "SPDXRef-Specification" + - "SPDXRef-CommonsLangSrc" + - "SPDXRef-JenaLib" + - "SPDXRef-DoapSource" + - "SPDXRef-Specification" + - "SPDXRef-CommonsLangSrc" + - "SPDXRef-JenaLib" + - "SPDXRef-DoapSource" + releaseDate: "2012-01-29T18:30:22Z" + sourceInfo: "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git." + summary: "GNU C library." + supplier: "Person: Jane Doe (jane.doe@example.com)" + validUntilDate: "2014-01-29T18:30:22Z" + versionInfo: "2.11.1" +- SPDXID: "SPDXRef-fromDoap-1" + copyrightText: "NOASSERTION" + downloadLocation: "NOASSERTION" + filesAnalyzed: false + homepage: "http://commons.apache.org/proper/commons-lang/" + licenseConcluded: "NOASSERTION" + licenseDeclared: "NOASSERTION" + name: "Apache Commons Lang" +- SPDXID: "SPDXRef-fromDoap-0" + downloadLocation: "https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz" + externalRefs: + - referenceCategory: "PACKAGE-MANAGER" + referenceLocator: "pkg:maven/org.apache.jena/apache-jena@3.12.0" + referenceType: "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#purl" + filesAnalyzed: false + homepage: "http://www.openjena.org/" + name: "Jena" + versionInfo: "3.12.0" +- SPDXID: "SPDXRef-Saxon" + checksums: + - algorithm: "SHA1" + checksumValue: "85ed0817af83a24ad8da68c2b5094de69833983c" + copyrightText: "Copyright Saxonica Ltd" + description: "The Saxon package is a collection of tools for processing XML documents." + downloadLocation: "https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download" + filesAnalyzed: false + homepage: "http://saxon.sourceforge.net/" + licenseComments: "Other versions available for a commercial license" + licenseConcluded: "MPL-1.0" + licenseDeclared: "MPL-1.0" + name: "Saxon" + packageFileName: "saxonB-8.8.zip" + versionInfo: "8.8" +files: +- SPDXID: "SPDXRef-DoapSource" + checksums: + - algorithm: "SHA1" + checksumValue: "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" + copyrightText: "Copyright 2010, 2011 Source Auditor Inc." + fileContributors: + - "Protecode Inc." + - "SPDX Technical Team Members" + - "Open Logic Inc." + - "Source Auditor Inc." + - "Black Duck Software In.c" + fileName: "./src/org/spdx/parser/DOAPProject.java" + fileTypes: + - "SOURCE" + licenseConcluded: "Apache-2.0" + licenseInfoInFiles: + - "Apache-2.0" +- SPDXID: "SPDXRef-CommonsLangSrc" + checksums: + - algorithm: "SHA1" + checksumValue: "c2b4e1c67a2d28fced849ee1bb76e7391b93f125" + comment: "This file is used by Jena" + copyrightText: "Copyright 2001-2011 The Apache Software Foundation" + fileContributors: + - "Apache Software Foundation" + fileName: "./lib-source/commons-lang3-3.1-sources.jar" + fileTypes: + - "ARCHIVE" + licenseConcluded: "Apache-2.0" + licenseInfoInFiles: + - "Apache-2.0" + noticeText: "Apache Commons Lang\nCopyright 2001-2011 The Apache Software Foundation\n\ + \nThis product includes software developed by\nThe Apache Software Foundation\ + \ (http://www.apache.org/).\n\nThis product includes software from the Spring\ + \ Framework,\nunder the Apache License 2.0 (see: StringUtils.containsWhitespace())" +- SPDXID: "SPDXRef-JenaLib" + checksums: + - algorithm: "SHA1" + checksumValue: "3ab4e1c67a2d28fced849ee1bb76e7391b93f125" + comment: "This file belongs to Jena" + copyrightText: "(c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,\ + \ 2009 Hewlett-Packard Development Company, LP" + fileContributors: + - "Apache Software Foundation" + - "Hewlett Packard Inc." + fileName: "./lib-source/jena-2.6.3-sources.jar" + fileTypes: + - "ARCHIVE" + licenseComments: "This license is used by Jena" + licenseConcluded: "LicenseRef-1" + licenseInfoInFiles: + - "LicenseRef-1" +- SPDXID: "SPDXRef-Specification" + checksums: + - algorithm: "SHA1" + checksumValue: "fff4e1c67a2d28fced849ee1bb76e7391b93f125" + comment: "Specification Documentation" + fileName: "./docs/myspec.pdf" + fileTypes: + - "DOCUMENTATION" +- SPDXID: "SPDXRef-File" + annotations: + - annotationDate: "2011-01-29T18:30:22Z" + annotationType: "OTHER" + annotator: "Person: File Commenter" + comment: "File level annotation" + checksums: + - algorithm: "SHA1" + checksumValue: "d6a770ba38583ed4bb4525bd96e50461655d2758" + - algorithm: "MD5" + checksumValue: "624c1abb3664f4b35547e7c73864ad24" + comment: "The concluded license was taken from the package level that the file was\ + \ included in.\nThis information was found in the COPYING.txt file in the xyz\ + \ directory." + copyrightText: "Copyright 2008-2010 John Smith" + fileContributors: + - "The Regents of the University of California" + - "Modified by Paul Mundt lethal@linux-sh.org" + - "IBM Corporation" + fileName: "./package/foo.c" + fileTypes: + - "SOURCE" + licenseComments: "The concluded license was taken from the package level that the\ + \ file was included in." + licenseConcluded: "(LGPL-2.0-only OR LicenseRef-2)" + licenseInfoInFiles: + - "GPL-2.0-only" + - "LicenseRef-2" + noticeText: "Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is\ + \ hereby granted, free of charge, to any person obtaining a copy of this software\ + \ and associated documentation files (the \"Software\"), to deal in the Software\ + \ without restriction, including without limitation the rights to use, copy, modify,\ + \ merge, publish, distribute, sublicense, and/or sell copies of the Software,\ + \ and to permit persons to whom the Software is furnished to do so, subject to\ + \ the following conditions: \nThe above copyright notice and this permission notice\ + \ shall be included in all copies or substantial portions of the Software.\n\n\ + THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\ + \ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR\ + \ A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\ + \ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\ + \ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\ + \ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." +snippets: +- SPDXID: "SPDXRef-Snippet" + comment: "This snippet was identified as significant and highlighted in this Apache-2.0\ + \ file, when a commercial scanner identified it as being derived from file foo.c\ + \ in package xyz which is licensed under GPL-2.0." + copyrightText: "Copyright 2008-2010 John Smith" + licenseComments: "The concluded license was taken from package xyz, from which the\ + \ snippet was copied into the current file. The concluded license information\ + \ was found in the COPYING.txt file in package xyz." + licenseConcluded: "GPL-2.0-only" + licenseInfoInSnippets: + - "GPL-2.0-only" + name: "from linux kernel" + ranges: + - endPointer: + offset: 420 + reference: "SPDXRef-DoapSource" + startPointer: + offset: 310 + reference: "SPDXRef-DoapSource" + - endPointer: + lineNumber: 23 + reference: "SPDXRef-DoapSource" + startPointer: + lineNumber: 5 + reference: "SPDXRef-DoapSource" + snippetFromFile: "SPDXRef-DoapSource" +relationships: +- spdxElementId: "SPDXRef-DOCUMENT" + relationshipType: "CONTAINS" + relatedSpdxElement: "SPDXRef-Package" +- spdxElementId: "SPDXRef-DOCUMENT" + relationshipType: "COPY_OF" + relatedSpdxElement: "DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement" +- spdxElementId: "SPDXRef-Package" + relationshipType: "DYNAMIC_LINK" + relatedSpdxElement: "SPDXRef-Saxon" +- spdxElementId: "SPDXRef-CommonsLangSrc" + relationshipType: "GENERATED_FROM" + relatedSpdxElement: "NOASSERTION" +- spdxElementId: "SPDXRef-JenaLib" + relationshipType: "CONTAINS" + relatedSpdxElement: "SPDXRef-Package" +- spdxElementId: "SPDXRef-Specification" + relationshipType: "SPECIFICATION_FOR" + relatedSpdxElement: "SPDXRef-fromDoap-0" +- spdxElementId: "SPDXRef-File" + relationshipType: "GENERATED_FROM" + relatedSpdxElement: "SPDXRef-fromDoap-0" diff --git a/tests/spdx/parser/json/__init__.py b/tests/spdx/parser/all_formats/__init__.py similarity index 100% rename from tests/spdx/parser/json/__init__.py rename to tests/spdx/parser/all_formats/__init__.py diff --git a/tests/spdx/parser/all_formats/test_parse_from_file.py b/tests/spdx/parser/all_formats/test_parse_from_file.py new file mode 100644 index 000000000..fe7b54f01 --- /dev/null +++ b/tests/spdx/parser/all_formats/test_parse_from_file.py @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +import os + +import pytest + +from spdx.model.document import Document +from spdx.parser.json import json_parser +from spdx.parser.rdf import rdf_parser +from spdx.parser.tagvalue import tagvalue_parser +from spdx.parser.xml import xml_parser +from spdx.parser.yaml import yaml_parser + + +@pytest.mark.parametrize( + "parser, format_name, extension", + [ + (json_parser, "JSON", ".json"), + (xml_parser, "XML", ".xml"), + (yaml_parser, "YAML", ".yaml"), + (rdf_parser, "Rdf", ".rdf.xml"), + (tagvalue_parser, "Tag", ""), + ], +) +class TestParseFromFile: + def test_parse_from_file_not_found(self, parser, format_name, extension): + with pytest.raises(FileNotFoundError) as err: + wrong_file_path = os.path.join(os.path.dirname(__file__), f"hnjfkjsedhnflsiafg.spdx{extension}") + parser.parse_from_file(wrong_file_path) + + assert err.value.args[1] == "No such file or directory" + + def test_parse_from_file_with_2_3_example(self, parser, format_name, extension): + doc = parser.parse_from_file( + os.path.join( + os.path.dirname(__file__), f"../../data/formats/SPDX{format_name}Example-v2.3.spdx{extension}" + ) + ) + assert type(doc) == Document + assert len(doc.annotations) == 5 + assert len(doc.files) == 5 + assert len(doc.packages) == 4 + assert len(doc.snippets) == 1 + assert len(doc.relationships) == 13 + assert len(doc.extracted_licensing_info) == 5 + + def test_parse_json_with_2_2_example(self, parser, format_name, extension): + doc = parser.parse_from_file( + os.path.join( + os.path.dirname(__file__), f"../../data/formats/SPDX{format_name}Example-v2.2.spdx{extension}" + ) + ) + assert type(doc) == Document + assert len(doc.annotations) == 5 + assert len(doc.files) == 4 + assert len(doc.packages) == 4 + assert len(doc.snippets) == 1 + assert len(doc.relationships) == 11 + assert len(doc.extracted_licensing_info) == 5 diff --git a/tests/spdx/parser/json/test_json_parser.py b/tests/spdx/parser/json/test_json_parser.py deleted file mode 100644 index ac3fb684b..000000000 --- a/tests/spdx/parser/json/test_json_parser.py +++ /dev/null @@ -1,44 +0,0 @@ -# SPDX-FileCopyrightText: 2022 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 - -import os - -import pytest - -from spdx.model.document import Document -from spdx.parser.json import json_parser - - -def test_parse_json_file_not_found(): - with pytest.raises(FileNotFoundError) as err: - wrong_file_path = os.path.join(os.path.dirname(__file__), "hnjfkjsedhnflsiafg.json") - json_parser.parse_from_file(wrong_file_path) - - assert err.value.args[1] == "No such file or directory" - - -def test_parse_json_with_2_3_example(): - doc = json_parser.parse_from_file( - os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXJSONExample-v2.3.spdx.json") - ) - assert type(doc) == Document - assert len(doc.annotations) == 5 - assert len(doc.files) == 5 - assert len(doc.packages) == 4 - assert len(doc.snippets) == 1 - assert len(doc.relationships) == 13 - assert len(doc.extracted_licensing_info) == 5 - - -def test_parse_json_with_2_2_example(): - doc = json_parser.parse_from_file( - os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXJSONExample-v2.2.spdx.json") - ) - assert type(doc) == Document - assert len(doc.annotations) == 5 - assert len(doc.files) == 4 - assert len(doc.packages) == 4 - assert len(doc.snippets) == 1 - assert len(doc.relationships) == 11 - assert len(doc.extracted_licensing_info) == 5 diff --git a/tests/spdx/parser/rdf/test_rdf_parser.py b/tests/spdx/parser/rdf/test_rdf_parser.py deleted file mode 100644 index ca1233c15..000000000 --- a/tests/spdx/parser/rdf/test_rdf_parser.py +++ /dev/null @@ -1,48 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -import os - -import pytest - -from spdx.model.document import Document -from spdx.parser.rdf import rdf_parser -from spdx.validation.document_validator import validate_full_spdx_document - - -def test_rdf_parser_file_not_found(): - with pytest.raises(FileNotFoundError, match="No such file or directory"): - wrong_file_path = os.path.join(os.path.dirname(__file__), "hnjfkjsedhnflsiafg.json") - rdf_parser.parse_from_file(wrong_file_path) - - -def test_rdf_parser_with_2_3_example(): - doc = rdf_parser.parse_from_file( - os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXRdfExample-v2.3.spdx.rdf.xml") - ) - validation_messages = validate_full_spdx_document(doc) - - assert validation_messages == [] - assert type(doc) == Document - assert len(doc.snippets) == 1 - assert len(doc.files) == 5 - assert len(doc.annotations) == 5 - assert len(doc.packages) == 4 - assert len(doc.relationships) == 13 - assert len(doc.extracted_licensing_info) == 5 - - -def test_rdf_parser_with_2_2_example(): - doc = rdf_parser.parse_from_file( - os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXRdfExample-v2.2.spdx.rdf.xml") - ) - validation_messages = validate_full_spdx_document(doc) - - assert validation_messages == [] - assert type(doc) == Document - assert len(doc.snippets) == 1 - assert len(doc.files) == 4 - assert len(doc.annotations) == 5 - assert len(doc.packages) == 4 - assert len(doc.relationships) == 11 - assert len(doc.extracted_licensing_info) == 5 diff --git a/tests/spdx/parser/tagvalue/test_tag_value_parser.py b/tests/spdx/parser/tagvalue/test_tag_value_parser.py index f9b6d16cd..44b4375e9 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_parser.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_parser.py @@ -2,12 +2,10 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -import os import pytest from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.document import Document from spdx.model.relationship import Relationship, RelationshipType from spdx.parser.error import SPDXParsingError from spdx.parser.tagvalue.parser import Parser @@ -22,22 +20,6 @@ def test_parse_unknown_tag(): parser.parse(unknown_tag_str) -def test_tag_value_parser(): - parser = Parser() - fn = os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXTagExample-v2.3.spdx") - - with open(fn) as f: - data = f.read() - doc = parser.parse(data) - assert type(doc) == Document - assert len(doc.annotations) == 5 - assert len(doc.files) == 5 - assert len(doc.packages) == 4 - assert len(doc.snippets) == 1 - assert len(doc.relationships) == 13 - assert len(doc.extracted_licensing_info) == 5 - - def test_building_contains_relationship(): parser = Parser() document_str = "\n".join( From 0138e9c5e321fd54f3f7b845dc67d52cc195f824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 12 Apr 2023 15:48:27 +0200 Subject: [PATCH 049/354] [refactor] move test data from data/formats to data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .github/workflows/install_and_test.yml | 2 +- README.md | 10 +++++----- .../data/{formats => }/SPDXJSONExample-v2.2.spdx.json | 0 .../data/{formats => }/SPDXJSONExample-v2.3.spdx.json | 0 .../{formats => }/SPDXRdfExample-v2.2.spdx.rdf.xml | 0 .../{formats => }/SPDXRdfExample-v2.3.spdx.rdf.xml | 0 tests/spdx/data/{formats => }/SPDXTagExample-v2.2.spdx | 0 tests/spdx/data/{formats => }/SPDXTagExample-v2.3.spdx | 0 .../data/{formats => }/SPDXXMLExample-v2.2.spdx.xml | 0 .../data/{formats => }/SPDXXMLExample-v2.3.spdx.xml | 0 .../data/{formats => }/SPDXYAMLExample-v2.2.spdx.yaml | 0 .../data/{formats => }/SPDXYAMLExample-v2.3.spdx.yaml | 0 tests/spdx/parser/all_formats/test_parse_from_file.py | 8 ++------ .../spdx/parser/rdf/test_license_expression_parser.py | 2 +- tests/spdx/test_graph_generation.py | 2 +- 15 files changed, 10 insertions(+), 14 deletions(-) rename tests/spdx/data/{formats => }/SPDXJSONExample-v2.2.spdx.json (100%) rename tests/spdx/data/{formats => }/SPDXJSONExample-v2.3.spdx.json (100%) rename tests/spdx/data/{formats => }/SPDXRdfExample-v2.2.spdx.rdf.xml (100%) rename tests/spdx/data/{formats => }/SPDXRdfExample-v2.3.spdx.rdf.xml (100%) rename tests/spdx/data/{formats => }/SPDXTagExample-v2.2.spdx (100%) rename tests/spdx/data/{formats => }/SPDXTagExample-v2.3.spdx (100%) rename tests/spdx/data/{formats => }/SPDXXMLExample-v2.2.spdx.xml (100%) rename tests/spdx/data/{formats => }/SPDXXMLExample-v2.3.spdx.xml (100%) rename tests/spdx/data/{formats => }/SPDXYAMLExample-v2.2.spdx.yaml (100%) rename tests/spdx/data/{formats => }/SPDXYAMLExample-v2.3.spdx.yaml (100%) diff --git a/.github/workflows/install_and_test.yml b/.github/workflows/install_and_test.yml index a23887e4b..f0fae5a3c 100644 --- a/.github/workflows/install_and_test.yml +++ b/.github/workflows/install_and_test.yml @@ -32,7 +32,7 @@ jobs: - name: Run tests run: pytest - name: Run CLI - run: pyspdxtools -i ./tests/spdx/data/formats/SPDXJSONExample-v2.3.spdx.json + run: pyspdxtools -i ./tests/spdx/data/SPDXJSONExample-v2.3.spdx.json - name: Install optional dependencies run: python -m pip install networkx diff --git a/README.md b/README.md index 3aa762980..41f2580d6 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ instead of `bin`. * Use `pyspdxtools -i ` where `` is the location of the file. The input format is inferred automatically from the file ending. * If you are using a source distribution, try running: - `pyspdxtools -i tests/data/formats/SPDXJSONExample-v2.3.spdx.json` + `pyspdxtools -i tests/data/SPDXJSONExample-v2.3.spdx.json` 2. **CONVERTING** (for converting one format to another): @@ -72,10 +72,10 @@ instead of `bin`. and `` is the location of the output file. The input and output formats are inferred automatically from the file endings. * If you are using a source distribution, try running: - `pyspdxtools -i tests/data/formats/SPDXJSONExample-v2.3.spdx.json -o output.tag` + `pyspdxtools -i tests/data/SPDXJSONExample-v2.3.spdx.json -o output.tag` * If you want to skip the validation process, provide the `--novalidation` flag, like so: - `pyspdxtools -i tests/data/formats/SPDXJSONExample-v2.3.spdx.json -o output.tag --novalidation` + `pyspdxtools -i tests/data/SPDXJSONExample-v2.3.spdx.json -o output.tag --novalidation` (use this with caution: note that undetected invalid documents may lead to unexpected behavior of the tool) * For help use `pyspdxtools --help` @@ -83,13 +83,13 @@ instead of `bin`. 3. **GRAPH GENERATION** (optional feature) * This feature generates a graph representing all elements in the SPDX document and their connections based on the provided - relationships. The graph can be rendered to a picture. Below is an example for the file `tests/data/formats/SPDXJSONExample-v2.3.spdx.json`: + relationships. The graph can be rendered to a picture. Below is an example for the file `tests/data/SPDXJSONExample-v2.3.spdx.json`: ![SPDXJSONExample-v2.3.spdx.png](assets/SPDXJSONExample-v2.3.spdx.png) * Make sure you install the optional dependencies `networkx` and `pygraphviz`. To do so run `pip install ".[graph_generation]"`. * Use `pyspdxtools -i --graph -o ` where `` is an output file name with valid format for `pygraphviz` (check the documentation [here](https://pygraphviz.github.io/documentation/stable/reference/agraph.html#pygraphviz.AGraph.draw)). * If you are using a source distribution, try running - `pyspdxtools -i tests/data/formats/SPDXJSONExample-v2.3.spdx.json --graph -o SPDXJSONExample-v2.3.spdx.png` to generate + `pyspdxtools -i tests/data/SPDXJSONExample-v2.3.spdx.json --graph -o SPDXJSONExample-v2.3.spdx.png` to generate a png with an overview of the structure of the example file. ## Library usage diff --git a/tests/spdx/data/formats/SPDXJSONExample-v2.2.spdx.json b/tests/spdx/data/SPDXJSONExample-v2.2.spdx.json similarity index 100% rename from tests/spdx/data/formats/SPDXJSONExample-v2.2.spdx.json rename to tests/spdx/data/SPDXJSONExample-v2.2.spdx.json diff --git a/tests/spdx/data/formats/SPDXJSONExample-v2.3.spdx.json b/tests/spdx/data/SPDXJSONExample-v2.3.spdx.json similarity index 100% rename from tests/spdx/data/formats/SPDXJSONExample-v2.3.spdx.json rename to tests/spdx/data/SPDXJSONExample-v2.3.spdx.json diff --git a/tests/spdx/data/formats/SPDXRdfExample-v2.2.spdx.rdf.xml b/tests/spdx/data/SPDXRdfExample-v2.2.spdx.rdf.xml similarity index 100% rename from tests/spdx/data/formats/SPDXRdfExample-v2.2.spdx.rdf.xml rename to tests/spdx/data/SPDXRdfExample-v2.2.spdx.rdf.xml diff --git a/tests/spdx/data/formats/SPDXRdfExample-v2.3.spdx.rdf.xml b/tests/spdx/data/SPDXRdfExample-v2.3.spdx.rdf.xml similarity index 100% rename from tests/spdx/data/formats/SPDXRdfExample-v2.3.spdx.rdf.xml rename to tests/spdx/data/SPDXRdfExample-v2.3.spdx.rdf.xml diff --git a/tests/spdx/data/formats/SPDXTagExample-v2.2.spdx b/tests/spdx/data/SPDXTagExample-v2.2.spdx similarity index 100% rename from tests/spdx/data/formats/SPDXTagExample-v2.2.spdx rename to tests/spdx/data/SPDXTagExample-v2.2.spdx diff --git a/tests/spdx/data/formats/SPDXTagExample-v2.3.spdx b/tests/spdx/data/SPDXTagExample-v2.3.spdx similarity index 100% rename from tests/spdx/data/formats/SPDXTagExample-v2.3.spdx rename to tests/spdx/data/SPDXTagExample-v2.3.spdx diff --git a/tests/spdx/data/formats/SPDXXMLExample-v2.2.spdx.xml b/tests/spdx/data/SPDXXMLExample-v2.2.spdx.xml similarity index 100% rename from tests/spdx/data/formats/SPDXXMLExample-v2.2.spdx.xml rename to tests/spdx/data/SPDXXMLExample-v2.2.spdx.xml diff --git a/tests/spdx/data/formats/SPDXXMLExample-v2.3.spdx.xml b/tests/spdx/data/SPDXXMLExample-v2.3.spdx.xml similarity index 100% rename from tests/spdx/data/formats/SPDXXMLExample-v2.3.spdx.xml rename to tests/spdx/data/SPDXXMLExample-v2.3.spdx.xml diff --git a/tests/spdx/data/formats/SPDXYAMLExample-v2.2.spdx.yaml b/tests/spdx/data/SPDXYAMLExample-v2.2.spdx.yaml similarity index 100% rename from tests/spdx/data/formats/SPDXYAMLExample-v2.2.spdx.yaml rename to tests/spdx/data/SPDXYAMLExample-v2.2.spdx.yaml diff --git a/tests/spdx/data/formats/SPDXYAMLExample-v2.3.spdx.yaml b/tests/spdx/data/SPDXYAMLExample-v2.3.spdx.yaml similarity index 100% rename from tests/spdx/data/formats/SPDXYAMLExample-v2.3.spdx.yaml rename to tests/spdx/data/SPDXYAMLExample-v2.3.spdx.yaml diff --git a/tests/spdx/parser/all_formats/test_parse_from_file.py b/tests/spdx/parser/all_formats/test_parse_from_file.py index fe7b54f01..083e7a0fa 100644 --- a/tests/spdx/parser/all_formats/test_parse_from_file.py +++ b/tests/spdx/parser/all_formats/test_parse_from_file.py @@ -34,9 +34,7 @@ def test_parse_from_file_not_found(self, parser, format_name, extension): def test_parse_from_file_with_2_3_example(self, parser, format_name, extension): doc = parser.parse_from_file( - os.path.join( - os.path.dirname(__file__), f"../../data/formats/SPDX{format_name}Example-v2.3.spdx{extension}" - ) + os.path.join(os.path.dirname(__file__), f"../../data/SPDX{format_name}Example-v2.3.spdx{extension}") ) assert type(doc) == Document assert len(doc.annotations) == 5 @@ -48,9 +46,7 @@ def test_parse_from_file_with_2_3_example(self, parser, format_name, extension): def test_parse_json_with_2_2_example(self, parser, format_name, extension): doc = parser.parse_from_file( - os.path.join( - os.path.dirname(__file__), f"../../data/formats/SPDX{format_name}Example-v2.2.spdx{extension}" - ) + os.path.join(os.path.dirname(__file__), f"../../data/SPDX{format_name}Example-v2.2.spdx{extension}") ) assert type(doc) == Document assert len(doc.annotations) == 5 diff --git a/tests/spdx/parser/rdf/test_license_expression_parser.py b/tests/spdx/parser/rdf/test_license_expression_parser.py index 74875eefb..71772ae45 100644 --- a/tests/spdx/parser/rdf/test_license_expression_parser.py +++ b/tests/spdx/parser/rdf/test_license_expression_parser.py @@ -24,7 +24,7 @@ def test_license_expression_parser(): def test_license_expression_parser_with_coupled_licenses(): doc = rdf_parser.parse_from_file( - os.path.join(os.path.dirname(__file__), "../../data/formats/SPDXRdfExample-v2.3.spdx.rdf.xml") + os.path.join(os.path.dirname(__file__), "../../data/SPDXRdfExample-v2.3.spdx.rdf.xml") ) packages_by_spdx_id = {package.spdx_id: package for package in doc.packages} diff --git a/tests/spdx/test_graph_generation.py b/tests/spdx/test_graph_generation.py index 9128625f2..492841847 100644 --- a/tests/spdx/test_graph_generation.py +++ b/tests/spdx/test_graph_generation.py @@ -60,7 +60,7 @@ def test_generate_graph_from_spdx( edges_count: int, relationship_node_keys: List[str], ) -> None: - document = parse_file(str(Path(__file__).resolve().parent.parent / "spdx" / "data" / "formats" / file_name)) + document = parse_file(str(Path(__file__).resolve().parent.parent / "spdx" / "data" / file_name)) graph = generate_relationship_graph_from_spdx(document) assert document.creation_info.spdx_id in graph.nodes() From a9ad3f69c6a6ee25f8e8d335173d7f40482f8c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 12 Apr 2023 16:33:46 +0200 Subject: [PATCH 050/354] [issue-540] change validation: allow no DESCRIBES relationship if there is a single package only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx/validation/document_validator.py | 5 +++-- .../spdx/validation/test_document_validator.py | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/spdx/validation/document_validator.py b/src/spdx/validation/document_validator.py index f32be8f64..a749f43ab 100644 --- a/src/spdx/validation/document_validator.py +++ b/src/spdx/validation/document_validator.py @@ -70,11 +70,12 @@ def validate_full_spdx_document(document: Document, spdx_version: str = None) -> document.relationships, RelationshipType.DESCRIBED_BY, document_id ) - if not document_describes_relationships + described_by_document_relationships: + only_a_single_package = len(document.packages) == 1 and not document.files and not document.snippets + if not only_a_single_package and not document_describes_relationships + described_by_document_relationships: validation_messages.append( ValidationMessage( f'there must be at least one relationship "{document_id} DESCRIBES ..." or "... DESCRIBED_BY ' - f'{document_id}"', + f'{document_id}" when there is not only a single package present', ValidationContext(spdx_id=document_id, element_type=SpdxElementType.DOCUMENT), ) ) diff --git a/tests/spdx/validation/test_document_validator.py b/tests/spdx/validation/test_document_validator.py index c58916c43..ce55ccde3 100644 --- a/tests/spdx/validation/test_document_validator.py +++ b/tests/spdx/validation/test_document_validator.py @@ -94,7 +94,20 @@ def test_document_describes_at_least_one_element(relationships): assert validation_messages == [] -def test_document_does_not_describe_an_element(): +def test_document_does_not_describe_an_element_with_only_one_package(): + document = document_fixture( + packages=[package_fixture()], + files=[], + snippets=[], + relationships=[], + annotations=[], + ) + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) + + assert validation_messages == [] + + +def test_document_does_not_describe_an_element_with_multiple_elements(): document = document_fixture( relationships=[Relationship("SPDXRef-Package", RelationshipType.DESCRIBES, "SPDXRef-File")] ) @@ -103,7 +116,7 @@ def test_document_does_not_describe_an_element(): assert validation_messages == [ ValidationMessage( f'there must be at least one relationship "{DOCUMENT_SPDX_ID} DESCRIBES ..." or "... DESCRIBED_BY ' - f'{DOCUMENT_SPDX_ID}"', + f'{DOCUMENT_SPDX_ID}" when there is not only a single package present', ValidationContext(spdx_id=DOCUMENT_SPDX_ID, element_type=SpdxElementType.DOCUMENT), ) ] From aaae4982f2af868cb816a984cebec52a272f4a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 13 Apr 2023 11:15:33 +0200 Subject: [PATCH 051/354] [issue-578] remove documentDescribes output from json writer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx/jsonschema/document_converter.py | 39 +------- src/spdx/jsonschema/document_properties.py | 1 - .../jsonschema/test_document_converter.py | 97 +------------------ .../json/expected_results/expected.json | 3 - 4 files changed, 6 insertions(+), 134 deletions(-) diff --git a/src/spdx/jsonschema/document_converter.py b/src/spdx/jsonschema/document_converter.py index 56bba2872..2b9967dfb 100644 --- a/src/spdx/jsonschema/document_converter.py +++ b/src/spdx/jsonschema/document_converter.py @@ -16,13 +16,6 @@ from spdx.jsonschema.relationship_converter import RelationshipConverter from spdx.jsonschema.snippet_converter import SnippetConverter from spdx.model.document import Document -from spdx.model.relationship import RelationshipType -from spdx.model.relationship_filters import ( - filter_by_type_and_origin, - filter_by_type_and_target, - find_file_contained_by_package_relationships, - find_package_contains_file_relationships, -) class DocumentConverter(TypedConverter[Document]): @@ -90,20 +83,6 @@ def _get_property_value( return document.creation_info.spdx_version elif document_property == DocumentProperty.DOCUMENT_NAMESPACE: return document.creation_info.document_namespace - elif document_property == DocumentProperty.DOCUMENT_DESCRIBES: - describes_ids = [ - relationship.related_spdx_element_id - for relationship in filter_by_type_and_origin( - document.relationships, RelationshipType.DESCRIBES, document.creation_info.spdx_id - ) - ] - described_by_ids = [ - relationship.spdx_element_id - for relationship in filter_by_type_and_target( - document.relationships, RelationshipType.DESCRIBED_BY, document.creation_info.spdx_id - ) - ] - return describes_ids + described_by_ids or None elif document_property == DocumentProperty.PACKAGES: return [self.package_converter.convert(package, document) for package in document.packages] or None elif document_property == DocumentProperty.FILES: @@ -111,22 +90,6 @@ def _get_property_value( elif document_property == DocumentProperty.SNIPPETS: return [self.snippet_converter.convert(snippet, document) for snippet in document.snippets] or None elif document_property == DocumentProperty.RELATIONSHIPS: - already_covered_relationships = filter_by_type_and_origin( - document.relationships, RelationshipType.DESCRIBES, document.creation_info.spdx_id - ) - already_covered_relationships.extend( - filter_by_type_and_target( - document.relationships, RelationshipType.DESCRIBED_BY, document.creation_info.spdx_id - ) - ) - for package in document.packages: - already_covered_relationships.extend(find_package_contains_file_relationships(document, package)) - already_covered_relationships.extend(find_file_contained_by_package_relationships(document, package)) - relationships_to_ignore = [ - relationship for relationship in already_covered_relationships if relationship.comment is None - ] return [ - self.relationship_converter.convert(relationship) - for relationship in document.relationships - if relationship not in relationships_to_ignore + self.relationship_converter.convert(relationship) for relationship in document.relationships ] or None diff --git a/src/spdx/jsonschema/document_properties.py b/src/spdx/jsonschema/document_properties.py index 6fc244a8b..045ecb7c0 100644 --- a/src/spdx/jsonschema/document_properties.py +++ b/src/spdx/jsonschema/document_properties.py @@ -17,7 +17,6 @@ class DocumentProperty(JsonProperty): NAME = auto() SPDX_VERSION = auto() DOCUMENT_NAMESPACE = auto() - DOCUMENT_DESCRIBES = auto() PACKAGES = auto() FILES = auto() SNIPPETS = auto() diff --git a/tests/spdx/jsonschema/test_document_converter.py b/tests/spdx/jsonschema/test_document_converter.py index 149eca9ac..ba964e718 100644 --- a/tests/spdx/jsonschema/test_document_converter.py +++ b/tests/spdx/jsonschema/test_document_converter.py @@ -11,7 +11,6 @@ from spdx.jsonschema.annotation_converter import AnnotationConverter from spdx.jsonschema.document_converter import DocumentConverter from spdx.jsonschema.document_properties import DocumentProperty -from spdx.jsonschema.relationship_converter import RelationshipConverter from spdx.model.actor import Actor, ActorType from spdx.model.annotation import Annotation, AnnotationType from spdx.model.document import Document @@ -20,14 +19,12 @@ from tests.spdx.fixtures import ( annotation_fixture, creation_info_fixture, - document_fixture, external_document_ref_fixture, file_fixture, package_fixture, - relationship_fixture, snippet_fixture, ) -from tests.spdx.mock_utils import assert_mock_method_called_with_arguments, assert_no_mock_methods_called +from tests.spdx.mock_utils import assert_mock_method_called_with_arguments @pytest.fixture @@ -139,11 +136,13 @@ def test_successful_conversion(converter: DocumentConverter): converter.json_property_name(DocumentProperty.NAME): "name", converter.json_property_name(DocumentProperty.SPDX_VERSION): "spdxVersion", converter.json_property_name(DocumentProperty.DOCUMENT_NAMESPACE): "namespace", - converter.json_property_name(DocumentProperty.DOCUMENT_DESCRIBES): ["describedElementId"], converter.json_property_name(DocumentProperty.PACKAGES): ["mock_converted_package"], converter.json_property_name(DocumentProperty.FILES): ["mock_converted_file"], converter.json_property_name(DocumentProperty.SNIPPETS): ["mock_converted_snippet"], - converter.json_property_name(DocumentProperty.RELATIONSHIPS): ["mock_converted_relationship"], + converter.json_property_name(DocumentProperty.RELATIONSHIPS): [ + "mock_converted_relationship", + "mock_converted_relationship", + ], } @@ -163,7 +162,6 @@ def test_null_values(converter: DocumentConverter): assert converter.json_property_name(DocumentProperty.ANNOTATIONS) not in converted_dict assert converter.json_property_name(DocumentProperty.EXTERNAL_DOCUMENT_REFS) not in converted_dict assert converter.json_property_name(DocumentProperty.HAS_EXTRACTED_LICENSING_INFOS) not in converted_dict - assert converter.json_property_name(DocumentProperty.DOCUMENT_DESCRIBES) not in converted_dict assert converter.json_property_name(DocumentProperty.PACKAGES) not in converted_dict assert converter.json_property_name(DocumentProperty.FILES) not in converted_dict assert converter.json_property_name(DocumentProperty.SNIPPETS) not in converted_dict @@ -205,88 +203,3 @@ def test_document_annotations(converter: DocumentConverter): assert_mock_method_called_with_arguments(annotation_converter, "convert", document_annotation, other_annotation) converted_document_annotations = converted_dict.get(converter.json_property_name(DocumentProperty.ANNOTATIONS)) assert converted_document_annotations == ["mock_converted_annotation", "mock_converted_annotation"] - - -def test_document_describes(converter: DocumentConverter): - document = document_fixture() - document_id = document.creation_info.spdx_id - document_describes_relationship = relationship_fixture( - spdx_element_id=document_id, - relationship_type=RelationshipType.DESCRIBES, - related_spdx_element_id="describesId", - ) - described_by_document_relationship = relationship_fixture( - related_spdx_element_id=document_id, - relationship_type=RelationshipType.DESCRIBED_BY, - spdx_element_id="describedById", - ) - other_describes_relationship = relationship_fixture( - spdx_element_id="DocumentRef-external", relationship_type=RelationshipType.DESCRIBES - ) - other_relationship = relationship_fixture(spdx_element_id=document_id, relationship_type=RelationshipType.CONTAINS) - document.relationships = [ - document_describes_relationship, - described_by_document_relationship, - other_describes_relationship, - other_relationship, - ] - - converted_dict = converter.convert(document) - - document_describes = converted_dict.get(converter.json_property_name(DocumentProperty.DOCUMENT_DESCRIBES)) - assert document_describes == [ - document_describes_relationship.related_spdx_element_id, - described_by_document_relationship.spdx_element_id, - ] - - -DOCUMENT_ID = "docConverterTestDocumentId" -PACKAGE_ID = "docConverterTestPackageId" -FILE_ID = "docConverterTestFileId" - - -@pytest.mark.parametrize( - "relationship,should_be_written", - [ - (relationship_fixture(DOCUMENT_ID, RelationshipType.DESCRIBES), True), - (relationship_fixture(DOCUMENT_ID, RelationshipType.DESCRIBES, comment=None), False), - ( - relationship_fixture(relationship_type=RelationshipType.DESCRIBED_BY, related_spdx_element_id=DOCUMENT_ID), - True, - ), - ( - relationship_fixture( - relationship_type=RelationshipType.DESCRIBED_BY, related_spdx_element_id=DOCUMENT_ID, comment=None - ), - False, - ), - (relationship_fixture(DOCUMENT_ID, RelationshipType.AMENDS, comment=None), True), - (relationship_fixture(PACKAGE_ID, RelationshipType.CONTAINS, FILE_ID), True), - (relationship_fixture(PACKAGE_ID, RelationshipType.CONTAINS, FILE_ID, comment=None), False), - (relationship_fixture(FILE_ID, RelationshipType.CONTAINED_BY, PACKAGE_ID), True), - (relationship_fixture(FILE_ID, RelationshipType.CONTAINED_BY, PACKAGE_ID, comment=None), False), - (relationship_fixture(PACKAGE_ID, RelationshipType.CONTAINS, comment=None), True), - (relationship_fixture(PACKAGE_ID, RelationshipType.COPY_OF, FILE_ID, comment=None), True), - ], -) -def test_document_relationships(converter: DocumentConverter, relationship: Relationship, should_be_written: bool): - package = package_fixture(spdx_id=PACKAGE_ID) - file = file_fixture(spdx_id=FILE_ID) - document = document_fixture( - creation_info_fixture(spdx_id=DOCUMENT_ID), packages=[package], files=[file], relationships=[relationship] - ) - - # Weird type hint to make warnings about unresolved references from the mock class disappear - relationship_converter: Union[RelationshipConverter, NonCallableMagicMock] = converter.relationship_converter - relationship_converter.convert.return_value = "mock_converted_relationship" - - converted_dict = converter.convert(document) - - relationships = converted_dict.get(converter.json_property_name(DocumentProperty.RELATIONSHIPS)) - - if should_be_written: - assert_mock_method_called_with_arguments(relationship_converter, "convert", relationship) - assert relationships == ["mock_converted_relationship"] - else: - assert_no_mock_methods_called(relationship_converter) - assert relationships is None diff --git a/tests/spdx/writer/json/expected_results/expected.json b/tests/spdx/writer/json/expected_results/expected.json index 0d444ba52..264cf0410 100644 --- a/tests/spdx/writer/json/expected_results/expected.json +++ b/tests/spdx/writer/json/expected_results/expected.json @@ -10,9 +10,6 @@ "licenseListVersion": "3.19" }, "dataLicense": "CC0-1.0", - "documentDescribes": [ - "SPDXRef-File" - ], "documentNamespace": "https://some.namespace", "externalDocumentRefs": [ { From 64b5561c733388a4aa59684f68766e33989d142f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 13 Apr 2023 11:19:25 +0200 Subject: [PATCH 052/354] [issue-578] remove hasFiles output from json writer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- README.md | 2 +- src/spdx/jsonschema/package_converter.py | 14 ------ src/spdx/jsonschema/package_properties.py | 1 - .../spdx/jsonschema/test_package_converter.py | 48 ------------------- 4 files changed, 1 insertion(+), 64 deletions(-) diff --git a/README.md b/README.md index 41f2580d6..19ae4e3f2 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ instead of `bin`. * Note: in-place manipulations like `list.append(item)` will circumvent the type checking (a `TypeError` will still be raised when reading `list` again). We recommend using `list = list + [item]` instead. * The main entry point of an SPDX document is the `Document` class, which links to all other classes. * For license handling, the [license_expression](https://github.com/nexB/license-expression) library is used. - * Note on `documentDescribes` and `hasFiles`: These fields will be converted to relationships in the internal data model. During serialization, they will be written again where appropriate. + * Note on `documentDescribes` and `hasFiles`: These fields will be converted to relationships in the internal data model. As they are deprecated, these fields will not be written in the output. 2. **PARSING** * Use `parse_file(file_name)` from the `parse_anything.py` module to parse an arbitrary file with one of the supported file endings. * Successful parsing will return a `Document` instance. Unsuccessful parsing will raise `SPDXParsingError` with a list of all encountered problems. diff --git a/src/spdx/jsonschema/package_converter.py b/src/spdx/jsonschema/package_converter.py index 0141289bc..0019b80a3 100644 --- a/src/spdx/jsonschema/package_converter.py +++ b/src/spdx/jsonschema/package_converter.py @@ -15,10 +15,6 @@ from spdx.model.actor import Actor from spdx.model.document import Document from spdx.model.package import Package -from spdx.model.relationship_filters import ( - find_file_contained_by_package_relationships, - find_package_contains_file_relationships, -) class PackageConverter(TypedConverter[Package]): @@ -71,16 +67,6 @@ def _get_property_value( ] or None elif package_property == PackageProperty.FILES_ANALYZED: return package.files_analyzed - elif package_property == PackageProperty.HAS_FILES: - package_contains_file_ids = [ - relationship.related_spdx_element_id - for relationship in find_package_contains_file_relationships(document, package) - ] - file_contained_in_package_ids = [ - relationship.spdx_element_id - for relationship in find_file_contained_by_package_relationships(document, package) - ] - return package_contains_file_ids + file_contained_in_package_ids or None elif package_property == PackageProperty.HOMEPAGE: return apply_if_present(str, package.homepage) elif package_property == PackageProperty.LICENSE_COMMENTS: diff --git a/src/spdx/jsonschema/package_properties.py b/src/spdx/jsonschema/package_properties.py index 5b3b42eb3..60ba0ff20 100644 --- a/src/spdx/jsonschema/package_properties.py +++ b/src/spdx/jsonschema/package_properties.py @@ -18,7 +18,6 @@ class PackageProperty(JsonProperty): DOWNLOAD_LOCATION = auto() EXTERNAL_REFS = auto() FILES_ANALYZED = auto() - HAS_FILES = auto() HOMEPAGE = auto() LICENSE_COMMENTS = auto() LICENSE_CONCLUDED = auto() diff --git a/tests/spdx/jsonschema/test_package_converter.py b/tests/spdx/jsonschema/test_package_converter.py index cb8466ed8..d35236563 100644 --- a/tests/spdx/jsonschema/test_package_converter.py +++ b/tests/spdx/jsonschema/test_package_converter.py @@ -17,7 +17,6 @@ from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.model.document import Document from spdx.model.package import Package, PackagePurpose, PackageVerificationCode -from spdx.model.relationship import RelationshipType from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion from spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone from tests.spdx.fixtures import ( @@ -25,10 +24,7 @@ creation_info_fixture, document_fixture, external_package_ref_fixture, - file_fixture, package_fixture, - relationship_fixture, - snippet_fixture, ) from tests.spdx.mock_utils import assert_mock_method_called_with_arguments @@ -66,7 +62,6 @@ def converter( (PackageProperty.DOWNLOAD_LOCATION, "downloadLocation"), (PackageProperty.EXTERNAL_REFS, "externalRefs"), (PackageProperty.FILES_ANALYZED, "filesAnalyzed"), - (PackageProperty.HAS_FILES, "hasFiles"), (PackageProperty.HOMEPAGE, "homepage"), (PackageProperty.LICENSE_COMMENTS, "licenseComments"), (PackageProperty.LICENSE_CONCLUDED, "licenseConcluded"), @@ -230,7 +225,6 @@ def test_null_values(converter: PackageConverter): assert converter.json_property_name(PackageProperty.ATTRIBUTION_TEXTS) not in converted_dict assert converter.json_property_name(PackageProperty.CHECKSUMS) not in converted_dict assert converter.json_property_name(PackageProperty.EXTERNAL_REFS) not in converted_dict - assert converter.json_property_name(PackageProperty.HAS_FILES) not in converted_dict assert converter.json_property_name(PackageProperty.LICENSE_INFO_FROM_FILES) not in converted_dict @@ -314,45 +308,3 @@ def test_package_annotations(converter: PackageConverter): ) converted_file_annotations = converted_dict.get(converter.json_property_name(PackageProperty.ANNOTATIONS)) assert converted_file_annotations == ["mock_converted_annotation", "mock_converted_annotation"] - - -def test_has_files(converter: PackageConverter): - package = package_fixture() - first_contained_file = file_fixture(spdx_id="firstFileId") - second_contained_file = file_fixture(spdx_id="secondFileId") - non_contained_file = file_fixture(spdx_id="otherFileId") - snippet = snippet_fixture() - document = document_fixture( - packages=[package], files=[first_contained_file, second_contained_file, non_contained_file], snippets=[snippet] - ) - package_contains_file_relationship = relationship_fixture( - spdx_element_id=package.spdx_id, - relationship_type=RelationshipType.CONTAINS, - related_spdx_element_id=first_contained_file.spdx_id, - ) - file_contained_in_package_relationship = relationship_fixture( - spdx_element_id=second_contained_file.spdx_id, - relationship_type=RelationshipType.CONTAINED_BY, - related_spdx_element_id=package.spdx_id, - ) - package_contains_snippet_relationship = relationship_fixture( - spdx_element_id=package.spdx_id, - relationship_type=RelationshipType.CONTAINS, - related_spdx_element_id=snippet.spdx_id, - ) - package_describes_file_relationship = relationship_fixture( - spdx_element_id=package.spdx_id, - relationship_type=RelationshipType.DESCRIBES, - related_spdx_element_id=non_contained_file.spdx_id, - ) - document.relationships = [ - package_contains_file_relationship, - file_contained_in_package_relationship, - package_contains_snippet_relationship, - package_describes_file_relationship, - ] - - converted_dict = converter.convert(package, document) - - has_files = converted_dict.get(converter.json_property_name(PackageProperty.HAS_FILES)) - assert has_files == [first_contained_file.spdx_id, second_contained_file.spdx_id] From fab555d5a46bded061590537ab7f66bde29cedd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 13 Apr 2023 11:43:14 +0200 Subject: [PATCH 053/354] [issue-580] RDF: don't output relationship comment if there is none MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx/writer/rdf/relationship_writer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/spdx/writer/rdf/relationship_writer.py b/src/spdx/writer/rdf/relationship_writer.py index 585ccdfcc..9db6fea3f 100644 --- a/src/spdx/writer/rdf/relationship_writer.py +++ b/src/spdx/writer/rdf/relationship_writer.py @@ -41,7 +41,8 @@ def add_relationship_to_graph( ), ) ) - graph.add((relationship_node, RDFS.comment, Literal(relationship.comment))) + if relationship.comment: + graph.add((relationship_node, RDFS.comment, Literal(relationship.comment))) relationship_resource = URIRef( add_namespace_to_spdx_id(relationship.spdx_element_id, doc_namespace, external_doc_ref_to_namespace) ) From eb0c96173fe3afe72e8a70774546cb037bc469fe Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 14 Apr 2023 08:55:12 +0200 Subject: [PATCH 054/354] [issue_583] fix type hint Signed-off-by: Meret Behrens --- src/spdx/model/snippet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx/model/snippet.py b/src/spdx/model/snippet.py index fc9fa0353..b88d9d835 100644 --- a/src/spdx/model/snippet.py +++ b/src/spdx/model/snippet.py @@ -35,7 +35,7 @@ def __init__( license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, license_info_in_snippet: List[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None, license_comment: Optional[str] = None, - copyright_text: Optional[str] = None, + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None, comment: Optional[str] = None, name: Optional[str] = None, attribution_texts: List[str] = None, From 95d6ce143dac35825d8184edffabb48d4a71f12a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 17 Apr 2023 13:57:56 +0200 Subject: [PATCH 055/354] [issue-375] add validation test for SPDX Lite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx/data/SPDXLite.spdx | 36 +++++++++++++++++++ .../validation/test_document_validator.py | 9 ++++- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tests/spdx/data/SPDXLite.spdx diff --git a/tests/spdx/data/SPDXLite.spdx b/tests/spdx/data/SPDXLite.spdx new file mode 100644 index 000000000..d080bb86a --- /dev/null +++ b/tests/spdx/data/SPDXLite.spdx @@ -0,0 +1,36 @@ +# from https://github.com/OpenChain-Project/OpenChain-JWG/blob/4675d7a61ad552e8f9780419c54dddbdf87f6018/subgroups/sbom-sg/outcomes/SPDX-Lite/sample/SPDX-tools-spdxlite.txt +## 2 Document Creation Information + +SPDXVersion: SPDX-2.2 +DataLicense: CC0-1.0 +SPDXID: SPDXRef-DOCUMENT +DocumentName: example-v1.0 +DocumentNamespace: https://example.com/example-v1.0 +Creator: Person: someone +Created: 2021-04-05T01:23:45Z + +## 3 Package Information + +PackageName: SPDX tools +SPDXID: SPDXRef-spdxtools +PackageVersion: 2.0.3 +PackageFileName: spdx-tools-2.0.2-jar-with-dependencies.jar +PackageDownloadLocation: NONE +FilesAnalyzed: false +PackageHomePage: https://spdx.org/tools +PackageLicenseConcluded: Apache-2.0 +PackageLicenseDeclared: Apache-2.0 +PackageLicenseComments: +PackageCopyrightText: software copyright (c) 2000-2003, BEA Systems, +PackageComment: + ModificationRecord: NO + CompileOptions: --some-option + LinkMethodology: Dynamic + + +## 6 Other Licensing Information Detected + +LicenseID: LicenseRef-1 +ExtractedText: hoge +LicenseName: NOASSERTION +LicenseComment: diff --git a/tests/spdx/validation/test_document_validator.py b/tests/spdx/validation/test_document_validator.py index ce55ccde3..41733db9a 100644 --- a/tests/spdx/validation/test_document_validator.py +++ b/tests/spdx/validation/test_document_validator.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 - +import os from typing import List, Optional import pytest @@ -9,6 +9,7 @@ from spdx.constants import DOCUMENT_SPDX_ID from spdx.model.document import CreationInfo, Document from spdx.model.relationship import Relationship, RelationshipType +from spdx.parser.parse_anything import parse_file from spdx.validation.document_validator import validate_full_spdx_document from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import creation_info_fixture, document_fixture, file_fixture, package_fixture, snippet_fixture @@ -21,6 +22,12 @@ def test_valid_document(): assert validation_messages == [] +def test_spdx_lite_validation(): + document = parse_file(os.path.join(os.path.dirname(__file__), "../data/SPDXLite.spdx")) + + assert validate_full_spdx_document(document) == [] + + @pytest.mark.parametrize( "creation_info, version_input, expected_message", [ From 5fbbd34c14ca564222749d98c744bbc9f3f04e99 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 17 Apr 2023 13:44:19 +0200 Subject: [PATCH 056/354] [issue_586] make infile a required argument to display a help message when no arguments are given Signed-off-by: Meret Behrens --- src/spdx/clitools/pyspdxtools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx/clitools/pyspdxtools.py b/src/spdx/clitools/pyspdxtools.py index e2461767d..f2d480ea1 100644 --- a/src/spdx/clitools/pyspdxtools.py +++ b/src/spdx/clitools/pyspdxtools.py @@ -29,7 +29,7 @@ @click.command() -@click.option("--infile", "-i", help="The file containing the document to be validated or converted.") +@click.option("--infile", "-i", required=True, help="The file containing the document to be validated or converted.") @click.option( "--outfile", "-o", From 3204bda8bb4cb99de97bd08d13cd31cbcb8e8344 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 17 Apr 2023 14:02:58 +0200 Subject: [PATCH 057/354] [issue_586] add tests for cli usage Signed-off-by: Meret Behrens --- tests/spdx/test_cli.py | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tests/spdx/test_cli.py diff --git a/tests/spdx/test_cli.py b/tests/spdx/test_cli.py new file mode 100644 index 000000000..39660392d --- /dev/null +++ b/tests/spdx/test_cli.py @@ -0,0 +1,45 @@ +import os + +import pytest +from click.testing import CliRunner + +from spdx.clitools.pyspdxtools import main + + +@pytest.mark.parametrize( + "options", + [ + ("--infile", os.path.join(os.path.dirname(__file__), "data/SPDXJSONExample-v2.3.spdx.json")), + ("-i", os.path.join(os.path.dirname(__file__), "data/SPDXJSONExample-v2.3.spdx.json"), "--novalidation"), + ( + "-i", + os.path.join(os.path.dirname(__file__), "data/SPDXJSONExample-v2.3.spdx.json"), + "--novalidation", + "--version", + "SPDX-2.3", + ), + ("-i", os.path.join(os.path.dirname(__file__), "data/SPDXJSONExample-v2.3.spdx.json"), "-o", "-"), + ], +) +def test_cli_with_system_exit_code_0(options): + runner = CliRunner() + + result = runner.invoke(main, options) + + assert result.exit_code == 0 + + +@pytest.mark.parametrize( + "options", + [ + (), + ("-i", os.path.join(os.path.dirname(__file__), "data/SPDXJSONExample-v2.3.spdx.json"), "--version"), + ("-i", os.path.join(os.path.dirname(__file__), "data/SPDXJSONExample-v2.3.spdx.json"), "-o"), + ], +) +def test_cli_with_system_exit_code_2(options): + runner = CliRunner() + + result = runner.invoke(main, options) + + assert result.exit_code == 2 From d9a2e01c8f247f9267ae531309a019c86b71dbdb Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 17 Apr 2023 15:07:53 +0200 Subject: [PATCH 058/354] [issue_589] fix json parser: process fields that can be "NOASSERTION" or "NONE" correctly Signed-off-by: Meret Behrens --- src/spdx/parser/jsonlikedict/file_parser.py | 9 ++- .../parser/jsonlikedict/package_parser.py | 8 +- .../parser/jsonlikedict/snippet_parser.py | 9 ++- .../parser/jsonlikedict/test_file_parser.py | 15 +++- .../jsonlikedict/test_package_parser.py | 76 ++++++++++++++++--- .../jsonlikedict/test_snippet_parser.py | 15 +++- 6 files changed, 109 insertions(+), 23 deletions(-) diff --git a/src/spdx/parser/jsonlikedict/file_parser.py b/src/spdx/parser/jsonlikedict/file_parser.py index eb59fcc52..3f4b565e1 100644 --- a/src/spdx/parser/jsonlikedict/file_parser.py +++ b/src/spdx/parser/jsonlikedict/file_parser.py @@ -10,7 +10,10 @@ from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone from spdx.parser.jsonlikedict.checksum_parser import ChecksumParser -from spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_log_error +from spdx.parser.jsonlikedict.dict_parsing_functions import ( + parse_field_or_log_error, + parse_field_or_no_assertion_or_none, +) from spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser from spdx.parser.logger import Logger from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages @@ -37,7 +40,9 @@ def parse_file(self, file_dict: Dict) -> Optional[File]: attribution_texts: List[str] = file_dict.get("attributionTexts", []) comment: Optional[str] = file_dict.get("comment") - copyright_text: Optional[str] = file_dict.get("copyrightText") + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = parse_field_or_no_assertion_or_none( + file_dict.get("copyrightText") + ) file_contributors: List[str] = file_dict.get("fileContributors", []) file_types: List[FileType] = parse_field_or_log_error( logger, file_dict.get("fileTypes"), self.parse_file_types diff --git a/src/spdx/parser/jsonlikedict/package_parser.py b/src/spdx/parser/jsonlikedict/package_parser.py index c79fd1145..090a7ad7e 100644 --- a/src/spdx/parser/jsonlikedict/package_parser.py +++ b/src/spdx/parser/jsonlikedict/package_parser.py @@ -58,7 +58,9 @@ def parse_package(self, package_dict: Dict) -> Package: logger, package_dict.get("checksums"), self.checksum_parser.parse_checksum, field_is_list=True ) comment: Optional[str] = package_dict.get("comment") - copyright_text: Optional[str] = package_dict.get("copyrightText") + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = parse_field_or_no_assertion_or_none( + package_dict.get("copyrightText") + ) description: Optional[str] = package_dict.get("description") download_location: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = parse_field_or_no_assertion_or_none( package_dict.get("downloadLocation") @@ -78,7 +80,9 @@ def parse_package(self, package_dict: Dict) -> Package: elif files_analyzed.lower() == "false": files_analyzed = False - homepage: Optional[str] = package_dict.get("homepage") + homepage: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = parse_field_or_no_assertion_or_none( + package_dict.get("homepage") + ) license_comments: Optional[str] = package_dict.get("licenseComments") license_concluded = parse_field_or_log_error( logger, package_dict.get("licenseConcluded"), self.license_expression_parser.parse_license_expression diff --git a/src/spdx/parser/jsonlikedict/snippet_parser.py b/src/spdx/parser/jsonlikedict/snippet_parser.py index 52d2194ba..c4f525015 100644 --- a/src/spdx/parser/jsonlikedict/snippet_parser.py +++ b/src/spdx/parser/jsonlikedict/snippet_parser.py @@ -10,7 +10,10 @@ from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_log_error +from spdx.parser.jsonlikedict.dict_parsing_functions import ( + parse_field_or_log_error, + parse_field_or_no_assertion_or_none, +) from spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser from spdx.parser.logger import Logger from spdx.parser.parsing_functions import construct_or_raise_parsing_error @@ -43,7 +46,9 @@ def parse_snippet(self, snippet_dict: Dict) -> Snippet: attribution_texts: List[str] = snippet_dict.get("attributionTexts", []) comment: Optional[str] = snippet_dict.get("comment") - copyright_text: Optional[str] = snippet_dict.get("copyrightText") + copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = parse_field_or_no_assertion_or_none( + snippet_dict.get("copyrightText") + ) license_comment: Optional[str] = snippet_dict.get("licenseComments") license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error( logger, snippet_dict.get("licenseConcluded"), self.license_expression_parser.parse_license_expression diff --git a/tests/spdx/parser/jsonlikedict/test_file_parser.py b/tests/spdx/parser/jsonlikedict/test_file_parser.py index e99c039ed..6aacf44ad 100644 --- a/tests/spdx/parser/jsonlikedict/test_file_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_file_parser.py @@ -9,12 +9,21 @@ from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.model.file import FileType from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx.model.spdx_none import SpdxNone from spdx.parser.error import SPDXParsingError from spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements from spdx.parser.jsonlikedict.file_parser import FileParser -def test_parse_file(): +@pytest.mark.parametrize( + "copyright_text, expected_copyright_text", + [ + ("Copyright 2008-2010 John Smith", "Copyright 2008-2010 John Smith"), + ("NOASSERTION", SpdxNoAssertion()), + ("NONE", SpdxNone()), + ], +) +def test_parse_file(copyright_text, expected_copyright_text): file_parser = FileParser() file_dict = { "SPDXID": "SPDXRef-File", @@ -25,7 +34,7 @@ def test_parse_file(): ], "comment": "The concluded license was taken from the package level that the file was included in.\nThis " "information was found in the COPYING.txt file in the xyz directory.", - "copyrightText": "Copyright 2008-2010 John Smith", + "copyrightText": copyright_text, "fileContributors": [ "The Regents of the University of California", "Modified by Paul Mundt lethal@linux-sh.org", @@ -66,7 +75,7 @@ def test_parse_file(): == "The concluded license was taken from the package level that the file was included in.\nThis information " "was found in the COPYING.txt file in the xyz directory." ) - assert file.copyright_text == "Copyright 2008-2010 John Smith" + assert file.copyright_text == expected_copyright_text assert file.file_types == [FileType.SOURCE] TestCase().assertCountEqual( file.contributors, diff --git a/tests/spdx/parser/jsonlikedict/test_package_parser.py b/tests/spdx/parser/jsonlikedict/test_package_parser.py index 00cecbdb4..bb0fea497 100644 --- a/tests/spdx/parser/jsonlikedict/test_package_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_package_parser.py @@ -11,12 +11,66 @@ from spdx.model.checksum import Checksum, ChecksumAlgorithm from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory, PackagePurpose, PackageVerificationCode from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx.model.spdx_none import SpdxNone from spdx.parser.error import SPDXParsingError from spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements from spdx.parser.jsonlikedict.package_parser import PackageParser -def test_parse_package(): +@pytest.mark.parametrize( + "homepage, expected_homepage, download_location, expected_download_location, " + "copyright_text, expected_copyright_text, originator, expected_originator, supplier, expected_supplier", + [ + ( + "http://ftp.gnu.org/gnu/glibc", + "http://ftp.gnu.org/gnu/glibc", + "NOASSERTION", + SpdxNoAssertion(), + "NONE", + SpdxNone(), + "Organization: ExampleCodeInspect (contact@example.com)", + Actor(ActorType.ORGANIZATION, "ExampleCodeInspect", "contact@example.com"), + "NOASSERTION", + SpdxNoAssertion(), + ), + ( + "NOASSERTION", + SpdxNoAssertion(), + "NONE", + SpdxNone(), + "Copyright 2008-2010 John Smith", + "Copyright 2008-2010 John Smith", + None, + None, + None, + None, + ), + ( + "NONE", + SpdxNone(), + "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + "NOASSERTION", + SpdxNoAssertion(), + "NOASSERTION", + SpdxNoAssertion(), + "Person: Jane Doe (jane.doe@example.com)", + Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com"), + ), + ], +) +def test_parse_package( + homepage, + expected_homepage, + download_location, + expected_download_location, + copyright_text, + expected_copyright_text, + originator, + expected_originator, + supplier, + expected_supplier, +): package_parser = PackageParser() package_dict = { @@ -42,11 +96,11 @@ def test_parse_package(): }, ], "comment": "This is a comment.", - "copyrightText": "Copyright 2008-2010 John Smith", + "copyrightText": copyright_text, "description": "The GNU C Library defines functions that are specified by the ISO C standard, as well as " "additional features specific to POSIX and other derivatives of the Unix operating system, and " "extensions specific to GNU systems.", - "downloadLocation": "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + "downloadLocation": download_location, "externalRefs": [ { "referenceCategory": "SECURITY", @@ -62,14 +116,14 @@ def test_parse_package(): }, ], "filesAnalyzed": True, - "homepage": "http://ftp.gnu.org/gnu/glibc", + "homepage": homepage, "licenseComments": "The license for this project changed with the release of version x.y. The version of the " "project included here post-dates the license change.", "licenseConcluded": "(LGPL-2.0-only OR LicenseRef-3)", "licenseDeclared": "(LGPL-2.0-only AND LicenseRef-3)", "licenseInfoFromFiles": ["GPL-2.0-only", "LicenseRef-2", "LicenseRef-1", "NOASSERTION"], "name": "glibc", - "originator": "Organization: ExampleCodeInspect (contact@example.com)", + "originator": originator, "packageFileName": "glibc-2.11.1.tar.gz", "packageVerificationCode": { "packageVerificationCodeExcludedFiles": ["./package.spdx"], @@ -79,7 +133,7 @@ def test_parse_package(): "releaseDate": "2012-01-29T18:30:22Z", "sourceInfo": "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git.", "summary": "GNU C library.", - "supplier": "Person: Jane Doe (jane.doe@example.com)", + "supplier": supplier, "validUntilDate": "2014-01-29T18:30:22Z", "versionInfo": "2.11.1", } @@ -88,11 +142,11 @@ def test_parse_package(): assert package.spdx_id == "SPDXRef-Package" assert package.name == "glibc" - assert package.download_location == "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz" + assert package.download_location == expected_download_location assert package.version == "2.11.1" assert package.file_name == "glibc-2.11.1.tar.gz" - assert package.supplier == Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com") - assert package.originator == Actor(ActorType.ORGANIZATION, "ExampleCodeInspect", "contact@example.com") + assert package.supplier == expected_supplier + assert package.originator == expected_originator assert package.files_analyzed is True assert package.verification_code == PackageVerificationCode( value="d6a770ba38583ed4bb4525bd96e50461655d2758", excluded_files=["./package.spdx"] @@ -110,7 +164,7 @@ def test_parse_package(): ), ], ) - assert package.homepage == "http://ftp.gnu.org/gnu/glibc" + assert package.homepage == expected_homepage assert package.source_info == "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git." assert package.license_concluded == Licensing().parse("(LGPL-2.0-only OR LicenseRef-3)") TestCase().assertCountEqual( @@ -128,7 +182,7 @@ def test_parse_package(): == "The license for this project changed with the release of version x.y. The version of the project included" " here post-dates the license change." ) - assert package.copyright_text == "Copyright 2008-2010 John Smith" + assert package.copyright_text == expected_copyright_text assert package.summary == "GNU C library." assert ( package.description diff --git a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py index 10b0fb232..1cbceb95e 100644 --- a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py @@ -7,11 +7,20 @@ from license_expression import Licensing from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx.model.spdx_none import SpdxNone from spdx.parser.error import SPDXParsingError from spdx.parser.jsonlikedict.snippet_parser import SnippetParser -def test_parse_snippet(): +@pytest.mark.parametrize( + "copyright_text, expected_copyright_text", + [ + ("Copyright 2008-2010 John Smith", "Copyright 2008-2010 John Smith"), + ("NOASSERTION", SpdxNoAssertion()), + ("NONE", SpdxNone()), + ], +) +def test_parse_snippet(copyright_text, expected_copyright_text): snippet_parser = SnippetParser() snippet_dict = { @@ -19,7 +28,7 @@ def test_parse_snippet(): "comment": "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a " "commercial scanner identified it as being derived from file foo.c in package xyz which is licensed" " under GPL-2.0.", - "copyrightText": "Copyright 2008-2010 John Smith", + "copyrightText": copyright_text, "licenseComments": "The concluded license was taken from package xyz, from which the snippet was copied into " "the current file. The concluded license information was found in the COPYING.txt file in " "package xyz.", @@ -48,7 +57,7 @@ def test_parse_snippet(): == "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial " "scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0." ) - assert snippet.copyright_text == "Copyright 2008-2010 John Smith" + assert snippet.copyright_text == expected_copyright_text assert ( snippet.license_comment == "The concluded license was taken from package xyz, from which the snippet was copied into the current file." From 873c635432fdd6645ba794c1aea65bdbab560682 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 18 Apr 2023 13:54:27 +0200 Subject: [PATCH 059/354] [issue_508] add methods to remove duplicated items from list properties Signed-off-by: Meret Behrens --- src/spdx/document_utils.py | 30 ++++++- src/spdx/writer/json/json_writer.py | 9 +- src/spdx/writer/rdf/rdf_writer.py | 6 +- src/spdx/writer/tagvalue/tagvalue_writer.py | 5 +- src/spdx/writer/xml/xml_writer.py | 10 ++- src/spdx/writer/yaml/yaml_writer.py | 9 +- tests/spdx/test_document_utils.py | 95 ++++++++++++++++++++- 7 files changed, 155 insertions(+), 9 deletions(-) diff --git a/src/spdx/document_utils.py b/src/spdx/document_utils.py index a050ee5a2..647683fdd 100644 --- a/src/spdx/document_utils.py +++ b/src/spdx/document_utils.py @@ -1,7 +1,8 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict, List, Union +from copy import deepcopy +from typing import Any, Dict, List, Union from spdx.model.document import Document from spdx.model.file import File @@ -29,3 +30,30 @@ def get_contained_spdx_elements(document: Document) -> Dict[str, Union[Package, contained_spdx_elements.update({snippet.spdx_id: snippet for snippet in document.snippets}) return contained_spdx_elements + + +def create_document_without_duplicates(document: Document) -> Document: + document_without_duplicates = deepcopy(document) + for elements in [ + [document_without_duplicates.creation_info], + document_without_duplicates.files, + document_without_duplicates.packages, + document_without_duplicates.snippets, + document_without_duplicates.extracted_licensing_info, + ]: + for element in elements: + for key, value in element.__dict__.items(): + if isinstance(value, list): + value_without_duplicates = create_list_without_duplicates(value) + setattr(element, key, value_without_duplicates) + + return document_without_duplicates + + +def create_list_without_duplicates(list_with_potential_duplicates: List[Any]) -> List[Any]: + list_without_duplicates = [] + for element in list_with_potential_duplicates: + if element not in list_without_duplicates: + list_without_duplicates.append(element) + + return list_without_duplicates diff --git a/src/spdx/writer/json/json_writer.py b/src/spdx/writer/json/json_writer.py index 6a11671ce..88880d37c 100644 --- a/src/spdx/writer/json/json_writer.py +++ b/src/spdx/writer/json/json_writer.py @@ -4,6 +4,7 @@ import json from typing import List +from spdx.document_utils import create_document_without_duplicates from spdx.jsonschema.document_converter import DocumentConverter from spdx.model.document import Document from spdx.validation.document_validator import validate_full_spdx_document @@ -11,7 +12,11 @@ def write_document_to_file( - document: Document, file_name: str, validate: bool = True, converter: DocumentConverter = None + document: Document, + file_name: str, + validate: bool = True, + converter: DocumentConverter = None, + drop_duplicates: bool = True, ): """ Serializes the provided document to json and writes it to a file with the provided name. Unless validate is set @@ -22,6 +27,8 @@ def write_document_to_file( validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) if validation_messages: raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}") + if drop_duplicates: + document = create_document_without_duplicates(document) if converter is None: converter = DocumentConverter() document_dict = converter.convert(document) diff --git a/src/spdx/writer/rdf/rdf_writer.py b/src/spdx/writer/rdf/rdf_writer.py index 0e07a5818..78d30f6df 100644 --- a/src/spdx/writer/rdf/rdf_writer.py +++ b/src/spdx/writer/rdf/rdf_writer.py @@ -6,6 +6,7 @@ from rdflib import DOAP, Graph from rdflib.compare import to_isomorphic +from spdx.document_utils import create_document_without_duplicates from spdx.model.document import Document from spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE from spdx.validation.document_validator import validate_full_spdx_document @@ -19,12 +20,13 @@ from spdx.writer.rdf.snippet_writer import add_snippet_to_graph -def write_document_to_file(document: Document, file_name: str, validate: bool): +def write_document_to_file(document: Document, file_name: str, validate: bool, drop_duplicates: bool = True): if validate: validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) if validation_messages: raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}") - + if drop_duplicates: + document = create_document_without_duplicates(document) graph = Graph() doc_namespace = document.creation_info.document_namespace external_doc_ref_to_namespace: Dict[str, str] = { diff --git a/src/spdx/writer/tagvalue/tagvalue_writer.py b/src/spdx/writer/tagvalue/tagvalue_writer.py index 3c94e3dc4..418d3afee 100644 --- a/src/spdx/writer/tagvalue/tagvalue_writer.py +++ b/src/spdx/writer/tagvalue/tagvalue_writer.py @@ -10,6 +10,7 @@ # limitations under the License. from typing import List, TextIO +from spdx.document_utils import create_document_without_duplicates from spdx.model.document import Document from spdx.validation.document_validator import validate_full_spdx_document from spdx.validation.validation_message import ValidationMessage @@ -29,11 +30,13 @@ ) -def write_document_to_file(document: Document, file_name: str, validate: bool = True): +def write_document_to_file(document: Document, file_name: str, validate: bool = True, drop_duplicates: bool = True): if validate: validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) if validation_messages: raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}") + if drop_duplicates: + document = create_document_without_duplicates(document) with open(file_name, "w") as out: write_document(document, out) diff --git a/src/spdx/writer/xml/xml_writer.py b/src/spdx/writer/xml/xml_writer.py index 678010183..d9176cccc 100644 --- a/src/spdx/writer/xml/xml_writer.py +++ b/src/spdx/writer/xml/xml_writer.py @@ -5,6 +5,7 @@ import xmltodict +from spdx.document_utils import create_document_without_duplicates from spdx.jsonschema.document_converter import DocumentConverter from spdx.model.document import Document from spdx.validation.document_validator import validate_full_spdx_document @@ -12,7 +13,11 @@ def write_document_to_file( - document: Document, file_name: str, validate: bool = True, converter: DocumentConverter = None + document: Document, + file_name: str, + validate: bool = True, + converter: DocumentConverter = None, + drop_duplicates: bool = True, ): """ Serializes the provided document to XML and writes it to a file with the provided name. Unless validate is set @@ -23,6 +28,9 @@ def write_document_to_file( validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) if validation_messages: raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}") + if drop_duplicates: + document = create_document_without_duplicates(document) + if converter is None: converter = DocumentConverter() document_dict = {"Document": converter.convert(document)} diff --git a/src/spdx/writer/yaml/yaml_writer.py b/src/spdx/writer/yaml/yaml_writer.py index de3e27571..e93915f21 100644 --- a/src/spdx/writer/yaml/yaml_writer.py +++ b/src/spdx/writer/yaml/yaml_writer.py @@ -5,6 +5,7 @@ import yaml +from spdx.document_utils import create_document_without_duplicates from spdx.jsonschema.document_converter import DocumentConverter from spdx.model.document import Document from spdx.validation.document_validator import validate_full_spdx_document @@ -12,7 +13,11 @@ def write_document_to_file( - document: Document, file_name: str, validate: bool = True, converter: DocumentConverter = None + document: Document, + file_name: str, + validate: bool = True, + converter: DocumentConverter = None, + drop_duplicates: bool = True, ): """ Serializes the provided document to yaml and writes it to a file with the provided name. Unless validate is set @@ -23,6 +28,8 @@ def write_document_to_file( validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) if validation_messages: raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}") + if drop_duplicates: + document = create_document_without_duplicates(document) if converter is None: converter = DocumentConverter() document_dict = converter.convert(document) diff --git a/tests/spdx/test_document_utils.py b/tests/spdx/test_document_utils.py index a81a39bd8..bb40da4ff 100644 --- a/tests/spdx/test_document_utils.py +++ b/tests/spdx/test_document_utils.py @@ -5,8 +5,28 @@ import pytest -from spdx.document_utils import get_contained_spdx_element_ids, get_contained_spdx_elements, get_element_from_spdx_id -from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture, snippet_fixture +from spdx.document_utils import ( + create_document_without_duplicates, + create_list_without_duplicates, + get_contained_spdx_element_ids, + get_contained_spdx_elements, + get_element_from_spdx_id, +) +from spdx.model.file import FileType +from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx.model.spdx_none import SpdxNone +from tests.spdx.fixtures import ( + actor_fixture, + checksum_fixture, + creation_info_fixture, + document_fixture, + external_document_ref_fixture, + external_package_ref_fixture, + extracted_licensing_info_fixture, + file_fixture, + package_fixture, + snippet_fixture, +) @pytest.fixture @@ -34,3 +54,74 @@ def test_get_contained_spdx_elements(variables): assert contained_elements[package.spdx_id] == package assert contained_elements[file.spdx_id] == file assert contained_elements[snippet.spdx_id] == snippet + + +def test_create_list_without_duplicates(): + list_with_duplicates = [1, 2, 3, 5, 1, 67, 9, 67] + + list_without_duplicates = create_list_without_duplicates(list_with_duplicates) + + assert list_without_duplicates == [1, 2, 3, 5, 67, 9] + + +def test_create_document_without_duplicates(): + document = document_fixture( + creation_info=creation_info_fixture( + creators=[actor_fixture(name="creatorName"), actor_fixture(name="creatorName")], + external_document_refs=[external_document_ref_fixture(), external_document_ref_fixture()], + ), + packages=[ + package_fixture( + checksums=[checksum_fixture(), checksum_fixture()], + license_info_from_files=[SpdxNoAssertion(), SpdxNoAssertion()], + external_references=[external_package_ref_fixture(), external_package_ref_fixture()], + attribution_texts=["duplicated text", "duplicated text"], + ) + ], + files=[ + file_fixture( + checksums=[checksum_fixture(), checksum_fixture()], + file_types=[FileType.TEXT, FileType.TEXT], + license_info_in_file=[SpdxNoAssertion(), SpdxNoAssertion()], + contributors=["duplicated contributor", "duplicated contributor"], + attribution_texts=["duplicated text", "duplicated text"], + ) + ], + snippets=[ + snippet_fixture( + license_info_in_snippet=[SpdxNone(), SpdxNone()], + attribution_texts=["duplicated text", "duplicated text"], + ) + ], + extracted_licensing_info=[ + extracted_licensing_info_fixture(cross_references=["duplicated reference", "duplicated reference"]) + ], + ) + expected_document = document_fixture( + creation_info=creation_info_fixture( + creators=[actor_fixture(name="creatorName")], external_document_refs=[external_document_ref_fixture()] + ), + packages=[ + package_fixture( + checksums=[checksum_fixture()], + license_info_from_files=[SpdxNoAssertion()], + external_references=[external_package_ref_fixture()], + attribution_texts=["duplicated text"], + ) + ], + files=[ + file_fixture( + checksums=[checksum_fixture()], + file_types=[FileType.TEXT], + license_info_in_file=[SpdxNoAssertion()], + contributors=["duplicated contributor"], + attribution_texts=["duplicated text"], + ) + ], + snippets=[snippet_fixture(license_info_in_snippet=[SpdxNone()], attribution_texts=["duplicated text"])], + extracted_licensing_info=[extracted_licensing_info_fixture(cross_references=["duplicated reference"])], + ) + + document_without_duplicates = create_document_without_duplicates(document) + + assert document_without_duplicates == expected_document From cafd4da2f15f2d14a832608d949ebfe9a840368f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 18 Apr 2023 17:48:30 +0200 Subject: [PATCH 060/354] [issue-593] add imports to README example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 19ae4e3f2..906bb52d7 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,17 @@ instead of `bin`. ## Example Here are some examples of possible use cases to quickly get you started with the spdx-tools: ```python +import logging + +from license_expression import get_spdx_licensing + +from spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx.model.file import File, FileType +from spdx.model.relationship import Relationship, RelationshipType +from spdx.parser.parse_anything import parse_file +from spdx.validation.document_validator import validate_full_spdx_document +from spdx.writer.write_anything import write_file + # read in an SPDX document from a file document = parse_file("spdx_document.json") From b35941f23d497b8b2981fb95a33057515f921b96 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 19 Apr 2023 09:02:07 +0200 Subject: [PATCH 061/354] [issue_592] add top-level package Signed-off-by: Meret Behrens --- .flake8 | 2 +- .gitignore | 2 +- README.md | 12 +++--- pyproject.toml | 2 +- src/{ => spdx_tools}/common/__init__.py | 0 .../common/typing/__init__.py | 0 .../common/typing/constructor_type_errors.py | 0 .../typing/dataclass_with_properties.py | 0 .../common/typing/type_checks.py | 2 +- src/{ => spdx_tools}/spdx/__init__.py | 0 src/{ => spdx_tools}/spdx/casing_tools.py | 0 .../spdx/clitools/__init__.py | 0 .../spdx/clitools/pyspdxtools.py | 16 ++++---- src/{ => spdx_tools}/spdx/constants.py | 0 .../spdx/datetime_conversions.py | 0 src/{ => spdx_tools}/spdx/document_utils.py | 8 ++-- src/{ => spdx_tools}/spdx/formats.py | 2 +- src/{ => spdx_tools}/spdx/graph_generation.py | 12 +++--- .../spdx/jsonschema/__init__.py | 0 .../spdx/jsonschema/annotation_converter.py | 12 +++--- .../spdx/jsonschema/annotation_properties.py | 2 +- .../spdx/jsonschema/checksum_converter.py | 10 ++--- .../spdx/jsonschema/checksum_properties.py | 2 +- .../spdx/jsonschema/converter.py | 6 +-- .../jsonschema/creation_info_converter.py | 12 +++--- .../jsonschema/creation_info_properties.py | 2 +- .../spdx/jsonschema/document_converter.py | 26 ++++++------- .../spdx/jsonschema/document_properties.py | 2 +- .../external_document_ref_converter.py | 12 +++--- .../external_document_ref_properties.py | 2 +- .../external_package_ref_converter.py | 10 ++--- .../external_package_ref_properties.py | 2 +- .../extracted_licensing_info_converter.py | 12 +++--- .../extracted_licensing_info_properties.py | 2 +- .../spdx/jsonschema/file_converter.py | 16 ++++---- .../spdx/jsonschema/file_properties.py | 2 +- .../spdx/jsonschema/json_property.py | 0 .../spdx/jsonschema/optional_utils.py | 0 .../spdx/jsonschema/package_converter.py | 24 ++++++------ .../spdx/jsonschema/package_properties.py | 2 +- .../package_verification_code_converter.py | 10 ++--- .../package_verification_code_properties.py | 2 +- .../spdx/jsonschema/relationship_converter.py | 10 ++--- .../jsonschema/relationship_properties.py | 2 +- .../spdx/jsonschema/snippet_converter.py | 14 +++---- .../spdx/jsonschema/snippet_properties.py | 2 +- src/{ => spdx_tools}/spdx/model/__init__.py | 0 src/{ => spdx_tools}/spdx/model/actor.py | 4 +- src/{ => spdx_tools}/spdx/model/annotation.py | 6 +-- src/{ => spdx_tools}/spdx/model/checksum.py | 4 +- src/{ => spdx_tools}/spdx/model/document.py | 22 +++++------ .../spdx/model/external_document_ref.py | 6 +-- .../spdx/model/extracted_licensing_info.py | 6 +-- src/{ => spdx_tools}/spdx/model/file.py | 10 ++--- src/{ => spdx_tools}/spdx/model/package.py | 12 +++--- .../spdx/model/relationship.py | 8 ++-- .../spdx/model/relationship_filters.py | 6 +-- src/{ => spdx_tools}/spdx/model/snippet.py | 8 ++-- .../spdx/model/spdx_no_assertion.py | 0 src/{ => spdx_tools}/spdx/model/spdx_none.py | 0 src/{ => spdx_tools}/spdx/model/version.py | 0 src/{ => spdx_tools}/spdx/parser/__init__.py | 0 .../spdx/parser/actor_parser.py | 6 +-- src/{ => spdx_tools}/spdx/parser/error.py | 0 .../spdx/parser/json/__init__.py | 0 .../spdx/parser/json/json_parser.py | 4 +- .../spdx/parser/jsonlikedict/__init__.py | 0 .../parser/jsonlikedict/annotation_parser.py | 22 +++++++---- .../parser/jsonlikedict/checksum_parser.py | 11 ++++-- .../jsonlikedict/creation_info_parser.py | 27 +++++++------ .../jsonlikedict/dict_parsing_functions.py | 10 ++--- .../extracted_licensing_info_parser.py | 10 ++--- .../spdx/parser/jsonlikedict/file_parser.py | 21 +++++----- .../jsonlikedict/json_like_dict_parser.py | 27 +++++++------ .../jsonlikedict/license_expression_parser.py | 6 +-- .../parser/jsonlikedict/package_parser.py | 27 +++++++------ .../jsonlikedict/relationship_parser.py | 15 ++++--- .../parser/jsonlikedict/snippet_parser.py | 16 ++++---- src/{ => spdx_tools}/spdx/parser/logger.py | 0 .../spdx/parser/parse_anything.py | 12 +++--- .../spdx/parser/parsing_functions.py | 6 +-- .../spdx/parser/rdf/__init__.py | 0 .../spdx/parser/rdf/annotation_parser.py | 17 ++++---- .../spdx/parser/rdf/checksum_parser.py | 15 ++++--- .../spdx/parser/rdf/creation_info_parser.py | 27 +++++++------ .../rdf/extracted_licensing_info_parser.py | 13 ++++--- .../spdx/parser/rdf/file_parser.py | 17 ++++---- .../parser/rdf/graph_parsing_functions.py | 12 +++--- .../parser/rdf/license_expression_parser.py | 6 +-- .../spdx/parser/rdf/package_parser.py | 21 +++++----- .../spdx/parser/rdf/rdf_parser.py | 31 ++++++++------- .../spdx/parser/rdf/relationship_parser.py | 13 ++++--- .../spdx/parser/rdf/snippet_parser.py | 17 ++++---- .../spdx/parser/tagvalue/__init__.py | 0 .../spdx/parser/tagvalue/helper_methods.py | 18 ++++----- .../spdx/parser/tagvalue/lexer.py | 0 .../spdx/parser/tagvalue/parser.py | 39 ++++++++++--------- .../spdx/parser/tagvalue/tagvalue_parser.py | 4 +- .../spdx/parser/xml/__init__.py | 0 .../spdx/parser/xml/xml_parser.py | 6 +-- .../spdx/parser/yaml/__init__.py | 0 .../spdx/parser/yaml/yaml_parser.py | 4 +- src/{ => spdx_tools}/spdx/py.typed | 0 .../spdx/rdfschema/__init__.py | 0 .../spdx/rdfschema/namespace.py | 0 .../spdx/validation/__init__.py | 0 .../spdx/validation/actor_validator.py | 4 +- .../spdx/validation/annotation_validator.py | 10 ++--- .../spdx/validation/checksum_validator.py | 4 +- .../validation/creation_info_validator.py | 12 +++--- .../spdx/validation/document_validator.py | 24 ++++++------ .../external_document_ref_validator.py | 10 ++--- .../external_package_ref_validator.py | 10 +++-- .../extracted_licensing_info_validator.py | 6 +-- .../spdx/validation/file_validator.py | 17 ++++---- .../license_expression_validator.py | 8 ++-- .../spdx/validation/package_validator.py | 25 ++++++------ .../package_verification_code_validator.py | 4 +- .../spdx/validation/relationship_validator.py | 12 +++--- .../spdx/validation/snippet_validator.py | 13 ++++--- .../spdx/validation/spdx_id_validators.py | 6 +-- .../spdx/validation/uri_validators.py | 0 .../spdx/validation/validation_message.py | 0 src/{ => spdx_tools}/spdx/writer/__init__.py | 0 .../spdx/writer/json/__init__.py | 0 .../spdx/writer/json/json_writer.py | 10 ++--- .../spdx/writer/rdf/__init__.py | 0 .../spdx/writer/rdf/annotation_writer.py | 10 ++--- .../spdx/writer/rdf/checksum_writer.py | 4 +- .../spdx/writer/rdf/creation_info_writer.py | 10 ++--- .../rdf/external_document_ref_writer.py | 6 +-- .../rdf/extracted_licensing_info_writer.py | 6 +-- .../spdx/writer/rdf/file_writer.py | 12 +++--- .../writer/rdf/license_expression_writer.py | 6 +-- .../spdx/writer/rdf/package_writer.py | 12 +++--- .../spdx/writer/rdf/rdf_writer.py | 24 ++++++------ .../spdx/writer/rdf/relationship_writer.py | 12 +++--- .../spdx/writer/rdf/snippet_writer.py | 8 ++-- .../spdx/writer/rdf/writer_utils.py | 10 ++--- .../spdx/writer/tagvalue/__init__.py | 0 .../spdx/writer/tagvalue/annotation_writer.py | 6 +-- .../spdx/writer/tagvalue/checksum_writer.py | 2 +- .../writer/tagvalue/creation_info_writer.py | 6 +-- .../extracted_licensing_info_writer.py | 4 +- .../spdx/writer/tagvalue/file_writer.py | 6 +-- .../spdx/writer/tagvalue/package_writer.py | 8 ++-- .../writer/tagvalue/relationship_writer.py | 4 +- .../spdx/writer/tagvalue/snippet_writer.py | 4 +- .../spdx/writer/tagvalue/tagvalue_writer.py | 24 ++++++------ .../tagvalue_writer_helper_functions.py | 14 +++---- .../spdx/writer/write_anything.py | 14 +++---- .../spdx/writer/xml/__init__.py | 0 .../spdx/writer/xml/xml_writer.py | 10 ++--- .../spdx/writer/yaml/__init__.py | 0 .../spdx/writer/yaml/yaml_writer.py | 10 ++--- tests/spdx/fixtures.py | 28 ++++++------- .../jsonschema/test_annotation_converter.py | 10 ++--- .../jsonschema/test_checksum_converter.py | 6 +-- tests/spdx/jsonschema/test_converter.py | 12 +++--- .../test_creation_info_converter.py | 12 +++--- .../jsonschema/test_document_converter.py | 34 ++++++++-------- .../test_external_document_ref_converter.py | 10 ++--- .../test_external_package_ref_converter.py | 6 +-- ...test_extracted_licensing_info_converter.py | 8 ++-- tests/spdx/jsonschema/test_file_converter.py | 24 ++++++------ .../spdx/jsonschema/test_package_converter.py | 30 +++++++------- ...est_package_verification_code_converter.py | 6 +-- .../jsonschema/test_relationship_converter.py | 10 ++--- .../spdx/jsonschema/test_snippet_converter.py | 20 +++++----- tests/spdx/model/test_actor.py | 2 +- tests/spdx/model/test_annotation.py | 14 +++---- tests/spdx/model/test_checksum.py | 2 +- tests/spdx/model/test_creation_info.py | 28 ++++++------- tests/spdx/model/test_document.py | 30 +++++++------- .../spdx/model/test_external_document_ref.py | 8 ++-- .../model/test_external_package_reference.py | 2 +- .../model/test_extracted_licensing_info.py | 2 +- tests/spdx/model/test_file.py | 34 ++++++++-------- tests/spdx/model/test_package.py | 16 ++++---- .../model/test_package_verification_code.py | 2 +- tests/spdx/model/test_relationship.py | 4 +- tests/spdx/model/test_snippet.py | 6 +-- tests/spdx/model/test_version.py | 2 +- .../all_formats/test_parse_from_file.py | 12 +++--- .../jsonlikedict/test_annotation_parser.py | 16 ++++---- .../jsonlikedict/test_checksum_parser.py | 6 +-- .../jsonlikedict/test_creation_info_parser.py | 14 +++---- .../test_dict_parsing_functions.py | 8 ++-- .../test_extracted_licensing_info_parser.py | 4 +- .../parser/jsonlikedict/test_file_parser.py | 14 +++---- .../test_license_expression_parser.py | 8 ++-- .../jsonlikedict/test_package_parser.py | 27 +++++++------ .../jsonlikedict/test_relationship_parser.py | 12 +++--- .../jsonlikedict/test_snippet_parser.py | 8 ++-- .../spdx/parser/rdf/test_annotation_parser.py | 8 ++-- tests/spdx/parser/rdf/test_checksum_parser.py | 8 ++-- .../parser/rdf/test_creation_info_parser.py | 12 +++--- .../test_extracted_licensing_info_parser.py | 4 +- tests/spdx/parser/rdf/test_file_parser.py | 10 ++--- .../parser/rdf/test_graph_parsing_function.py | 2 +- .../rdf/test_license_expression_parser.py | 6 +-- tests/spdx/parser/rdf/test_package_parser.py | 12 +++--- .../parser/rdf/test_relationship_parser.py | 8 ++-- tests/spdx/parser/rdf/test_snippet_parser.py | 8 ++-- .../parser/tagvalue/test_annotation_parser.py | 8 ++-- .../tagvalue/test_creation_info_parser.py | 14 +++---- .../test_extracted_licensing_info_parser.py | 4 +- .../spdx/parser/tagvalue/test_file_parser.py | 8 ++-- .../parser/tagvalue/test_helper_methods.py | 4 +- .../parser/tagvalue/test_package_parser.py | 10 ++--- .../tagvalue/test_relationship_parser.py | 12 +++--- .../parser/tagvalue/test_snippet_parser.py | 6 +-- .../parser/tagvalue/test_tag_value_lexer.py | 4 +- .../parser/tagvalue/test_tag_value_parser.py | 8 ++-- tests/spdx/test_actor_parser.py | 6 +-- tests/spdx/test_casing_tools.py | 2 +- tests/spdx/test_cli.py | 2 +- tests/spdx/test_datetime_conversions.py | 2 +- tests/spdx/test_document_utils.py | 8 ++-- tests/spdx/test_graph_generation.py | 8 ++-- tests/spdx/validation/test_actor_validator.py | 8 ++-- .../validation/test_annotation_validator.py | 8 ++-- .../validation/test_checksum_validator.py | 6 +-- .../test_creation_info_validator.py | 6 +-- .../validation/test_document_validator.py | 12 +++--- .../test_external_document_ref_validator.py | 4 +- .../test_external_package_ref_validator.py | 6 +-- ...test_extracted_licensing_info_validator.py | 4 +- tests/spdx/validation/test_file_validator.py | 6 +-- .../test_license_expression_validator.py | 13 ++++--- .../spdx/validation/test_package_validator.py | 12 +++--- ...est_package_verification_code_validator.py | 6 +-- .../validation/test_relationship_validator.py | 14 +++---- .../spdx/validation/test_snippet_validator.py | 4 +- .../validation/test_spdx_id_validators.py | 4 +- tests/spdx/validation/test_uri_validators.py | 2 +- tests/spdx/writer/json/test_json_writer.py | 2 +- .../spdx/writer/rdf/test_annotation_writer.py | 6 +-- tests/spdx/writer/rdf/test_checksum_writer.py | 6 +-- .../writer/rdf/test_creation_info_writer.py | 6 +-- .../rdf/test_external_document_ref_writer.py | 4 +- .../test_extracted_licensing_info_writer.py | 4 +- tests/spdx/writer/rdf/test_file_writer.py | 4 +- .../rdf/test_license_expression_writer.py | 4 +- tests/spdx/writer/rdf/test_package_writer.py | 8 ++-- tests/spdx/writer/rdf/test_rdf_writer.py | 4 +- .../writer/rdf/test_relationship_writer.py | 6 +-- tests/spdx/writer/rdf/test_snippet_writer.py | 4 +- tests/spdx/writer/rdf/test_writer_utils.py | 2 +- .../writer/tagvalue/test_annotation_writer.py | 2 +- .../writer/tagvalue/test_checksum_writer.py | 4 +- .../tagvalue/test_creation_info_writer.py | 6 +-- .../test_extracted_licensing_info_writer.py | 2 +- .../spdx/writer/tagvalue/test_file_writer.py | 2 +- .../writer/tagvalue/test_package_writer.py | 2 +- .../tagvalue/test_relationship_writer.py | 6 +-- .../writer/tagvalue/test_snippet_writer.py | 2 +- .../writer/tagvalue/test_tagvalue_writer.py | 12 +++--- .../test_tagvalue_writer_helper_functions.py | 8 ++-- 259 files changed, 1108 insertions(+), 1029 deletions(-) rename src/{ => spdx_tools}/common/__init__.py (100%) rename src/{ => spdx_tools}/common/typing/__init__.py (100%) rename src/{ => spdx_tools}/common/typing/constructor_type_errors.py (100%) rename src/{ => spdx_tools}/common/typing/dataclass_with_properties.py (100%) rename src/{ => spdx_tools}/common/typing/type_checks.py (93%) rename src/{ => spdx_tools}/spdx/__init__.py (100%) rename src/{ => spdx_tools}/spdx/casing_tools.py (100%) rename src/{ => spdx_tools}/spdx/clitools/__init__.py (100%) rename src/{ => spdx_tools}/spdx/clitools/pyspdxtools.py (89%) rename src/{ => spdx_tools}/spdx/constants.py (100%) rename src/{ => spdx_tools}/spdx/datetime_conversions.py (100%) rename src/{ => spdx_tools}/spdx/document_utils.py (91%) rename src/{ => spdx_tools}/spdx/formats.py (93%) rename src/{ => spdx_tools}/spdx/graph_generation.py (90%) rename src/{ => spdx_tools}/spdx/jsonschema/__init__.py (100%) rename src/{ => spdx_tools}/spdx/jsonschema/annotation_converter.py (71%) rename src/{ => spdx_tools}/spdx/jsonschema/annotation_properties.py (79%) rename src/{ => spdx_tools}/spdx/jsonschema/checksum_converter.py (74%) rename src/{ => spdx_tools}/spdx/jsonschema/checksum_properties.py (75%) rename src/{ => spdx_tools}/spdx/jsonschema/converter.py (94%) rename src/{ => spdx_tools}/spdx/jsonschema/creation_info_converter.py (71%) rename src/{ => spdx_tools}/spdx/jsonschema/creation_info_properties.py (79%) rename src/{ => spdx_tools}/spdx/jsonschema/document_converter.py (81%) rename src/{ => spdx_tools}/spdx/jsonschema/document_properties.py (88%) rename src/{ => spdx_tools}/spdx/jsonschema/external_document_ref_converter.py (73%) rename src/{ => spdx_tools}/spdx/jsonschema/external_document_ref_properties.py (78%) rename src/{ => spdx_tools}/spdx/jsonschema/external_package_ref_converter.py (75%) rename src/{ => spdx_tools}/spdx/jsonschema/external_package_ref_properties.py (80%) rename src/{ => spdx_tools}/spdx/jsonschema/extracted_licensing_info_converter.py (76%) rename src/{ => spdx_tools}/spdx/jsonschema/extracted_licensing_info_properties.py (80%) rename src/{ => spdx_tools}/spdx/jsonschema/file_converter.py (84%) rename src/{ => spdx_tools}/spdx/jsonschema/file_properties.py (89%) rename src/{ => spdx_tools}/spdx/jsonschema/json_property.py (100%) rename src/{ => spdx_tools}/spdx/jsonschema/optional_utils.py (100%) rename src/{ => spdx_tools}/spdx/jsonschema/package_converter.py (86%) rename src/{ => spdx_tools}/spdx/jsonschema/package_properties.py (93%) rename src/{ => spdx_tools}/spdx/jsonschema/package_verification_code_converter.py (72%) rename src/{ => spdx_tools}/spdx/jsonschema/package_verification_code_properties.py (80%) rename src/{ => spdx_tools}/spdx/jsonschema/relationship_converter.py (75%) rename src/{ => spdx_tools}/spdx/jsonschema/relationship_properties.py (80%) rename src/{ => spdx_tools}/spdx/jsonschema/snippet_converter.py (87%) rename src/{ => spdx_tools}/spdx/jsonschema/snippet_properties.py (87%) rename src/{ => spdx_tools}/spdx/model/__init__.py (100%) rename src/{ => spdx_tools}/spdx/model/actor.py (84%) rename src/{ => spdx_tools}/spdx/model/annotation.py (75%) rename src/{ => spdx_tools}/spdx/model/checksum.py (81%) rename src/{ => spdx_tools}/spdx/model/document.py (78%) rename src/{ => spdx_tools}/spdx/model/external_document_ref.py (64%) rename src/{ => spdx_tools}/spdx/model/extracted_licensing_info.py (78%) rename src/{ => spdx_tools}/spdx/model/file.py (87%) rename src/{ => spdx_tools}/spdx/model/package.py (93%) rename src/{ => spdx_tools}/spdx/model/relationship.py (87%) rename src/{ => spdx_tools}/spdx/model/relationship_filters.py (90%) rename src/{ => spdx_tools}/spdx/model/snippet.py (85%) rename src/{ => spdx_tools}/spdx/model/spdx_no_assertion.py (100%) rename src/{ => spdx_tools}/spdx/model/spdx_none.py (100%) rename src/{ => spdx_tools}/spdx/model/version.py (100%) rename src/{ => spdx_tools}/spdx/parser/__init__.py (100%) rename src/{ => spdx_tools}/spdx/parser/actor_parser.py (91%) rename src/{ => spdx_tools}/spdx/parser/error.py (100%) rename src/{ => spdx_tools}/spdx/parser/json/__init__.py (100%) rename src/{ => spdx_tools}/spdx/parser/json/json_parser.py (69%) rename src/{ => spdx_tools}/spdx/parser/jsonlikedict/__init__.py (100%) rename src/{ => spdx_tools}/spdx/parser/jsonlikedict/annotation_parser.py (87%) rename src/{ => spdx_tools}/spdx/parser/jsonlikedict/checksum_parser.py (71%) rename src/{ => spdx_tools}/spdx/parser/jsonlikedict/creation_info_parser.py (86%) rename src/{ => spdx_tools}/spdx/parser/jsonlikedict/dict_parsing_functions.py (88%) rename src/{ => spdx_tools}/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py (76%) rename src/{ => spdx_tools}/spdx/parser/jsonlikedict/file_parser.py (83%) rename src/{ => spdx_tools}/spdx/parser/jsonlikedict/json_like_dict_parser.py (74%) rename src/{ => spdx_tools}/spdx/parser/jsonlikedict/license_expression_parser.py (83%) rename src/{ => spdx_tools}/spdx/parser/jsonlikedict/package_parser.py (91%) rename src/{ => spdx_tools}/spdx/parser/jsonlikedict/relationship_parser.py (94%) rename src/{ => spdx_tools}/spdx/parser/jsonlikedict/snippet_parser.py (91%) rename src/{ => spdx_tools}/spdx/parser/logger.py (100%) rename src/{ => spdx_tools}/spdx/parser/parse_anything.py (77%) rename src/{ => spdx_tools}/spdx/parser/parsing_functions.py (83%) rename src/{ => spdx_tools}/spdx/parser/rdf/__init__.py (100%) rename src/{ => spdx_tools}/spdx/parser/rdf/annotation_parser.py (70%) rename src/{ => spdx_tools}/spdx/parser/rdf/checksum_parser.py (68%) rename src/{ => spdx_tools}/spdx/parser/rdf/creation_info_parser.py (85%) rename src/{ => spdx_tools}/spdx/parser/rdf/extracted_licensing_info_parser.py (81%) rename src/{ => spdx_tools}/spdx/parser/rdf/file_parser.py (85%) rename src/{ => spdx_tools}/spdx/parser/rdf/graph_parsing_functions.py (92%) rename src/{ => spdx_tools}/spdx/parser/rdf/license_expression_parser.py (91%) rename src/{ => spdx_tools}/spdx/parser/rdf/package_parser.py (92%) rename src/{ => spdx_tools}/spdx/parser/rdf/rdf_parser.py (75%) rename src/{ => spdx_tools}/spdx/parser/rdf/relationship_parser.py (84%) rename src/{ => spdx_tools}/spdx/parser/rdf/snippet_parser.py (91%) rename src/{ => spdx_tools}/spdx/parser/tagvalue/__init__.py (100%) rename src/{ => spdx_tools}/spdx/parser/tagvalue/helper_methods.py (90%) rename src/{ => spdx_tools}/spdx/parser/tagvalue/lexer.py (100%) rename src/{ => spdx_tools}/spdx/parser/tagvalue/parser.py (95%) rename src/{ => spdx_tools}/spdx/parser/tagvalue/tagvalue_parser.py (72%) rename src/{ => spdx_tools}/spdx/parser/xml/__init__.py (100%) rename src/{ => spdx_tools}/spdx/parser/xml/xml_parser.py (90%) rename src/{ => spdx_tools}/spdx/parser/yaml/__init__.py (100%) rename src/{ => spdx_tools}/spdx/parser/yaml/yaml_parser.py (69%) rename src/{ => spdx_tools}/spdx/py.typed (100%) rename src/{ => spdx_tools}/spdx/rdfschema/__init__.py (100%) rename src/{ => spdx_tools}/spdx/rdfschema/namespace.py (100%) rename src/{ => spdx_tools}/spdx/validation/__init__.py (100%) rename src/{ => spdx_tools}/spdx/validation/actor_validator.py (83%) rename src/{ => spdx_tools}/spdx/validation/annotation_validator.py (71%) rename src/{ => spdx_tools}/spdx/validation/checksum_validator.py (93%) rename src/{ => spdx_tools}/spdx/validation/creation_info_validator.py (72%) rename src/{ => spdx_tools}/spdx/validation/document_validator.py (79%) rename src/{ => spdx_tools}/spdx/validation/external_document_ref_validator.py (78%) rename src/{ => spdx_tools}/spdx/validation/external_package_ref_validator.py (93%) rename src/{ => spdx_tools}/spdx/validation/extracted_licensing_info_validator.py (86%) rename src/{ => spdx_tools}/spdx/validation/file_validator.py (83%) rename src/{ => spdx_tools}/spdx/validation/license_expression_validator.py (90%) rename src/{ => spdx_tools}/spdx/validation/package_validator.py (85%) rename src/{ => spdx_tools}/spdx/validation/package_verification_code_validator.py (86%) rename src/{ => spdx_tools}/spdx/validation/relationship_validator.py (79%) rename src/{ => spdx_tools}/spdx/validation/snippet_validator.py (89%) rename src/{ => spdx_tools}/spdx/validation/spdx_id_validators.py (95%) rename src/{ => spdx_tools}/spdx/validation/uri_validators.py (100%) rename src/{ => spdx_tools}/spdx/validation/validation_message.py (100%) rename src/{ => spdx_tools}/spdx/writer/__init__.py (100%) rename src/{ => spdx_tools}/spdx/writer/json/__init__.py (100%) rename src/{ => spdx_tools}/spdx/writer/json/json_writer.py (75%) rename src/{ => spdx_tools}/spdx/writer/rdf/__init__.py (100%) rename src/{ => spdx_tools}/spdx/writer/rdf/annotation_writer.py (78%) rename src/{ => spdx_tools}/spdx/writer/rdf/checksum_writer.py (86%) rename src/{ => spdx_tools}/spdx/writer/rdf/creation_info_writer.py (80%) rename src/{ => spdx_tools}/spdx/writer/rdf/external_document_ref_writer.py (78%) rename src/{ => spdx_tools}/spdx/writer/rdf/extracted_licensing_info_writer.py (85%) rename src/{ => spdx_tools}/spdx/writer/rdf/file_writer.py (80%) rename src/{ => spdx_tools}/spdx/writer/rdf/license_expression_writer.py (94%) rename src/{ => spdx_tools}/spdx/writer/rdf/package_writer.py (93%) rename src/{ => spdx_tools}/spdx/writer/rdf/rdf_writer.py (68%) rename src/{ => spdx_tools}/spdx/writer/rdf/relationship_writer.py (81%) rename src/{ => spdx_tools}/spdx/writer/rdf/snippet_writer.py (89%) rename src/{ => spdx_tools}/spdx/writer/rdf/writer_utils.py (85%) rename src/{ => spdx_tools}/spdx/writer/tagvalue/__init__.py (100%) rename src/{ => spdx_tools}/spdx/writer/tagvalue/annotation_writer.py (82%) rename src/{ => spdx_tools}/spdx/writer/tagvalue/checksum_writer.py (95%) rename src/{ => spdx_tools}/spdx/writer/tagvalue/creation_info_writer.py (91%) rename src/{ => spdx_tools}/spdx/writer/tagvalue/extracted_licensing_info_writer.py (86%) rename src/{ => spdx_tools}/spdx/writer/tagvalue/file_writer.py (88%) rename src/{ => spdx_tools}/spdx/writer/tagvalue/package_writer.py (92%) rename src/{ => spdx_tools}/spdx/writer/tagvalue/relationship_writer.py (86%) rename src/{ => spdx_tools}/spdx/writer/tagvalue/snippet_writer.py (90%) rename src/{ => spdx_tools}/spdx/writer/tagvalue/tagvalue_writer.py (80%) rename src/{ => spdx_tools}/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py (91%) rename src/{ => spdx_tools}/spdx/writer/write_anything.py (67%) rename src/{ => spdx_tools}/spdx/writer/xml/__init__.py (100%) rename src/{ => spdx_tools}/spdx/writer/xml/xml_writer.py (75%) rename src/{ => spdx_tools}/spdx/writer/yaml/__init__.py (100%) rename src/{ => spdx_tools}/spdx/writer/yaml/yaml_writer.py (75%) diff --git a/.flake8 b/.flake8 index ae819fe55..3ca504408 100644 --- a/.flake8 +++ b/.flake8 @@ -1,4 +1,4 @@ [flake8] max-line-length = 119 -exclude = src/spdx/parser/tagvalue/parsetab.py +exclude = src/spdx_tools/spdx/parser/tagvalue/parsetab.py extend-ignore = E203 diff --git a/.gitignore b/.gitignore index 201c079bc..23a3c2678 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ __pycache__/ /build/ /dist/ /tmp/ -src/spdx/parser/tagvalue/parsetab.py +src/spdx_tools/spdx/parser/tagvalue/parsetab.py /.cache/ .tox diff --git a/README.md b/README.md index 906bb52d7..9c82d6ff9 100644 --- a/README.md +++ b/README.md @@ -123,12 +123,12 @@ import logging from license_expression import get_spdx_licensing -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.file import File, FileType -from spdx.model.relationship import Relationship, RelationshipType -from spdx.parser.parse_anything import parse_file -from spdx.validation.document_validator import validate_full_spdx_document -from spdx.writer.write_anything import write_file +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.file import File, FileType +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.parser.parse_anything import parse_file +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.writer.write_anything import write_file # read in an SPDX document from a file document = parse_file("spdx_document.json") diff --git a/pyproject.toml b/pyproject.toml index 7acbb7ffa..c9756834b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ graph_generation = ["pygraphviz", "networkx"] development = ["black", "flake8", "isort", "networkx", "pytest"] [project.scripts] -pyspdxtools = "spdx.clitools.pyspdxtools:main" +pyspdxtools = "spdx_tools.spdx.clitools.pyspdxtools:main" [tool.setuptools] zip-safe = false # because of the uses of __file__: https://github.com/spdx/tools-python/issues/257 diff --git a/src/common/__init__.py b/src/spdx_tools/common/__init__.py similarity index 100% rename from src/common/__init__.py rename to src/spdx_tools/common/__init__.py diff --git a/src/common/typing/__init__.py b/src/spdx_tools/common/typing/__init__.py similarity index 100% rename from src/common/typing/__init__.py rename to src/spdx_tools/common/typing/__init__.py diff --git a/src/common/typing/constructor_type_errors.py b/src/spdx_tools/common/typing/constructor_type_errors.py similarity index 100% rename from src/common/typing/constructor_type_errors.py rename to src/spdx_tools/common/typing/constructor_type_errors.py diff --git a/src/common/typing/dataclass_with_properties.py b/src/spdx_tools/common/typing/dataclass_with_properties.py similarity index 100% rename from src/common/typing/dataclass_with_properties.py rename to src/spdx_tools/common/typing/dataclass_with_properties.py diff --git a/src/common/typing/type_checks.py b/src/spdx_tools/common/typing/type_checks.py similarity index 93% rename from src/common/typing/type_checks.py rename to src/spdx_tools/common/typing/type_checks.py index 71a741f04..09e3f5d49 100644 --- a/src/common/typing/type_checks.py +++ b/src/spdx_tools/common/typing/type_checks.py @@ -1,6 +1,6 @@ from typing import Any, Dict -from common.typing.constructor_type_errors import ConstructorTypeErrors +from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors def check_types_and_set_values(instance_under_construction: Any, local_variables: Dict) -> None: diff --git a/src/spdx/__init__.py b/src/spdx_tools/spdx/__init__.py similarity index 100% rename from src/spdx/__init__.py rename to src/spdx_tools/spdx/__init__.py diff --git a/src/spdx/casing_tools.py b/src/spdx_tools/spdx/casing_tools.py similarity index 100% rename from src/spdx/casing_tools.py rename to src/spdx_tools/spdx/casing_tools.py diff --git a/src/spdx/clitools/__init__.py b/src/spdx_tools/spdx/clitools/__init__.py similarity index 100% rename from src/spdx/clitools/__init__.py rename to src/spdx_tools/spdx/clitools/__init__.py diff --git a/src/spdx/clitools/pyspdxtools.py b/src/spdx_tools/spdx/clitools/pyspdxtools.py similarity index 89% rename from src/spdx/clitools/pyspdxtools.py rename to src/spdx_tools/spdx/clitools/pyspdxtools.py index f2d480ea1..1983106d6 100644 --- a/src/spdx/clitools/pyspdxtools.py +++ b/src/spdx_tools/spdx/clitools/pyspdxtools.py @@ -18,14 +18,14 @@ import click -from spdx.graph_generation import export_graph_from_document -from spdx.model.document import Document -from spdx.parser.error import SPDXParsingError -from spdx.parser.parse_anything import parse_file -from spdx.validation.document_validator import validate_full_spdx_document -from spdx.validation.validation_message import ValidationMessage -from spdx.writer.tagvalue import tagvalue_writer -from spdx.writer.write_anything import write_file +from spdx_tools.spdx.graph_generation import export_graph_from_document +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.parse_anything import parse_file +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.writer.tagvalue import tagvalue_writer +from spdx_tools.spdx.writer.write_anything import write_file @click.command() diff --git a/src/spdx/constants.py b/src/spdx_tools/spdx/constants.py similarity index 100% rename from src/spdx/constants.py rename to src/spdx_tools/spdx/constants.py diff --git a/src/spdx/datetime_conversions.py b/src/spdx_tools/spdx/datetime_conversions.py similarity index 100% rename from src/spdx/datetime_conversions.py rename to src/spdx_tools/spdx/datetime_conversions.py diff --git a/src/spdx/document_utils.py b/src/spdx_tools/spdx/document_utils.py similarity index 91% rename from src/spdx/document_utils.py rename to src/spdx_tools/spdx/document_utils.py index 647683fdd..0afc01702 100644 --- a/src/spdx/document_utils.py +++ b/src/spdx_tools/spdx/document_utils.py @@ -4,10 +4,10 @@ from copy import deepcopy from typing import Any, Dict, List, Union -from spdx.model.document import Document -from spdx.model.file import File -from spdx.model.package import Package -from spdx.model.snippet import Snippet +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.model.package import Package +from spdx_tools.spdx.model.snippet import Snippet def get_contained_spdx_element_ids(document: Document) -> List[str]: diff --git a/src/spdx/formats.py b/src/spdx_tools/spdx/formats.py similarity index 93% rename from src/spdx/formats.py rename to src/spdx_tools/spdx/formats.py index 0500088a6..56f5b1663 100644 --- a/src/spdx/formats.py +++ b/src/spdx_tools/spdx/formats.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto -from spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.error import SPDXParsingError class FileFormat(Enum): diff --git a/src/spdx/graph_generation.py b/src/spdx_tools/spdx/graph_generation.py similarity index 90% rename from src/spdx/graph_generation.py rename to src/spdx_tools/spdx/graph_generation.py index 40d673315..6052af995 100644 --- a/src/spdx/graph_generation.py +++ b/src/spdx_tools/spdx/graph_generation.py @@ -3,17 +3,17 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Dict, List, Union -from spdx.model.file import File -from spdx.model.package import Package -from spdx.model.snippet import Snippet +from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.model.package import Package +from spdx_tools.spdx.model.snippet import Snippet try: from networkx import DiGraph except ImportError: DiGraph = None -from spdx.document_utils import get_contained_spdx_elements -from spdx.model.document import Document -from spdx.model.relationship import Relationship +from spdx_tools.spdx.document_utils import get_contained_spdx_elements +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.relationship import Relationship def export_graph_from_document(document: Document, file_name: str) -> None: diff --git a/src/spdx/jsonschema/__init__.py b/src/spdx_tools/spdx/jsonschema/__init__.py similarity index 100% rename from src/spdx/jsonschema/__init__.py rename to src/spdx_tools/spdx/jsonschema/__init__.py diff --git a/src/spdx/jsonschema/annotation_converter.py b/src/spdx_tools/spdx/jsonschema/annotation_converter.py similarity index 71% rename from src/spdx/jsonschema/annotation_converter.py rename to src/spdx_tools/spdx/jsonschema/annotation_converter.py index 86aaafc32..a345353e4 100644 --- a/src/spdx/jsonschema/annotation_converter.py +++ b/src/spdx_tools/spdx/jsonschema/annotation_converter.py @@ -3,12 +3,12 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.jsonschema.annotation_properties import AnnotationProperty -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.json_property import JsonProperty -from spdx.model.annotation import Annotation -from spdx.model.document import Document +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.jsonschema.annotation_properties import AnnotationProperty +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.model.annotation import Annotation +from spdx_tools.spdx.model.document import Document class AnnotationConverter(TypedConverter[Annotation]): diff --git a/src/spdx/jsonschema/annotation_properties.py b/src/spdx_tools/spdx/jsonschema/annotation_properties.py similarity index 79% rename from src/spdx/jsonschema/annotation_properties.py rename to src/spdx_tools/spdx/jsonschema/annotation_properties.py index 659e222aa..e8226f945 100644 --- a/src/spdx/jsonschema/annotation_properties.py +++ b/src/spdx_tools/spdx/jsonschema/annotation_properties.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import auto -from spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty class AnnotationProperty(JsonProperty): diff --git a/src/spdx/jsonschema/checksum_converter.py b/src/spdx_tools/spdx/jsonschema/checksum_converter.py similarity index 74% rename from src/spdx/jsonschema/checksum_converter.py rename to src/spdx_tools/spdx/jsonschema/checksum_converter.py index 2cbdcf2b1..536e65974 100644 --- a/src/spdx/jsonschema/checksum_converter.py +++ b/src/spdx_tools/spdx/jsonschema/checksum_converter.py @@ -3,11 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Type -from spdx.jsonschema.checksum_properties import ChecksumProperty -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.json_property import JsonProperty -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.document import Document +from spdx_tools.spdx.jsonschema.checksum_properties import ChecksumProperty +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.document import Document class ChecksumConverter(TypedConverter[Checksum]): diff --git a/src/spdx/jsonschema/checksum_properties.py b/src/spdx_tools/spdx/jsonschema/checksum_properties.py similarity index 75% rename from src/spdx/jsonschema/checksum_properties.py rename to src/spdx_tools/spdx/jsonschema/checksum_properties.py index adac99357..c9e2f70c6 100644 --- a/src/spdx/jsonschema/checksum_properties.py +++ b/src/spdx_tools/spdx/jsonschema/checksum_properties.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import auto -from spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty class ChecksumProperty(JsonProperty): diff --git a/src/spdx/jsonschema/converter.py b/src/spdx_tools/spdx/jsonschema/converter.py similarity index 94% rename from src/spdx/jsonschema/converter.py rename to src/spdx_tools/spdx/jsonschema/converter.py index 8607f4a91..a613e3f3c 100644 --- a/src/spdx/jsonschema/converter.py +++ b/src/spdx_tools/spdx/jsonschema/converter.py @@ -4,9 +4,9 @@ from abc import ABC, abstractmethod from typing import Any, Dict, Generic, Type, TypeVar -from spdx.casing_tools import snake_case_to_camel_case -from spdx.jsonschema.json_property import JsonProperty -from spdx.model.document import Document +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.model.document import Document MISSING_IMPLEMENTATION_MESSAGE = "Must be implemented" diff --git a/src/spdx/jsonschema/creation_info_converter.py b/src/spdx_tools/spdx/jsonschema/creation_info_converter.py similarity index 71% rename from src/spdx/jsonschema/creation_info_converter.py rename to src/spdx_tools/spdx/jsonschema/creation_info_converter.py index c9e5d0f97..9d8832a03 100644 --- a/src/spdx/jsonschema/creation_info_converter.py +++ b/src/spdx_tools/spdx/jsonschema/creation_info_converter.py @@ -3,12 +3,12 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.creation_info_properties import CreationInfoProperty -from spdx.jsonschema.json_property import JsonProperty -from spdx.jsonschema.optional_utils import apply_if_present -from spdx.model.document import CreationInfo, Document +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.creation_info_properties import CreationInfoProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present +from spdx_tools.spdx.model.document import CreationInfo, Document class CreationInfoConverter(TypedConverter[CreationInfo]): diff --git a/src/spdx/jsonschema/creation_info_properties.py b/src/spdx_tools/spdx/jsonschema/creation_info_properties.py similarity index 79% rename from src/spdx/jsonschema/creation_info_properties.py rename to src/spdx_tools/spdx/jsonschema/creation_info_properties.py index d5a16eb2e..8385b646c 100644 --- a/src/spdx/jsonschema/creation_info_properties.py +++ b/src/spdx_tools/spdx/jsonschema/creation_info_properties.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import auto -from spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty class CreationInfoProperty(JsonProperty): diff --git a/src/spdx/jsonschema/document_converter.py b/src/spdx_tools/spdx/jsonschema/document_converter.py similarity index 81% rename from src/spdx/jsonschema/document_converter.py rename to src/spdx_tools/spdx/jsonschema/document_converter.py index 2b9967dfb..1ccf74fd4 100644 --- a/src/spdx/jsonschema/document_converter.py +++ b/src/spdx_tools/spdx/jsonschema/document_converter.py @@ -3,19 +3,19 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type -from spdx.document_utils import get_contained_spdx_element_ids -from spdx.jsonschema.annotation_converter import AnnotationConverter -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.creation_info_converter import CreationInfoConverter -from spdx.jsonschema.document_properties import DocumentProperty -from spdx.jsonschema.external_document_ref_converter import ExternalDocumentRefConverter -from spdx.jsonschema.extracted_licensing_info_converter import ExtractedLicensingInfoConverter -from spdx.jsonschema.file_converter import FileConverter -from spdx.jsonschema.json_property import JsonProperty -from spdx.jsonschema.package_converter import PackageConverter -from spdx.jsonschema.relationship_converter import RelationshipConverter -from spdx.jsonschema.snippet_converter import SnippetConverter -from spdx.model.document import Document +from spdx_tools.spdx.document_utils import get_contained_spdx_element_ids +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.creation_info_converter import CreationInfoConverter +from spdx_tools.spdx.jsonschema.document_properties import DocumentProperty +from spdx_tools.spdx.jsonschema.external_document_ref_converter import ExternalDocumentRefConverter +from spdx_tools.spdx.jsonschema.extracted_licensing_info_converter import ExtractedLicensingInfoConverter +from spdx_tools.spdx.jsonschema.file_converter import FileConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.package_converter import PackageConverter +from spdx_tools.spdx.jsonschema.relationship_converter import RelationshipConverter +from spdx_tools.spdx.jsonschema.snippet_converter import SnippetConverter +from spdx_tools.spdx.model.document import Document class DocumentConverter(TypedConverter[Document]): diff --git a/src/spdx/jsonschema/document_properties.py b/src/spdx_tools/spdx/jsonschema/document_properties.py similarity index 88% rename from src/spdx/jsonschema/document_properties.py rename to src/spdx_tools/spdx/jsonschema/document_properties.py index 045ecb7c0..9b56fa775 100644 --- a/src/spdx/jsonschema/document_properties.py +++ b/src/spdx_tools/spdx/jsonschema/document_properties.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import auto -from spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty class DocumentProperty(JsonProperty): diff --git a/src/spdx/jsonschema/external_document_ref_converter.py b/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py similarity index 73% rename from src/spdx/jsonschema/external_document_ref_converter.py rename to src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py index cc3d28bfc..f9d483a9b 100644 --- a/src/spdx/jsonschema/external_document_ref_converter.py +++ b/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py @@ -3,12 +3,12 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type -from spdx.jsonschema.checksum_converter import ChecksumConverter -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.external_document_ref_properties import ExternalDocumentRefProperty -from spdx.jsonschema.json_property import JsonProperty -from spdx.model.document import Document -from spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.jsonschema.checksum_converter import ChecksumConverter +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.external_document_ref_properties import ExternalDocumentRefProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef class ExternalDocumentRefConverter(TypedConverter[ExternalDocumentRef]): diff --git a/src/spdx/jsonschema/external_document_ref_properties.py b/src/spdx_tools/spdx/jsonschema/external_document_ref_properties.py similarity index 78% rename from src/spdx/jsonschema/external_document_ref_properties.py rename to src/spdx_tools/spdx/jsonschema/external_document_ref_properties.py index 16f1c33b8..822275179 100644 --- a/src/spdx/jsonschema/external_document_ref_properties.py +++ b/src/spdx_tools/spdx/jsonschema/external_document_ref_properties.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import auto -from spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty class ExternalDocumentRefProperty(JsonProperty): diff --git a/src/spdx/jsonschema/external_package_ref_converter.py b/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py similarity index 75% rename from src/spdx/jsonschema/external_package_ref_converter.py rename to src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py index 3df3215ca..f6fec734e 100644 --- a/src/spdx/jsonschema/external_package_ref_converter.py +++ b/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py @@ -3,11 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.external_package_ref_properties import ExternalPackageRefProperty -from spdx.jsonschema.json_property import JsonProperty -from spdx.model.document import Document -from spdx.model.package import ExternalPackageRef +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.external_package_ref_properties import ExternalPackageRefProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.package import ExternalPackageRef class ExternalPackageRefConverter(TypedConverter[ExternalPackageRef]): diff --git a/src/spdx/jsonschema/external_package_ref_properties.py b/src/spdx_tools/spdx/jsonschema/external_package_ref_properties.py similarity index 80% rename from src/spdx/jsonschema/external_package_ref_properties.py rename to src/spdx_tools/spdx/jsonschema/external_package_ref_properties.py index 153b37118..a9d249788 100644 --- a/src/spdx/jsonschema/external_package_ref_properties.py +++ b/src/spdx_tools/spdx/jsonschema/external_package_ref_properties.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import auto -from spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty class ExternalPackageRefProperty(JsonProperty): diff --git a/src/spdx/jsonschema/extracted_licensing_info_converter.py b/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py similarity index 76% rename from src/spdx/jsonschema/extracted_licensing_info_converter.py rename to src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py index 10c11b27d..6f49c2505 100644 --- a/src/spdx/jsonschema/extracted_licensing_info_converter.py +++ b/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py @@ -3,12 +3,12 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.extracted_licensing_info_properties import ExtractedLicensingInfoProperty -from spdx.jsonschema.json_property import JsonProperty -from spdx.jsonschema.optional_utils import apply_if_present -from spdx.model.document import Document -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.extracted_licensing_info_properties import ExtractedLicensingInfoProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo class ExtractedLicensingInfoConverter(TypedConverter[ExtractedLicensingInfo]): diff --git a/src/spdx/jsonschema/extracted_licensing_info_properties.py b/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_properties.py similarity index 80% rename from src/spdx/jsonschema/extracted_licensing_info_properties.py rename to src/spdx_tools/spdx/jsonschema/extracted_licensing_info_properties.py index f7d735079..b692c6ec3 100644 --- a/src/spdx/jsonschema/extracted_licensing_info_properties.py +++ b/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_properties.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import auto -from spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty class ExtractedLicensingInfoProperty(JsonProperty): diff --git a/src/spdx/jsonschema/file_converter.py b/src/spdx_tools/spdx/jsonschema/file_converter.py similarity index 84% rename from src/spdx/jsonschema/file_converter.py rename to src/spdx_tools/spdx/jsonschema/file_converter.py index 841c4e4b4..6ce642110 100644 --- a/src/spdx/jsonschema/file_converter.py +++ b/src/spdx_tools/spdx/jsonschema/file_converter.py @@ -3,14 +3,14 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type -from spdx.jsonschema.annotation_converter import AnnotationConverter -from spdx.jsonschema.checksum_converter import ChecksumConverter -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.file_properties import FileProperty -from spdx.jsonschema.json_property import JsonProperty -from spdx.jsonschema.optional_utils import apply_if_present -from spdx.model.document import Document -from spdx.model.file import File +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.checksum_converter import ChecksumConverter +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.file_properties import FileProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.file import File class FileConverter(TypedConverter[File]): diff --git a/src/spdx/jsonschema/file_properties.py b/src/spdx_tools/spdx/jsonschema/file_properties.py similarity index 89% rename from src/spdx/jsonschema/file_properties.py rename to src/spdx_tools/spdx/jsonschema/file_properties.py index d0179b353..c1d584eb5 100644 --- a/src/spdx/jsonschema/file_properties.py +++ b/src/spdx_tools/spdx/jsonschema/file_properties.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import auto -from spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty class FileProperty(JsonProperty): diff --git a/src/spdx/jsonschema/json_property.py b/src/spdx_tools/spdx/jsonschema/json_property.py similarity index 100% rename from src/spdx/jsonschema/json_property.py rename to src/spdx_tools/spdx/jsonschema/json_property.py diff --git a/src/spdx/jsonschema/optional_utils.py b/src/spdx_tools/spdx/jsonschema/optional_utils.py similarity index 100% rename from src/spdx/jsonschema/optional_utils.py rename to src/spdx_tools/spdx/jsonschema/optional_utils.py diff --git a/src/spdx/jsonschema/package_converter.py b/src/spdx_tools/spdx/jsonschema/package_converter.py similarity index 86% rename from src/spdx/jsonschema/package_converter.py rename to src/spdx_tools/spdx/jsonschema/package_converter.py index 0019b80a3..992eb649a 100644 --- a/src/spdx/jsonschema/package_converter.py +++ b/src/spdx_tools/spdx/jsonschema/package_converter.py @@ -3,18 +3,18 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.jsonschema.annotation_converter import AnnotationConverter -from spdx.jsonschema.checksum_converter import ChecksumConverter -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.external_package_ref_converter import ExternalPackageRefConverter -from spdx.jsonschema.json_property import JsonProperty -from spdx.jsonschema.optional_utils import apply_if_present -from spdx.jsonschema.package_properties import PackageProperty -from spdx.jsonschema.package_verification_code_converter import PackageVerificationCodeConverter -from spdx.model.actor import Actor -from spdx.model.document import Document -from spdx.model.package import Package +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.checksum_converter import ChecksumConverter +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.external_package_ref_converter import ExternalPackageRefConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present +from spdx_tools.spdx.jsonschema.package_properties import PackageProperty +from spdx_tools.spdx.jsonschema.package_verification_code_converter import PackageVerificationCodeConverter +from spdx_tools.spdx.model.actor import Actor +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.package import Package class PackageConverter(TypedConverter[Package]): diff --git a/src/spdx/jsonschema/package_properties.py b/src/spdx_tools/spdx/jsonschema/package_properties.py similarity index 93% rename from src/spdx/jsonschema/package_properties.py rename to src/spdx_tools/spdx/jsonschema/package_properties.py index 60ba0ff20..903fb1968 100644 --- a/src/spdx/jsonschema/package_properties.py +++ b/src/spdx_tools/spdx/jsonschema/package_properties.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import auto -from spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty class PackageProperty(JsonProperty): diff --git a/src/spdx/jsonschema/package_verification_code_converter.py b/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py similarity index 72% rename from src/spdx/jsonschema/package_verification_code_converter.py rename to src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py index 6eb48674c..f2a2f27e2 100644 --- a/src/spdx/jsonschema/package_verification_code_converter.py +++ b/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py @@ -3,11 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.json_property import JsonProperty -from spdx.jsonschema.package_verification_code_properties import PackageVerificationCodeProperty -from spdx.model.document import Document -from spdx.model.package import PackageVerificationCode +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.package_verification_code_properties import PackageVerificationCodeProperty +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.package import PackageVerificationCode class PackageVerificationCodeConverter(TypedConverter[PackageVerificationCode]): diff --git a/src/spdx/jsonschema/package_verification_code_properties.py b/src/spdx_tools/spdx/jsonschema/package_verification_code_properties.py similarity index 80% rename from src/spdx/jsonschema/package_verification_code_properties.py rename to src/spdx_tools/spdx/jsonschema/package_verification_code_properties.py index 0ffa2391c..f73410385 100644 --- a/src/spdx/jsonschema/package_verification_code_properties.py +++ b/src/spdx_tools/spdx/jsonschema/package_verification_code_properties.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import auto -from spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty class PackageVerificationCodeProperty(JsonProperty): diff --git a/src/spdx/jsonschema/relationship_converter.py b/src/spdx_tools/spdx/jsonschema/relationship_converter.py similarity index 75% rename from src/spdx/jsonschema/relationship_converter.py rename to src/spdx_tools/spdx/jsonschema/relationship_converter.py index bc3b06bda..e3be442b9 100644 --- a/src/spdx/jsonschema/relationship_converter.py +++ b/src/spdx_tools/spdx/jsonschema/relationship_converter.py @@ -3,11 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Type -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.json_property import JsonProperty -from spdx.jsonschema.relationship_properties import RelationshipProperty -from spdx.model.document import Document -from spdx.model.relationship import Relationship +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.relationship_properties import RelationshipProperty +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.relationship import Relationship class RelationshipConverter(TypedConverter[Relationship]): diff --git a/src/spdx/jsonschema/relationship_properties.py b/src/spdx_tools/spdx/jsonschema/relationship_properties.py similarity index 80% rename from src/spdx/jsonschema/relationship_properties.py rename to src/spdx_tools/spdx/jsonschema/relationship_properties.py index bfb2031c8..73c1259e9 100644 --- a/src/spdx/jsonschema/relationship_properties.py +++ b/src/spdx_tools/spdx/jsonschema/relationship_properties.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import auto -from spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty class RelationshipProperty(JsonProperty): diff --git a/src/spdx/jsonschema/snippet_converter.py b/src/spdx_tools/spdx/jsonschema/snippet_converter.py similarity index 87% rename from src/spdx/jsonschema/snippet_converter.py rename to src/spdx_tools/spdx/jsonschema/snippet_converter.py index e3fcd2b83..1d74a9c4d 100644 --- a/src/spdx/jsonschema/snippet_converter.py +++ b/src/spdx_tools/spdx/jsonschema/snippet_converter.py @@ -3,13 +3,13 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Dict, Tuple, Type -from spdx.jsonschema.annotation_converter import AnnotationConverter -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.json_property import JsonProperty -from spdx.jsonschema.optional_utils import apply_if_present -from spdx.jsonschema.snippet_properties import SnippetProperty -from spdx.model.document import Document -from spdx.model.snippet import Snippet +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present +from spdx_tools.spdx.jsonschema.snippet_properties import SnippetProperty +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.snippet import Snippet class SnippetConverter(TypedConverter[Snippet]): diff --git a/src/spdx/jsonschema/snippet_properties.py b/src/spdx_tools/spdx/jsonschema/snippet_properties.py similarity index 87% rename from src/spdx/jsonschema/snippet_properties.py rename to src/spdx_tools/spdx/jsonschema/snippet_properties.py index f485d59d0..772a58401 100644 --- a/src/spdx/jsonschema/snippet_properties.py +++ b/src/spdx_tools/spdx/jsonschema/snippet_properties.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from enum import auto -from spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.jsonschema.json_property import JsonProperty class SnippetProperty(JsonProperty): diff --git a/src/spdx/model/__init__.py b/src/spdx_tools/spdx/model/__init__.py similarity index 100% rename from src/spdx/model/__init__.py rename to src/spdx_tools/spdx/model/__init__.py diff --git a/src/spdx/model/actor.py b/src/spdx_tools/spdx/model/actor.py similarity index 84% rename from src/spdx/model/actor.py rename to src/spdx_tools/spdx/model/actor.py index 9160581e0..aff462bfc 100644 --- a/src/spdx/model/actor.py +++ b/src/spdx_tools/spdx/model/actor.py @@ -4,8 +4,8 @@ from enum import Enum, auto from typing import Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values class ActorType(Enum): diff --git a/src/spdx/model/annotation.py b/src/spdx_tools/spdx/model/annotation.py similarity index 75% rename from src/spdx/model/annotation.py rename to src/spdx_tools/spdx/model/annotation.py index 0e07f98fa..d128e57a9 100644 --- a/src/spdx/model/annotation.py +++ b/src/spdx_tools/spdx/model/annotation.py @@ -4,9 +4,9 @@ from datetime import datetime from enum import Enum, auto -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx.model.actor import Actor +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model.actor import Actor class AnnotationType(Enum): diff --git a/src/spdx/model/checksum.py b/src/spdx_tools/spdx/model/checksum.py similarity index 81% rename from src/spdx/model/checksum.py rename to src/spdx_tools/spdx/model/checksum.py index 5ec824fc1..7889e1163 100644 --- a/src/spdx/model/checksum.py +++ b/src/spdx_tools/spdx/model/checksum.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values class ChecksumAlgorithm(Enum): diff --git a/src/spdx/model/document.py b/src/spdx_tools/spdx/model/document.py similarity index 78% rename from src/spdx/model/document.py rename to src/spdx_tools/spdx/model/document.py index 0f2802a59..b6c7128b5 100644 --- a/src/spdx/model/document.py +++ b/src/spdx_tools/spdx/model/document.py @@ -5,17 +5,17 @@ from datetime import datetime from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx.model.actor import Actor -from spdx.model.annotation import Annotation -from spdx.model.external_document_ref import ExternalDocumentRef -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.model.file import File -from spdx.model.package import Package -from spdx.model.relationship import Relationship -from spdx.model.snippet import Snippet -from spdx.model.version import Version +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model.actor import Actor +from spdx_tools.spdx.model.annotation import Annotation +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.model.package import Package +from spdx_tools.spdx.model.relationship import Relationship +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model.version import Version @dataclass_with_properties diff --git a/src/spdx/model/external_document_ref.py b/src/spdx_tools/spdx/model/external_document_ref.py similarity index 64% rename from src/spdx/model/external_document_ref.py rename to src/spdx_tools/spdx/model/external_document_ref.py index afcb8450f..5d8233ba9 100644 --- a/src/spdx/model/external_document_ref.py +++ b/src/spdx_tools/spdx/model/external_document_ref.py @@ -2,9 +2,9 @@ # # SPDX-License-Identifier: Apache-2.0 -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx.model.checksum import Checksum +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model.checksum import Checksum @dataclass_with_properties diff --git a/src/spdx/model/extracted_licensing_info.py b/src/spdx_tools/spdx/model/extracted_licensing_info.py similarity index 78% rename from src/spdx/model/extracted_licensing_info.py rename to src/spdx_tools/spdx/model/extracted_licensing_info.py index 4b83dae20..017f82bf3 100644 --- a/src/spdx/model/extracted_licensing_info.py +++ b/src/spdx_tools/spdx/model/extracted_licensing_info.py @@ -4,9 +4,9 @@ from dataclasses import field from typing import List, Optional, Union -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion @dataclass_with_properties diff --git a/src/spdx/model/file.py b/src/spdx_tools/spdx/model/file.py similarity index 87% rename from src/spdx/model/file.py rename to src/spdx_tools/spdx/model/file.py index 6df5ba3f3..c46ba3f97 100644 --- a/src/spdx/model/file.py +++ b/src/spdx_tools/spdx/model/file.py @@ -7,11 +7,11 @@ from license_expression import LicenseExpression -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx.model.checksum import Checksum -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model.checksum import Checksum +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone class FileType(Enum): diff --git a/src/spdx/model/package.py b/src/spdx_tools/spdx/model/package.py similarity index 93% rename from src/spdx/model/package.py rename to src/spdx_tools/spdx/model/package.py index 196c44236..be54abcaf 100644 --- a/src/spdx/model/package.py +++ b/src/spdx_tools/spdx/model/package.py @@ -8,12 +8,12 @@ from license_expression import LicenseExpression -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx.model.actor import Actor -from spdx.model.checksum import Checksum -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model.actor import Actor +from spdx_tools.spdx.model.checksum import Checksum +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone class PackagePurpose(Enum): diff --git a/src/spdx/model/relationship.py b/src/spdx_tools/spdx/model/relationship.py similarity index 87% rename from src/spdx/model/relationship.py rename to src/spdx_tools/spdx/model/relationship.py index fdf0a8d7d..e8fe282c5 100644 --- a/src/spdx/model/relationship.py +++ b/src/spdx_tools/spdx/model/relationship.py @@ -4,10 +4,10 @@ from enum import Enum, auto from typing import Optional, Union -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone class RelationshipType(Enum): diff --git a/src/spdx/model/relationship_filters.py b/src/spdx_tools/spdx/model/relationship_filters.py similarity index 90% rename from src/spdx/model/relationship_filters.py rename to src/spdx_tools/spdx/model/relationship_filters.py index 3cc5dc5a6..073ee80fc 100644 --- a/src/spdx/model/relationship_filters.py +++ b/src/spdx_tools/spdx/model/relationship_filters.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List -from spdx.model.document import Document -from spdx.model.package import Package -from spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.package import Package +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType def find_package_contains_file_relationships(document: Document, package: Package) -> List[Relationship]: diff --git a/src/spdx/model/snippet.py b/src/spdx_tools/spdx/model/snippet.py similarity index 85% rename from src/spdx/model/snippet.py rename to src/spdx_tools/spdx/model/snippet.py index b88d9d835..d755cdff3 100644 --- a/src/spdx/model/snippet.py +++ b/src/spdx_tools/spdx/model/snippet.py @@ -6,10 +6,10 @@ from license_expression import LicenseExpression -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone @dataclass_with_properties diff --git a/src/spdx/model/spdx_no_assertion.py b/src/spdx_tools/spdx/model/spdx_no_assertion.py similarity index 100% rename from src/spdx/model/spdx_no_assertion.py rename to src/spdx_tools/spdx/model/spdx_no_assertion.py diff --git a/src/spdx/model/spdx_none.py b/src/spdx_tools/spdx/model/spdx_none.py similarity index 100% rename from src/spdx/model/spdx_none.py rename to src/spdx_tools/spdx/model/spdx_none.py diff --git a/src/spdx/model/version.py b/src/spdx_tools/spdx/model/version.py similarity index 100% rename from src/spdx/model/version.py rename to src/spdx_tools/spdx/model/version.py diff --git a/src/spdx/parser/__init__.py b/src/spdx_tools/spdx/parser/__init__.py similarity index 100% rename from src/spdx/parser/__init__.py rename to src/spdx_tools/spdx/parser/__init__.py diff --git a/src/spdx/parser/actor_parser.py b/src/spdx_tools/spdx/parser/actor_parser.py similarity index 91% rename from src/spdx/parser/actor_parser.py rename to src/spdx_tools/spdx/parser/actor_parser.py index 007a7c575..7a5240f0e 100644 --- a/src/spdx/parser/actor_parser.py +++ b/src/spdx_tools/spdx/parser/actor_parser.py @@ -4,9 +4,9 @@ import re from typing import Match, Optional, Pattern -from spdx.model.actor import Actor, ActorType -from spdx.parser.error import SPDXParsingError -from spdx.parser.parsing_functions import construct_or_raise_parsing_error +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.parsing_functions import construct_or_raise_parsing_error class ActorParser: diff --git a/src/spdx/parser/error.py b/src/spdx_tools/spdx/parser/error.py similarity index 100% rename from src/spdx/parser/error.py rename to src/spdx_tools/spdx/parser/error.py diff --git a/src/spdx/parser/json/__init__.py b/src/spdx_tools/spdx/parser/json/__init__.py similarity index 100% rename from src/spdx/parser/json/__init__.py rename to src/spdx_tools/spdx/parser/json/__init__.py diff --git a/src/spdx/parser/json/json_parser.py b/src/spdx_tools/spdx/parser/json/json_parser.py similarity index 69% rename from src/spdx/parser/json/json_parser.py rename to src/spdx_tools/spdx/parser/json/json_parser.py index 3d100afbb..3ef908ec9 100644 --- a/src/spdx/parser/json/json_parser.py +++ b/src/spdx_tools/spdx/parser/json/json_parser.py @@ -4,8 +4,8 @@ import json from typing import Dict -from spdx.model.document import Document -from spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser def parse_from_file(file_name: str) -> Document: diff --git a/src/spdx/parser/jsonlikedict/__init__.py b/src/spdx_tools/spdx/parser/jsonlikedict/__init__.py similarity index 100% rename from src/spdx/parser/jsonlikedict/__init__.py rename to src/spdx_tools/spdx/parser/jsonlikedict/__init__.py diff --git a/src/spdx/parser/jsonlikedict/annotation_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py similarity index 87% rename from src/spdx/parser/jsonlikedict/annotation_parser.py rename to src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py index 9d1d275ea..5d38aa616 100644 --- a/src/spdx/parser/jsonlikedict/annotation_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py @@ -4,14 +4,20 @@ from datetime import datetime from typing import Dict, List, Optional -from spdx.datetime_conversions import datetime_from_str -from spdx.model.actor import Actor -from spdx.model.annotation import Annotation, AnnotationType -from spdx.parser.actor_parser import ActorParser -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.dict_parsing_functions import append_parsed_field_or_log_error, parse_field_or_log_error -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model.actor import Actor +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( + append_parsed_field_or_log_error, + parse_field_or_log_error, +) +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) class AnnotationParser: diff --git a/src/spdx/parser/jsonlikedict/checksum_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py similarity index 71% rename from src/spdx/parser/jsonlikedict/checksum_parser.py rename to src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py index 3b61a2ee8..e9d0b3ad5 100644 --- a/src/spdx/parser/jsonlikedict/checksum_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py @@ -3,10 +3,13 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Dict, Optional -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.parser.jsonlikedict.dict_parsing_functions import json_str_to_enum_name -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import json_str_to_enum_name +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) class ChecksumParser: diff --git a/src/spdx/parser/jsonlikedict/creation_info_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py similarity index 86% rename from src/spdx/parser/jsonlikedict/creation_info_parser.py rename to src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py index 0f518e9f5..98af85e97 100644 --- a/src/spdx/parser/jsonlikedict/creation_info_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py @@ -4,22 +4,25 @@ from datetime import datetime from typing import Dict, List, Optional -from spdx.datetime_conversions import datetime_from_str -from spdx.model.actor import Actor -from spdx.model.checksum import Checksum -from spdx.model.document import CreationInfo -from spdx.model.external_document_ref import ExternalDocumentRef -from spdx.model.version import Version -from spdx.parser.actor_parser import ActorParser -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.checksum_parser import ChecksumParser -from spdx.parser.jsonlikedict.dict_parsing_functions import ( +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model.actor import Actor +from spdx_tools.spdx.model.checksum import Checksum +from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( append_parsed_field_or_log_error, parse_field_or_log_error, parse_field_or_no_assertion, ) -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) class CreationInfoParser: diff --git a/src/spdx/parser/jsonlikedict/dict_parsing_functions.py b/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py similarity index 88% rename from src/spdx/parser/jsonlikedict/dict_parsing_functions.py rename to src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py index be2c632fd..b8cbef483 100644 --- a/src/spdx/parser/jsonlikedict/dict_parsing_functions.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py @@ -3,11 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Callable, Dict, List, Optional -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.parser.error import SPDXParsingError -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import raise_parsing_error_if_logger_has_messages +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import raise_parsing_error_if_logger_has_messages def json_str_to_enum_name(json_str: str) -> str: diff --git a/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py similarity index 76% rename from src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py rename to src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py index 1ffd772a4..8b22f8443 100644 --- a/src/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py @@ -3,11 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Dict, List, Optional, Union -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_no_assertion -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_no_assertion +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import construct_or_raise_parsing_error class ExtractedLicensingInfoParser: diff --git a/src/spdx/parser/jsonlikedict/file_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py similarity index 83% rename from src/spdx/parser/jsonlikedict/file_parser.py rename to src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py index 3f4b565e1..94aa31b04 100644 --- a/src/spdx/parser/jsonlikedict/file_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py @@ -5,18 +5,21 @@ from license_expression import LicenseExpression -from spdx.model.checksum import Checksum -from spdx.model.file import File, FileType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.parser.jsonlikedict.checksum_parser import ChecksumParser -from spdx.parser.jsonlikedict.dict_parsing_functions import ( +from spdx_tools.spdx.model.checksum import Checksum +from spdx_tools.spdx.model.file import File, FileType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( parse_field_or_log_error, parse_field_or_no_assertion_or_none, ) -from spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx_tools.spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) class FileParser: diff --git a/src/spdx/parser/jsonlikedict/json_like_dict_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py similarity index 74% rename from src/spdx/parser/jsonlikedict/json_like_dict_parser.py rename to src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py index 65732de75..3f9b43a11 100644 --- a/src/spdx/parser/jsonlikedict/json_like_dict_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py @@ -3,18 +3,21 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Dict -from spdx.model.document import Document -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.annotation_parser import AnnotationParser -from spdx.parser.jsonlikedict.creation_info_parser import CreationInfoParser -from spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements -from spdx.parser.jsonlikedict.extracted_licensing_info_parser import ExtractedLicensingInfoParser -from spdx.parser.jsonlikedict.file_parser import FileParser -from spdx.parser.jsonlikedict.package_parser import PackageParser -from spdx.parser.jsonlikedict.relationship_parser import RelationshipParser -from spdx.parser.jsonlikedict.snippet_parser import SnippetParser -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.annotation_parser import AnnotationParser +from spdx_tools.spdx.parser.jsonlikedict.creation_info_parser import CreationInfoParser +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements +from spdx_tools.spdx.parser.jsonlikedict.extracted_licensing_info_parser import ExtractedLicensingInfoParser +from spdx_tools.spdx.parser.jsonlikedict.file_parser import FileParser +from spdx_tools.spdx.parser.jsonlikedict.package_parser import PackageParser +from spdx_tools.spdx.parser.jsonlikedict.relationship_parser import RelationshipParser +from spdx_tools.spdx.parser.jsonlikedict.snippet_parser import SnippetParser +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) class JsonLikeDictParser: diff --git a/src/spdx/parser/jsonlikedict/license_expression_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py similarity index 83% rename from src/spdx/parser/jsonlikedict/license_expression_parser.py rename to src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py index 70cac7aec..08b17f9da 100644 --- a/src/spdx/parser/jsonlikedict/license_expression_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py @@ -5,9 +5,9 @@ from license_expression import ExpressionError, LicenseExpression, Licensing -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError class LicenseExpressionParser: diff --git a/src/spdx/parser/jsonlikedict/package_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py similarity index 91% rename from src/spdx/parser/jsonlikedict/package_parser.py rename to src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py index 090a7ad7e..55b6e064d 100644 --- a/src/spdx/parser/jsonlikedict/package_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py @@ -6,30 +6,33 @@ from license_expression import LicenseExpression -from spdx.datetime_conversions import datetime_from_str -from spdx.model.actor import Actor -from spdx.model.package import ( +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model.actor import Actor +from spdx_tools.spdx.model.package import ( ExternalPackageRef, ExternalPackageRefCategory, Package, PackagePurpose, PackageVerificationCode, ) -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.parser.actor_parser import ActorParser -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.checksum_parser import ChecksumParser -from spdx.parser.jsonlikedict.dict_parsing_functions import ( +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( append_parsed_field_or_log_error, json_str_to_enum_name, parse_field_or_log_error, parse_field_or_no_assertion, parse_field_or_no_assertion_or_none, ) -from spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx_tools.spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) class PackageParser: diff --git a/src/spdx/parser/jsonlikedict/relationship_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py similarity index 94% rename from src/spdx/parser/jsonlikedict/relationship_parser.py rename to src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py index 3471fb51d..e541070b2 100644 --- a/src/spdx/parser/jsonlikedict/relationship_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py @@ -3,17 +3,20 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Dict, List, Optional -from common.typing.constructor_type_errors import ConstructorTypeErrors -from spdx.model.relationship import Relationship, RelationshipType -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.dict_parsing_functions import ( +from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( delete_duplicates_from_list, json_str_to_enum_name, parse_field_or_log_error, parse_field_or_no_assertion_or_none, ) -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) class RelationshipParser: diff --git a/src/spdx/parser/jsonlikedict/snippet_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py similarity index 91% rename from src/spdx/parser/jsonlikedict/snippet_parser.py rename to src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py index c4f525015..55745884f 100644 --- a/src/spdx/parser/jsonlikedict/snippet_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py @@ -6,17 +6,17 @@ from license_expression import LicenseExpression -from spdx.model.snippet import Snippet -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.dict_parsing_functions import ( +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( parse_field_or_log_error, parse_field_or_no_assertion_or_none, ) -from spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error +from spdx_tools.spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import construct_or_raise_parsing_error class RangeType(Enum): diff --git a/src/spdx/parser/logger.py b/src/spdx_tools/spdx/parser/logger.py similarity index 100% rename from src/spdx/parser/logger.py rename to src/spdx_tools/spdx/parser/logger.py diff --git a/src/spdx/parser/parse_anything.py b/src/spdx_tools/spdx/parser/parse_anything.py similarity index 77% rename from src/spdx/parser/parse_anything.py rename to src/spdx_tools/spdx/parser/parse_anything.py index 51a730ae5..b54bb7694 100644 --- a/src/spdx/parser/parse_anything.py +++ b/src/spdx_tools/spdx/parser/parse_anything.py @@ -8,12 +8,12 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from spdx.formats import FileFormat, file_name_to_format -from spdx.parser.json import json_parser -from spdx.parser.rdf import rdf_parser -from spdx.parser.tagvalue import tagvalue_parser -from spdx.parser.xml import xml_parser -from spdx.parser.yaml import yaml_parser +from spdx_tools.spdx.formats import FileFormat, file_name_to_format +from spdx_tools.spdx.parser.json import json_parser +from spdx_tools.spdx.parser.rdf import rdf_parser +from spdx_tools.spdx.parser.tagvalue import tagvalue_parser +from spdx_tools.spdx.parser.xml import xml_parser +from spdx_tools.spdx.parser.yaml import yaml_parser def parse_file(file_name: str): diff --git a/src/spdx/parser/parsing_functions.py b/src/spdx_tools/spdx/parser/parsing_functions.py similarity index 83% rename from src/spdx/parser/parsing_functions.py rename to src/spdx_tools/spdx/parser/parsing_functions.py index 594bf3871..f0e371d91 100644 --- a/src/spdx/parser/parsing_functions.py +++ b/src/spdx_tools/spdx/parser/parsing_functions.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Dict -from common.typing.constructor_type_errors import ConstructorTypeErrors -from spdx.parser.error import SPDXParsingError -from spdx.parser.logger import Logger +from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger def construct_or_raise_parsing_error(object_to_construct: Any, args_for_construction: Dict) -> Any: diff --git a/src/spdx/parser/rdf/__init__.py b/src/spdx_tools/spdx/parser/rdf/__init__.py similarity index 100% rename from src/spdx/parser/rdf/__init__.py rename to src/spdx_tools/spdx/parser/rdf/__init__.py diff --git a/src/spdx/parser/rdf/annotation_parser.py b/src/spdx_tools/spdx/parser/rdf/annotation_parser.py similarity index 70% rename from src/spdx/parser/rdf/annotation_parser.py rename to src/spdx_tools/spdx/parser/rdf/annotation_parser.py index 26544de3f..1a8e2746c 100644 --- a/src/spdx/parser/rdf/annotation_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/annotation_parser.py @@ -3,13 +3,16 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, BNode, Graph, URIRef -from spdx.datetime_conversions import datetime_from_str -from spdx.model.annotation import Annotation, AnnotationType -from spdx.parser.actor_parser import ActorParser -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.rdf.graph_parsing_functions import parse_enum_value, parse_literal, parse_spdx_id -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import parse_enum_value, parse_literal, parse_spdx_id +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def parse_annotation(annotation_node: BNode, graph: Graph, parent_node: URIRef, doc_namespace: str) -> Annotation: diff --git a/src/spdx/parser/rdf/checksum_parser.py b/src/spdx_tools/spdx/parser/rdf/checksum_parser.py similarity index 68% rename from src/spdx/parser/rdf/checksum_parser.py rename to src/spdx_tools/spdx/parser/rdf/checksum_parser.py index d2bad6e7d..633b2ad65 100644 --- a/src/spdx/parser/rdf/checksum_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/checksum_parser.py @@ -3,12 +3,15 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import BNode, Graph -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.parser.error import SPDXParsingError -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.rdf.graph_parsing_functions import parse_literal, remove_prefix -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import parse_literal, remove_prefix +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def parse_checksum(parent_node: BNode, graph: Graph) -> Checksum: diff --git a/src/spdx/parser/rdf/creation_info_parser.py b/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py similarity index 85% rename from src/spdx/parser/rdf/creation_info_parser.py rename to src/spdx_tools/spdx/parser/rdf/creation_info_parser.py index 5254d3a10..ca83a122c 100644 --- a/src/spdx/parser/rdf/creation_info_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py @@ -10,23 +10,26 @@ from rdflib.exceptions import UniquenessError from rdflib.term import URIRef -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.datetime_conversions import datetime_from_str -from spdx.model.document import CreationInfo -from spdx.model.external_document_ref import ExternalDocumentRef -from spdx.model.version import Version -from spdx.parser.actor_parser import ActorParser -from spdx.parser.error import SPDXParsingError -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.rdf.checksum_parser import parse_checksum -from spdx.parser.rdf.graph_parsing_functions import ( +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.checksum_parser import parse_checksum +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import ( get_correctly_typed_triples, parse_literal, parse_spdx_id, remove_prefix, ) -from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE def parse_creation_info(graph: Graph) -> Tuple[CreationInfo, URIRef]: diff --git a/src/spdx/parser/rdf/extracted_licensing_info_parser.py b/src/spdx_tools/spdx/parser/rdf/extracted_licensing_info_parser.py similarity index 81% rename from src/spdx/parser/rdf/extracted_licensing_info_parser.py rename to src/spdx_tools/spdx/parser/rdf/extracted_licensing_info_parser.py index eae155cc4..b61b83d48 100644 --- a/src/spdx/parser/rdf/extracted_licensing_info_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/extracted_licensing_info_parser.py @@ -3,15 +3,18 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.rdf.graph_parsing_functions import ( +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import ( get_correctly_typed_triples, parse_literal, parse_literal_or_no_assertion_or_none, ) -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def parse_extracted_licensing_info( diff --git a/src/spdx/parser/rdf/file_parser.py b/src/spdx_tools/spdx/parser/rdf/file_parser.py similarity index 85% rename from src/spdx/parser/rdf/file_parser.py rename to src/spdx_tools/spdx/parser/rdf/file_parser.py index 649d29879..69067ed24 100644 --- a/src/spdx/parser/rdf/file_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/file_parser.py @@ -3,11 +3,14 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef -from spdx.model.file import File, FileType -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.rdf.checksum_parser import parse_checksum -from spdx.parser.rdf.graph_parsing_functions import ( +from spdx_tools.spdx.model.file import File, FileType +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.checksum_parser import parse_checksum +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import ( apply_parsing_method_or_log_error, get_correctly_typed_triples, get_correctly_typed_value, @@ -16,8 +19,8 @@ parse_literal_or_no_assertion_or_none, parse_spdx_id, ) -from spdx.parser.rdf.license_expression_parser import parse_license_expression -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.parser.rdf.license_expression_parser import parse_license_expression +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def parse_file(file_node: URIRef, graph: Graph, doc_namespace: str) -> File: diff --git a/src/spdx/parser/rdf/graph_parsing_functions.py b/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py similarity index 92% rename from src/spdx/parser/rdf/graph_parsing_functions.py rename to src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py index 15a0ff8cf..12d78e680 100644 --- a/src/spdx/parser/rdf/graph_parsing_functions.py +++ b/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py @@ -9,12 +9,12 @@ from rdflib.namespace import NamespaceManager from rdflib.term import BNode, Literal, Node -from spdx.casing_tools import camel_case_to_snake_case -from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion -from spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone -from spdx.parser.error import SPDXParsingError -from spdx.parser.logger import Logger -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.casing_tools import camel_case_to_snake_case +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def parse_literal( diff --git a/src/spdx/parser/rdf/license_expression_parser.py b/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py similarity index 91% rename from src/spdx/parser/rdf/license_expression_parser.py rename to src/spdx_tools/spdx/parser/rdf/license_expression_parser.py index b6ccc3bd8..a55096976 100644 --- a/src/spdx/parser/rdf/license_expression_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py @@ -7,9 +7,9 @@ from rdflib import RDF, Graph from rdflib.term import BNode, Identifier, Node, URIRef -from spdx.parser.logger import Logger -from spdx.parser.rdf.graph_parsing_functions import get_value_from_graph, remove_prefix -from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import get_value_from_graph, remove_prefix +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE def parse_license_expression( diff --git a/src/spdx/parser/rdf/package_parser.py b/src/spdx_tools/spdx/parser/rdf/package_parser.py similarity index 92% rename from src/spdx/parser/rdf/package_parser.py rename to src/spdx_tools/spdx/parser/rdf/package_parser.py index e4ba4b02b..61d94a667 100644 --- a/src/spdx/parser/rdf/package_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/package_parser.py @@ -6,19 +6,22 @@ from rdflib import DOAP, RDFS, Graph, URIRef from rdflib.term import BNode -from spdx.datetime_conversions import datetime_from_str -from spdx.model.package import ( +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model.package import ( ExternalPackageRef, ExternalPackageRefCategory, Package, PackagePurpose, PackageVerificationCode, ) -from spdx.parser.actor_parser import ActorParser -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.rdf.checksum_parser import parse_checksum -from spdx.parser.rdf.graph_parsing_functions import ( +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.checksum_parser import parse_checksum +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import ( get_correctly_typed_triples, get_correctly_typed_value, get_value_from_graph, @@ -27,8 +30,8 @@ parse_literal_or_no_assertion_or_none, parse_spdx_id, ) -from spdx.parser.rdf.license_expression_parser import parse_license_expression -from spdx.rdfschema.namespace import REFERENCE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.parser.rdf.license_expression_parser import parse_license_expression +from spdx_tools.spdx.rdfschema.namespace import REFERENCE_NAMESPACE, SPDX_NAMESPACE def parse_package(package_node: URIRef, graph: Graph, doc_namespace: str) -> Package: diff --git a/src/spdx/parser/rdf/rdf_parser.py b/src/spdx_tools/spdx/parser/rdf/rdf_parser.py similarity index 75% rename from src/spdx/parser/rdf/rdf_parser.py rename to src/spdx_tools/spdx/parser/rdf/rdf_parser.py index e05de8b64..42d7c7ecc 100644 --- a/src/spdx/parser/rdf/rdf_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/rdf_parser.py @@ -5,20 +5,23 @@ from rdflib import RDF, Graph -from spdx.model.document import Document -from spdx.model.relationship import RelationshipType -from spdx.parser.error import SPDXParsingError -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.rdf.annotation_parser import parse_annotation -from spdx.parser.rdf.creation_info_parser import parse_creation_info -from spdx.parser.rdf.extracted_licensing_info_parser import parse_extracted_licensing_info -from spdx.parser.rdf.file_parser import parse_file -from spdx.parser.rdf.graph_parsing_functions import get_correctly_typed_triples -from spdx.parser.rdf.package_parser import parse_package -from spdx.parser.rdf.relationship_parser import parse_implicit_relationship, parse_relationship -from spdx.parser.rdf.snippet_parser import parse_snippet -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.relationship import RelationshipType +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.annotation_parser import parse_annotation +from spdx_tools.spdx.parser.rdf.creation_info_parser import parse_creation_info +from spdx_tools.spdx.parser.rdf.extracted_licensing_info_parser import parse_extracted_licensing_info +from spdx_tools.spdx.parser.rdf.file_parser import parse_file +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import get_correctly_typed_triples +from spdx_tools.spdx.parser.rdf.package_parser import parse_package +from spdx_tools.spdx.parser.rdf.relationship_parser import parse_implicit_relationship, parse_relationship +from spdx_tools.spdx.parser.rdf.snippet_parser import parse_snippet +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def parse_from_file(file_name: str) -> Document: diff --git a/src/spdx/parser/rdf/relationship_parser.py b/src/spdx_tools/spdx/parser/rdf/relationship_parser.py similarity index 84% rename from src/spdx/parser/rdf/relationship_parser.py rename to src/spdx_tools/spdx/parser/rdf/relationship_parser.py index d08ddf54d..c043cb8ca 100644 --- a/src/spdx/parser/rdf/relationship_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/relationship_parser.py @@ -4,16 +4,19 @@ from rdflib import RDFS, Graph, URIRef from rdflib.term import Node -from spdx.model.relationship import Relationship, RelationshipType -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.rdf.graph_parsing_functions import ( +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import ( parse_enum_value, parse_literal, parse_literal_or_no_assertion_or_none, parse_spdx_id, ) -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def parse_relationship(relationship_node: Node, graph: Graph, parent_node: URIRef, doc_namespace: str) -> Relationship: diff --git a/src/spdx/parser/rdf/snippet_parser.py b/src/spdx_tools/spdx/parser/rdf/snippet_parser.py similarity index 91% rename from src/spdx/parser/rdf/snippet_parser.py rename to src/spdx_tools/spdx/parser/rdf/snippet_parser.py index 23f746be5..073d7d9c8 100644 --- a/src/spdx/parser/rdf/snippet_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/snippet_parser.py @@ -7,11 +7,14 @@ from rdflib.exceptions import UniquenessError from rdflib.term import BNode, Node, URIRef -from spdx.model.snippet import Snippet -from spdx.parser.error import SPDXParsingError -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.rdf.graph_parsing_functions import ( +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import ( apply_parsing_method_or_log_error, get_correctly_typed_triples, get_correctly_typed_value, @@ -20,8 +23,8 @@ parse_literal_or_no_assertion_or_none, parse_spdx_id, ) -from spdx.parser.rdf.license_expression_parser import parse_license_expression -from spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.parser.rdf.license_expression_parser import parse_license_expression +from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE def parse_snippet(snippet_node: URIRef, graph: Graph, doc_namespace: str) -> Snippet: diff --git a/src/spdx/parser/tagvalue/__init__.py b/src/spdx_tools/spdx/parser/tagvalue/__init__.py similarity index 100% rename from src/spdx/parser/tagvalue/__init__.py rename to src/spdx_tools/spdx/parser/tagvalue/__init__.py diff --git a/src/spdx/parser/tagvalue/helper_methods.py b/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py similarity index 90% rename from src/spdx/parser/tagvalue/helper_methods.py rename to src/spdx_tools/spdx/parser/tagvalue/helper_methods.py index d5faef6b1..484067841 100644 --- a/src/spdx/parser/tagvalue/helper_methods.py +++ b/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py @@ -6,15 +6,15 @@ from ply.yacc import YaccProduction -from spdx.casing_tools import camel_case_to_snake_case -from spdx.model.annotation import Annotation -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.document import CreationInfo -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.model.file import File -from spdx.model.package import Package -from spdx.model.snippet import Snippet -from spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.casing_tools import camel_case_to_snake_case +from spdx_tools.spdx.model.annotation import Annotation +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.model.package import Package +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.parser.error import SPDXParsingError def grammar_rule(doc): diff --git a/src/spdx/parser/tagvalue/lexer.py b/src/spdx_tools/spdx/parser/tagvalue/lexer.py similarity index 100% rename from src/spdx/parser/tagvalue/lexer.py rename to src/spdx_tools/spdx/parser/tagvalue/lexer.py diff --git a/src/spdx/parser/tagvalue/parser.py b/src/spdx_tools/spdx/parser/tagvalue/parser.py similarity index 95% rename from src/spdx/parser/tagvalue/parser.py rename to src/spdx_tools/spdx/parser/tagvalue/parser.py index e52e6c9bf..e4376fbe0 100644 --- a/src/spdx/parser/tagvalue/parser.py +++ b/src/spdx_tools/spdx/parser/tagvalue/parser.py @@ -18,36 +18,39 @@ from ply import yacc from ply.yacc import LRParser -from spdx.datetime_conversions import datetime_from_str -from spdx.model.annotation import Annotation, AnnotationType -from spdx.model.document import CreationInfo, Document -from spdx.model.external_document_ref import ExternalDocumentRef -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.model.file import File, FileType -from spdx.model.package import ( +from spdx_tools.spdx.datetime_conversions import datetime_from_str +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model.document import CreationInfo, Document +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model.file import File, FileType +from spdx_tools.spdx.model.package import ( ExternalPackageRef, ExternalPackageRefCategory, Package, PackagePurpose, PackageVerificationCode, ) -from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.snippet import Snippet -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.model.version import Version -from spdx.parser.actor_parser import ActorParser -from spdx.parser.error import SPDXParsingError -from spdx.parser.logger import Logger -from spdx.parser.parsing_functions import construct_or_raise_parsing_error, raise_parsing_error_if_logger_has_messages -from spdx.parser.tagvalue.helper_methods import ( +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.logger import Logger +from spdx_tools.spdx.parser.parsing_functions import ( + construct_or_raise_parsing_error, + raise_parsing_error_if_logger_has_messages, +) +from spdx_tools.spdx.parser.tagvalue.helper_methods import ( TAG_DATA_MODEL_FIELD, grammar_rule, parse_checksum, set_value, str_from_text, ) -from spdx.parser.tagvalue.lexer import SPDXLexer +from spdx_tools.spdx.parser.tagvalue.lexer import SPDXLexer CLASS_MAPPING = dict( File="files", diff --git a/src/spdx/parser/tagvalue/tagvalue_parser.py b/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py similarity index 72% rename from src/spdx/parser/tagvalue/tagvalue_parser.py rename to src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py index 6fb54a28c..a617cac96 100644 --- a/src/spdx/parser/tagvalue/tagvalue_parser.py +++ b/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py @@ -1,8 +1,8 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from spdx.model.document import Document -from spdx.parser.tagvalue.parser import Parser +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.parser.tagvalue.parser import Parser def parse_from_file(file_name: str) -> Document: diff --git a/src/spdx/parser/xml/__init__.py b/src/spdx_tools/spdx/parser/xml/__init__.py similarity index 100% rename from src/spdx/parser/xml/__init__.py rename to src/spdx_tools/spdx/parser/xml/__init__.py diff --git a/src/spdx/parser/xml/xml_parser.py b/src/spdx_tools/spdx/parser/xml/xml_parser.py similarity index 90% rename from src/spdx/parser/xml/xml_parser.py rename to src/spdx_tools/spdx/parser/xml/xml_parser.py index 4d0fa14a8..bef87d86b 100644 --- a/src/spdx/parser/xml/xml_parser.py +++ b/src/spdx_tools/spdx/parser/xml/xml_parser.py @@ -5,9 +5,9 @@ import xmltodict -from spdx.model.document import Document -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser LIST_LIKE_FIELDS = [ "creators", diff --git a/src/spdx/parser/yaml/__init__.py b/src/spdx_tools/spdx/parser/yaml/__init__.py similarity index 100% rename from src/spdx/parser/yaml/__init__.py rename to src/spdx_tools/spdx/parser/yaml/__init__.py diff --git a/src/spdx/parser/yaml/yaml_parser.py b/src/spdx_tools/spdx/parser/yaml/yaml_parser.py similarity index 69% rename from src/spdx/parser/yaml/yaml_parser.py rename to src/spdx_tools/spdx/parser/yaml/yaml_parser.py index 7e413b66d..86bcd6e49 100644 --- a/src/spdx/parser/yaml/yaml_parser.py +++ b/src/spdx_tools/spdx/parser/yaml/yaml_parser.py @@ -5,8 +5,8 @@ import yaml -from spdx.model.document import Document -from spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser def parse_from_file(file_name: str) -> Document: diff --git a/src/spdx/py.typed b/src/spdx_tools/spdx/py.typed similarity index 100% rename from src/spdx/py.typed rename to src/spdx_tools/spdx/py.typed diff --git a/src/spdx/rdfschema/__init__.py b/src/spdx_tools/spdx/rdfschema/__init__.py similarity index 100% rename from src/spdx/rdfschema/__init__.py rename to src/spdx_tools/spdx/rdfschema/__init__.py diff --git a/src/spdx/rdfschema/namespace.py b/src/spdx_tools/spdx/rdfschema/namespace.py similarity index 100% rename from src/spdx/rdfschema/namespace.py rename to src/spdx_tools/spdx/rdfschema/namespace.py diff --git a/src/spdx/validation/__init__.py b/src/spdx_tools/spdx/validation/__init__.py similarity index 100% rename from src/spdx/validation/__init__.py rename to src/spdx_tools/spdx/validation/__init__.py diff --git a/src/spdx/validation/actor_validator.py b/src/spdx_tools/spdx/validation/actor_validator.py similarity index 83% rename from src/spdx/validation/actor_validator.py rename to src/spdx_tools/spdx/validation/actor_validator.py index d65472d82..c15b99e02 100644 --- a/src/spdx/validation/actor_validator.py +++ b/src/spdx_tools/spdx/validation/actor_validator.py @@ -4,8 +4,8 @@ from typing import List -from spdx.model.actor import Actor, ActorType -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_actors(actors: List[Actor], parent_id: str) -> List[ValidationMessage]: diff --git a/src/spdx/validation/annotation_validator.py b/src/spdx_tools/spdx/validation/annotation_validator.py similarity index 71% rename from src/spdx/validation/annotation_validator.py rename to src/spdx_tools/spdx/validation/annotation_validator.py index 92f470953..309f7c9fa 100644 --- a/src/spdx/validation/annotation_validator.py +++ b/src/spdx_tools/spdx/validation/annotation_validator.py @@ -4,11 +4,11 @@ from typing import List -from spdx.model.annotation import Annotation -from spdx.model.document import Document -from spdx.validation.actor_validator import validate_actor -from spdx.validation.spdx_id_validators import validate_spdx_id -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.annotation import Annotation +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.validation.actor_validator import validate_actor +from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_annotations(annotations: List[Annotation], document: Document) -> List[ValidationMessage]: diff --git a/src/spdx/validation/checksum_validator.py b/src/spdx_tools/spdx/validation/checksum_validator.py similarity index 93% rename from src/spdx/validation/checksum_validator.py rename to src/spdx_tools/spdx/validation/checksum_validator.py index 17b562587..53f40e473 100644 --- a/src/spdx/validation/checksum_validator.py +++ b/src/spdx_tools/spdx/validation/checksum_validator.py @@ -5,8 +5,8 @@ import re from typing import Dict, List -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage # in hexadecimal digits algorithm_length: Dict = { diff --git a/src/spdx/validation/creation_info_validator.py b/src/spdx_tools/spdx/validation/creation_info_validator.py similarity index 72% rename from src/spdx/validation/creation_info_validator.py rename to src/spdx_tools/spdx/validation/creation_info_validator.py index 9cb4e1259..32de32673 100644 --- a/src/spdx/validation/creation_info_validator.py +++ b/src/spdx_tools/spdx/validation/creation_info_validator.py @@ -4,12 +4,12 @@ from typing import List -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.document import CreationInfo -from spdx.validation.actor_validator import validate_actors -from spdx.validation.external_document_ref_validator import validate_external_document_refs -from spdx.validation.uri_validators import validate_uri -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.validation.actor_validator import validate_actors +from spdx_tools.spdx.validation.external_document_ref_validator import validate_external_document_refs +from spdx_tools.spdx.validation.uri_validators import validate_uri +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_creation_info(creation_info: CreationInfo, spdx_version: str) -> List[ValidationMessage]: diff --git a/src/spdx/validation/document_validator.py b/src/spdx_tools/spdx/validation/document_validator.py similarity index 79% rename from src/spdx/validation/document_validator.py rename to src/spdx_tools/spdx/validation/document_validator.py index a749f43ab..b368ff576 100644 --- a/src/spdx/validation/document_validator.py +++ b/src/spdx_tools/spdx/validation/document_validator.py @@ -3,18 +3,18 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List -from spdx.model.document import Document -from spdx.model.relationship import RelationshipType -from spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target -from spdx.validation.annotation_validator import validate_annotations -from spdx.validation.creation_info_validator import validate_creation_info -from spdx.validation.extracted_licensing_info_validator import validate_extracted_licensing_infos -from spdx.validation.file_validator import validate_files -from spdx.validation.package_validator import validate_packages -from spdx.validation.relationship_validator import validate_relationships -from spdx.validation.snippet_validator import validate_snippets -from spdx.validation.spdx_id_validators import get_list_of_all_spdx_ids -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.relationship import RelationshipType +from spdx_tools.spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target +from spdx_tools.spdx.validation.annotation_validator import validate_annotations +from spdx_tools.spdx.validation.creation_info_validator import validate_creation_info +from spdx_tools.spdx.validation.extracted_licensing_info_validator import validate_extracted_licensing_infos +from spdx_tools.spdx.validation.file_validator import validate_files +from spdx_tools.spdx.validation.package_validator import validate_packages +from spdx_tools.spdx.validation.relationship_validator import validate_relationships +from spdx_tools.spdx.validation.snippet_validator import validate_snippets +from spdx_tools.spdx.validation.spdx_id_validators import get_list_of_all_spdx_ids +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_full_spdx_document(document: Document, spdx_version: str = None) -> List[ValidationMessage]: diff --git a/src/spdx/validation/external_document_ref_validator.py b/src/spdx_tools/spdx/validation/external_document_ref_validator.py similarity index 78% rename from src/spdx/validation/external_document_ref_validator.py rename to src/spdx_tools/spdx/validation/external_document_ref_validator.py index 1f5746398..2bbf95566 100644 --- a/src/spdx/validation/external_document_ref_validator.py +++ b/src/spdx_tools/spdx/validation/external_document_ref_validator.py @@ -4,11 +4,11 @@ from typing import List -from spdx.model.external_document_ref import ExternalDocumentRef -from spdx.validation.checksum_validator import validate_checksum -from spdx.validation.spdx_id_validators import is_valid_external_doc_ref_id -from spdx.validation.uri_validators import validate_uri -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.validation.checksum_validator import validate_checksum +from spdx_tools.spdx.validation.spdx_id_validators import is_valid_external_doc_ref_id +from spdx_tools.spdx.validation.uri_validators import validate_uri +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_external_document_refs( diff --git a/src/spdx/validation/external_package_ref_validator.py b/src/spdx_tools/spdx/validation/external_package_ref_validator.py similarity index 93% rename from src/spdx/validation/external_package_ref_validator.py rename to src/spdx_tools/spdx/validation/external_package_ref_validator.py index 5d3a732c5..c37187f4b 100644 --- a/src/spdx/validation/external_package_ref_validator.py +++ b/src/spdx_tools/spdx/validation/external_package_ref_validator.py @@ -6,9 +6,13 @@ import uritools -from spdx.model.package import CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES, ExternalPackageRef, ExternalPackageRefCategory -from spdx.validation.uri_validators import validate_url -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.package import ( + CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES, + ExternalPackageRef, + ExternalPackageRefCategory, +) +from spdx_tools.spdx.validation.uri_validators import validate_url +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage CPE22TYPE_REGEX = r"^c[pP][eE]:/[AHOaho]?(:[A-Za-z0-9._\-~%]*){0,6}$" CPE23TYPE_REGEX = ( diff --git a/src/spdx/validation/extracted_licensing_info_validator.py b/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py similarity index 86% rename from src/spdx/validation/extracted_licensing_info_validator.py rename to src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py index 11aee1bab..7779c2d80 100644 --- a/src/spdx/validation/extracted_licensing_info_validator.py +++ b/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py @@ -5,9 +5,9 @@ import re from typing import List, Optional -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.validation.uri_validators import validate_url -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.validation.uri_validators import validate_url +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_extracted_licensing_infos( diff --git a/src/spdx/validation/file_validator.py b/src/spdx_tools/spdx/validation/file_validator.py similarity index 83% rename from src/spdx/validation/file_validator.py rename to src/spdx_tools/spdx/validation/file_validator.py index 45711050c..e461c14b0 100644 --- a/src/spdx/validation/file_validator.py +++ b/src/spdx_tools/spdx/validation/file_validator.py @@ -4,13 +4,16 @@ from typing import List, Optional -from spdx.model.checksum import ChecksumAlgorithm -from spdx.model.document import Document -from spdx.model.file import File -from spdx.validation.checksum_validator import validate_checksums -from spdx.validation.license_expression_validator import validate_license_expression, validate_license_expressions -from spdx.validation.spdx_id_validators import validate_spdx_id -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.validation.checksum_validator import validate_checksums +from spdx_tools.spdx.validation.license_expression_validator import ( + validate_license_expression, + validate_license_expressions, +) +from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_files( diff --git a/src/spdx/validation/license_expression_validator.py b/src/spdx_tools/spdx/validation/license_expression_validator.py similarity index 90% rename from src/spdx/validation/license_expression_validator.py rename to src/spdx_tools/spdx/validation/license_expression_validator.py index f29f59441..72dabe548 100644 --- a/src/spdx/validation/license_expression_validator.py +++ b/src/spdx_tools/spdx/validation/license_expression_validator.py @@ -6,10 +6,10 @@ from license_expression import ExpressionError, ExpressionParseError, LicenseExpression, get_spdx_licensing -from spdx.model.document import Document -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_license_expressions( diff --git a/src/spdx/validation/package_validator.py b/src/spdx_tools/spdx/validation/package_validator.py similarity index 85% rename from src/spdx/validation/package_validator.py rename to src/spdx_tools/spdx/validation/package_validator.py index d52be0884..51d887963 100644 --- a/src/spdx/validation/package_validator.py +++ b/src/spdx_tools/spdx/validation/package_validator.py @@ -4,17 +4,20 @@ from typing import List, Optional -from spdx.model.document import Document -from spdx.model.package import Package -from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target -from spdx.validation.checksum_validator import validate_checksums -from spdx.validation.external_package_ref_validator import validate_external_package_refs -from spdx.validation.license_expression_validator import validate_license_expression, validate_license_expressions -from spdx.validation.package_verification_code_validator import validate_verification_code -from spdx.validation.spdx_id_validators import validate_spdx_id -from spdx.validation.uri_validators import validate_download_location, validate_url -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.package import Package +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target +from spdx_tools.spdx.validation.checksum_validator import validate_checksums +from spdx_tools.spdx.validation.external_package_ref_validator import validate_external_package_refs +from spdx_tools.spdx.validation.license_expression_validator import ( + validate_license_expression, + validate_license_expressions, +) +from spdx_tools.spdx.validation.package_verification_code_validator import validate_verification_code +from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id +from spdx_tools.spdx.validation.uri_validators import validate_download_location, validate_url +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_packages( diff --git a/src/spdx/validation/package_verification_code_validator.py b/src/spdx_tools/spdx/validation/package_verification_code_validator.py similarity index 86% rename from src/spdx/validation/package_verification_code_validator.py rename to src/spdx_tools/spdx/validation/package_verification_code_validator.py index 1c910d8bb..db1a0edf2 100644 --- a/src/spdx/validation/package_verification_code_validator.py +++ b/src/spdx_tools/spdx/validation/package_verification_code_validator.py @@ -5,8 +5,8 @@ import re from typing import List -from spdx.model.package import PackageVerificationCode -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.package import PackageVerificationCode +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_verification_code(verification_code: PackageVerificationCode, parent_id: str) -> List[ValidationMessage]: diff --git a/src/spdx/validation/relationship_validator.py b/src/spdx_tools/spdx/validation/relationship_validator.py similarity index 79% rename from src/spdx/validation/relationship_validator.py rename to src/spdx_tools/spdx/validation/relationship_validator.py index 45e7845a9..84e97f6d1 100644 --- a/src/spdx/validation/relationship_validator.py +++ b/src/spdx_tools/spdx/validation/relationship_validator.py @@ -4,12 +4,12 @@ from typing import List -from spdx.model.document import Document -from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.validation.spdx_id_validators import validate_spdx_id -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_relationships( diff --git a/src/spdx/validation/snippet_validator.py b/src/spdx_tools/spdx/validation/snippet_validator.py similarity index 89% rename from src/spdx/validation/snippet_validator.py rename to src/spdx_tools/spdx/validation/snippet_validator.py index 1248e6cc2..db696e45e 100644 --- a/src/spdx/validation/snippet_validator.py +++ b/src/spdx_tools/spdx/validation/snippet_validator.py @@ -4,11 +4,14 @@ from typing import List, Optional -from spdx.model.document import Document -from spdx.model.snippet import Snippet -from spdx.validation.license_expression_validator import validate_license_expression, validate_license_expressions -from spdx.validation.spdx_id_validators import validate_spdx_id -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.validation.license_expression_validator import ( + validate_license_expression, + validate_license_expressions, +) +from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def validate_snippets( diff --git a/src/spdx/validation/spdx_id_validators.py b/src/spdx_tools/spdx/validation/spdx_id_validators.py similarity index 95% rename from src/spdx/validation/spdx_id_validators.py rename to src/spdx_tools/spdx/validation/spdx_id_validators.py index c8f031e1a..86952a4fc 100644 --- a/src/spdx/validation/spdx_id_validators.py +++ b/src/spdx_tools/spdx/validation/spdx_id_validators.py @@ -5,9 +5,9 @@ import re from typing import List -from spdx.document_utils import get_contained_spdx_element_ids -from spdx.model.document import Document -from spdx.model.file import File +from spdx_tools.spdx.document_utils import get_contained_spdx_element_ids +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.file import File def is_valid_internal_spdx_id(spdx_id: str) -> bool: diff --git a/src/spdx/validation/uri_validators.py b/src/spdx_tools/spdx/validation/uri_validators.py similarity index 100% rename from src/spdx/validation/uri_validators.py rename to src/spdx_tools/spdx/validation/uri_validators.py diff --git a/src/spdx/validation/validation_message.py b/src/spdx_tools/spdx/validation/validation_message.py similarity index 100% rename from src/spdx/validation/validation_message.py rename to src/spdx_tools/spdx/validation/validation_message.py diff --git a/src/spdx/writer/__init__.py b/src/spdx_tools/spdx/writer/__init__.py similarity index 100% rename from src/spdx/writer/__init__.py rename to src/spdx_tools/spdx/writer/__init__.py diff --git a/src/spdx/writer/json/__init__.py b/src/spdx_tools/spdx/writer/json/__init__.py similarity index 100% rename from src/spdx/writer/json/__init__.py rename to src/spdx_tools/spdx/writer/json/__init__.py diff --git a/src/spdx/writer/json/json_writer.py b/src/spdx_tools/spdx/writer/json/json_writer.py similarity index 75% rename from src/spdx/writer/json/json_writer.py rename to src/spdx_tools/spdx/writer/json/json_writer.py index 88880d37c..58c4acbee 100644 --- a/src/spdx/writer/json/json_writer.py +++ b/src/spdx_tools/spdx/writer/json/json_writer.py @@ -4,11 +4,11 @@ import json from typing import List -from spdx.document_utils import create_document_without_duplicates -from spdx.jsonschema.document_converter import DocumentConverter -from spdx.model.document import Document -from spdx.validation.document_validator import validate_full_spdx_document -from spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.document_utils import create_document_without_duplicates +from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage def write_document_to_file( diff --git a/src/spdx/writer/rdf/__init__.py b/src/spdx_tools/spdx/writer/rdf/__init__.py similarity index 100% rename from src/spdx/writer/rdf/__init__.py rename to src/spdx_tools/spdx/writer/rdf/__init__.py diff --git a/src/spdx/writer/rdf/annotation_writer.py b/src/spdx_tools/spdx/writer/rdf/annotation_writer.py similarity index 78% rename from src/spdx/writer/rdf/annotation_writer.py rename to src/spdx_tools/spdx/writer/rdf/annotation_writer.py index 490d68cfe..529f0ccd2 100644 --- a/src/spdx/writer/rdf/annotation_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/annotation_writer.py @@ -5,11 +5,11 @@ from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef -from spdx.casing_tools import snake_case_to_camel_case -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.model.annotation import Annotation -from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model.annotation import Annotation +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id def add_annotation_to_graph( diff --git a/src/spdx/writer/rdf/checksum_writer.py b/src/spdx_tools/spdx/writer/rdf/checksum_writer.py similarity index 86% rename from src/spdx/writer/rdf/checksum_writer.py rename to src/spdx_tools/spdx/writer/rdf/checksum_writer.py index 12bfe214e..8af75f53b 100644 --- a/src/spdx/writer/rdf/checksum_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/checksum_writer.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, BNode, Graph, Literal, URIRef -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def add_checksum_to_graph(checksum: Checksum, graph: Graph, parent: URIRef): diff --git a/src/spdx/writer/rdf/creation_info_writer.py b/src/spdx_tools/spdx/writer/rdf/creation_info_writer.py similarity index 80% rename from src/spdx/writer/rdf/creation_info_writer.py rename to src/spdx_tools/spdx/writer/rdf/creation_info_writer.py index 87999bf7c..b457101b6 100644 --- a/src/spdx/writer/rdf/creation_info_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/creation_info_writer.py @@ -3,11 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.model.document import CreationInfo -from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE -from spdx.writer.rdf.external_document_ref_writer import add_external_document_ref_to_graph -from spdx.writer.rdf.writer_utils import add_optional_literal +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.external_document_ref_writer import add_external_document_ref_to_graph +from spdx_tools.spdx.writer.rdf.writer_utils import add_optional_literal def add_creation_info_to_graph(creation_info: CreationInfo, graph: Graph): diff --git a/src/spdx/writer/rdf/external_document_ref_writer.py b/src/spdx_tools/spdx/writer/rdf/external_document_ref_writer.py similarity index 78% rename from src/spdx/writer/rdf/external_document_ref_writer.py rename to src/spdx_tools/spdx/writer/rdf/external_document_ref_writer.py index d84c3d224..536a96434 100644 --- a/src/spdx/writer/rdf/external_document_ref_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/external_document_ref_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, Graph, URIRef -from spdx.model.external_document_ref import ExternalDocumentRef -from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.writer.rdf.checksum_writer import add_checksum_to_graph +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph def add_external_document_ref_to_graph( diff --git a/src/spdx/writer/rdf/extracted_licensing_info_writer.py b/src/spdx_tools/spdx/writer/rdf/extracted_licensing_info_writer.py similarity index 85% rename from src/spdx/writer/rdf/extracted_licensing_info_writer.py rename to src/spdx_tools/spdx/writer/rdf/extracted_licensing_info_writer.py index 15a603d0c..89f163b8f 100644 --- a/src/spdx/writer/rdf/extracted_licensing_info_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/extracted_licensing_info_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.writer.rdf.writer_utils import add_literal_or_no_assertion, add_optional_literal +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.writer_utils import add_literal_or_no_assertion, add_optional_literal def add_extracted_licensing_info_to_graph( diff --git a/src/spdx/writer/rdf/file_writer.py b/src/spdx_tools/spdx/writer/rdf/file_writer.py similarity index 80% rename from src/spdx/writer/rdf/file_writer.py rename to src/spdx_tools/spdx/writer/rdf/file_writer.py index 76d84a549..d3454cc96 100644 --- a/src/spdx/writer/rdf/file_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/file_writer.py @@ -5,12 +5,12 @@ from rdflib import RDF, RDFS, Graph, Literal, URIRef -from spdx.casing_tools import snake_case_to_camel_case -from spdx.model.file import File -from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.writer.rdf.checksum_writer import add_checksum_to_graph -from spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion -from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id, add_optional_literal +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph +from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion +from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id, add_optional_literal def add_file_to_graph(file: File, graph: Graph, doc_namespace: str, external_doc_ref_to_namespace: Dict[str, str]): diff --git a/src/spdx/writer/rdf/license_expression_writer.py b/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py similarity index 94% rename from src/spdx/writer/rdf/license_expression_writer.py rename to src/spdx_tools/spdx/writer/rdf/license_expression_writer.py index d12c992b8..6df0d9800 100644 --- a/src/spdx/writer/rdf/license_expression_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py @@ -16,9 +16,9 @@ from rdflib import RDF, BNode, Graph, URIRef from rdflib.term import Literal, Node -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE def add_license_expression_or_none_or_no_assertion( diff --git a/src/spdx/writer/rdf/package_writer.py b/src/spdx_tools/spdx/writer/rdf/package_writer.py similarity index 93% rename from src/spdx/writer/rdf/package_writer.py rename to src/spdx_tools/spdx/writer/rdf/package_writer.py index 914201ea5..d678ba99d 100644 --- a/src/spdx/writer/rdf/package_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/package_writer.py @@ -5,17 +5,17 @@ from rdflib import DOAP, RDF, RDFS, XSD, BNode, Graph, Literal, URIRef -from spdx.casing_tools import snake_case_to_camel_case -from spdx.model.package import ( +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.model.package import ( CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES, ExternalPackageRef, Package, PackageVerificationCode, ) -from spdx.rdfschema.namespace import REFERENCE_NAMESPACE, SPDX_NAMESPACE -from spdx.writer.rdf.checksum_writer import add_checksum_to_graph -from spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion -from spdx.writer.rdf.writer_utils import ( +from spdx_tools.spdx.rdfschema.namespace import REFERENCE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph +from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion +from spdx_tools.spdx.writer.rdf.writer_utils import ( add_datetime_to_graph, add_literal_or_no_assertion_or_none, add_namespace_to_spdx_id, diff --git a/src/spdx/writer/rdf/rdf_writer.py b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py similarity index 68% rename from src/spdx/writer/rdf/rdf_writer.py rename to src/spdx_tools/spdx/writer/rdf/rdf_writer.py index 78d30f6df..32ba50c80 100644 --- a/src/spdx/writer/rdf/rdf_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py @@ -6,18 +6,18 @@ from rdflib import DOAP, Graph from rdflib.compare import to_isomorphic -from spdx.document_utils import create_document_without_duplicates -from spdx.model.document import Document -from spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE -from spdx.validation.document_validator import validate_full_spdx_document -from spdx.validation.validation_message import ValidationMessage -from spdx.writer.rdf.annotation_writer import add_annotation_to_graph -from spdx.writer.rdf.creation_info_writer import add_creation_info_to_graph -from spdx.writer.rdf.extracted_licensing_info_writer import add_extracted_licensing_info_to_graph -from spdx.writer.rdf.file_writer import add_file_to_graph -from spdx.writer.rdf.package_writer import add_package_to_graph -from spdx.writer.rdf.relationship_writer import add_relationship_to_graph -from spdx.writer.rdf.snippet_writer import add_snippet_to_graph +from spdx_tools.spdx.document_utils import create_document_without_duplicates +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.writer.rdf.annotation_writer import add_annotation_to_graph +from spdx_tools.spdx.writer.rdf.creation_info_writer import add_creation_info_to_graph +from spdx_tools.spdx.writer.rdf.extracted_licensing_info_writer import add_extracted_licensing_info_to_graph +from spdx_tools.spdx.writer.rdf.file_writer import add_file_to_graph +from spdx_tools.spdx.writer.rdf.package_writer import add_package_to_graph +from spdx_tools.spdx.writer.rdf.relationship_writer import add_relationship_to_graph +from spdx_tools.spdx.writer.rdf.snippet_writer import add_snippet_to_graph def write_document_to_file(document: Document, file_name: str, validate: bool, drop_duplicates: bool = True): diff --git a/src/spdx/writer/rdf/relationship_writer.py b/src/spdx_tools/spdx/writer/rdf/relationship_writer.py similarity index 81% rename from src/spdx/writer/rdf/relationship_writer.py rename to src/spdx_tools/spdx/writer/rdf/relationship_writer.py index 9db6fea3f..f33018074 100644 --- a/src/spdx/writer/rdf/relationship_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/relationship_writer.py @@ -5,12 +5,12 @@ from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef -from spdx.casing_tools import snake_case_to_camel_case -from spdx.model.relationship import Relationship -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.model.relationship import Relationship +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id def add_relationship_to_graph( diff --git a/src/spdx/writer/rdf/snippet_writer.py b/src/spdx_tools/spdx/writer/rdf/snippet_writer.py similarity index 89% rename from src/spdx/writer/rdf/snippet_writer.py rename to src/spdx_tools/spdx/writer/rdf/snippet_writer.py index c15304254..2f46cc3c1 100644 --- a/src/spdx/writer/rdf/snippet_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/snippet_writer.py @@ -5,10 +5,10 @@ from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef -from spdx.model.snippet import Snippet -from spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE -from spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion -from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id, add_optional_literal +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion +from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id, add_optional_literal def add_snippet_to_graph( diff --git a/src/spdx/writer/rdf/writer_utils.py b/src/spdx_tools/spdx/writer/rdf/writer_utils.py similarity index 85% rename from src/spdx/writer/rdf/writer_utils.py rename to src/spdx_tools/spdx/writer/rdf/writer_utils.py index f80173fbb..a6118208d 100644 --- a/src/spdx/writer/rdf/writer_utils.py +++ b/src/spdx_tools/spdx/writer/rdf/writer_utils.py @@ -8,11 +8,11 @@ from rdflib import Graph, Literal from rdflib.term import Node -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.validation.spdx_id_validators import is_valid_internal_spdx_id +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.validation.spdx_id_validators import is_valid_internal_spdx_id def add_optional_literal(value: Any, graph: Graph, parent: Node, predicate: Node): diff --git a/src/spdx/writer/tagvalue/__init__.py b/src/spdx_tools/spdx/writer/tagvalue/__init__.py similarity index 100% rename from src/spdx/writer/tagvalue/__init__.py rename to src/spdx_tools/spdx/writer/tagvalue/__init__.py diff --git a/src/spdx/writer/tagvalue/annotation_writer.py b/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py similarity index 82% rename from src/spdx/writer/tagvalue/annotation_writer.py rename to src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py index b74991cc8..7828b903f 100644 --- a/src/spdx/writer/tagvalue/annotation_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py @@ -10,9 +10,9 @@ # limitations under the License. from typing import TextIO -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.model.annotation import Annotation -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model.annotation import Annotation +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value def write_annotation(annotation: Annotation, text_output: TextIO): diff --git a/src/spdx/writer/tagvalue/checksum_writer.py b/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py similarity index 95% rename from src/spdx/writer/tagvalue/checksum_writer.py rename to src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py index 230c0dbfc..91d89dd8a 100644 --- a/src/spdx/writer/tagvalue/checksum_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm def write_checksum_to_tag_value(checksum: Checksum) -> str: diff --git a/src/spdx/writer/tagvalue/creation_info_writer.py b/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py similarity index 91% rename from src/spdx/writer/tagvalue/creation_info_writer.py rename to src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py index 798f7ed21..fca4d0bc3 100644 --- a/src/spdx/writer/tagvalue/creation_info_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py @@ -10,9 +10,9 @@ # limitations under the License. from typing import TextIO -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.model.document import CreationInfo -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( write_optional_heading, write_separator, write_text_value, diff --git a/src/spdx/writer/tagvalue/extracted_licensing_info_writer.py b/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py similarity index 86% rename from src/spdx/writer/tagvalue/extracted_licensing_info_writer.py rename to src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py index 556fb0737..ee728efca 100644 --- a/src/spdx/writer/tagvalue/extracted_licensing_info_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py @@ -10,8 +10,8 @@ # limitations under the License. from typing import TextIO -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value def write_extracted_licensing_info(extracted_licensing_info: ExtractedLicensingInfo, text_output: TextIO): diff --git a/src/spdx/writer/tagvalue/file_writer.py b/src/spdx_tools/spdx/writer/tagvalue/file_writer.py similarity index 88% rename from src/spdx/writer/tagvalue/file_writer.py rename to src/spdx_tools/spdx/writer/tagvalue/file_writer.py index c2d055fbd..1bfc07ff2 100644 --- a/src/spdx/writer/tagvalue/file_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/file_writer.py @@ -10,9 +10,9 @@ # limitations under the License. from typing import TextIO -from spdx.model.file import File -from spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value +from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value def write_file(file: File, text_output: TextIO): diff --git a/src/spdx/writer/tagvalue/package_writer.py b/src/spdx_tools/spdx/writer/tagvalue/package_writer.py similarity index 92% rename from src/spdx/writer/tagvalue/package_writer.py rename to src/spdx_tools/spdx/writer/tagvalue/package_writer.py index 4a7924685..f70259eae 100644 --- a/src/spdx/writer/tagvalue/package_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/package_writer.py @@ -10,10 +10,10 @@ # limitations under the License. from typing import TextIO -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.model.package import Package, PackageVerificationCode -from spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model.package import Package, PackageVerificationCode +from spdx_tools.spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( transform_enum_name_to_tv, write_actor, write_text_value, diff --git a/src/spdx/writer/tagvalue/relationship_writer.py b/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py similarity index 86% rename from src/spdx/writer/tagvalue/relationship_writer.py rename to src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py index 9cf7425fc..b124e81eb 100644 --- a/src/spdx/writer/tagvalue/relationship_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py @@ -10,8 +10,8 @@ # limitations under the License. from typing import TextIO -from spdx.model.relationship import Relationship -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value +from spdx_tools.spdx.model.relationship import Relationship +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value def write_relationship(relationship: Relationship, text_output: TextIO): diff --git a/src/spdx/writer/tagvalue/snippet_writer.py b/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py similarity index 90% rename from src/spdx/writer/tagvalue/snippet_writer.py rename to src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py index 55230bb07..2d404a17e 100644 --- a/src/spdx/writer/tagvalue/snippet_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py @@ -10,8 +10,8 @@ # limitations under the License. from typing import TextIO -from spdx.model.snippet import Snippet -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range, write_text_value, write_value +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range, write_text_value, write_value def write_snippet(snippet: Snippet, text_output: TextIO): diff --git a/src/spdx/writer/tagvalue/tagvalue_writer.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py similarity index 80% rename from src/spdx/writer/tagvalue/tagvalue_writer.py rename to src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py index 418d3afee..13013d385 100644 --- a/src/spdx/writer/tagvalue/tagvalue_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py @@ -10,18 +10,18 @@ # limitations under the License. from typing import List, TextIO -from spdx.document_utils import create_document_without_duplicates -from spdx.model.document import Document -from spdx.validation.document_validator import validate_full_spdx_document -from spdx.validation.validation_message import ValidationMessage -from spdx.writer.tagvalue.annotation_writer import write_annotation -from spdx.writer.tagvalue.creation_info_writer import write_creation_info -from spdx.writer.tagvalue.extracted_licensing_info_writer import write_extracted_licensing_info -from spdx.writer.tagvalue.file_writer import write_file -from spdx.writer.tagvalue.package_writer import write_package -from spdx.writer.tagvalue.relationship_writer import write_relationship -from spdx.writer.tagvalue.snippet_writer import write_snippet -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( +from spdx_tools.spdx.document_utils import create_document_without_duplicates +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.writer.tagvalue.annotation_writer import write_annotation +from spdx_tools.spdx.writer.tagvalue.creation_info_writer import write_creation_info +from spdx_tools.spdx.writer.tagvalue.extracted_licensing_info_writer import write_extracted_licensing_info +from spdx_tools.spdx.writer.tagvalue.file_writer import write_file +from spdx_tools.spdx.writer.tagvalue.package_writer import write_package +from spdx_tools.spdx.writer.tagvalue.relationship_writer import write_relationship +from spdx_tools.spdx.writer.tagvalue.snippet_writer import write_snippet +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( get_file_ids_with_contained_snippets, scan_relationships, write_list_of_elements, diff --git a/src/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py similarity index 91% rename from src/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py rename to src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py index 7b3ad849b..55acdf466 100644 --- a/src/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py @@ -12,13 +12,13 @@ from license_expression import LicenseExpression -from spdx.model.actor import Actor -from spdx.model.file import File -from spdx.model.package import Package -from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.snippet import Snippet -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model.actor import Actor +from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.model.package import Package +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone def write_separator(out: TextIO): diff --git a/src/spdx/writer/write_anything.py b/src/spdx_tools/spdx/writer/write_anything.py similarity index 67% rename from src/spdx/writer/write_anything.py rename to src/spdx_tools/spdx/writer/write_anything.py index 87a8e08a2..26f238d74 100644 --- a/src/spdx/writer/write_anything.py +++ b/src/spdx_tools/spdx/writer/write_anything.py @@ -1,13 +1,13 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from spdx.formats import FileFormat, file_name_to_format -from spdx.model.document import Document -from spdx.writer.json import json_writer -from spdx.writer.rdf import rdf_writer -from spdx.writer.tagvalue import tagvalue_writer -from spdx.writer.xml import xml_writer -from spdx.writer.yaml import yaml_writer +from spdx_tools.spdx.formats import FileFormat, file_name_to_format +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.writer.json import json_writer +from spdx_tools.spdx.writer.rdf import rdf_writer +from spdx_tools.spdx.writer.tagvalue import tagvalue_writer +from spdx_tools.spdx.writer.xml import xml_writer +from spdx_tools.spdx.writer.yaml import yaml_writer def write_file(document: Document, file_name: str, validate: bool = True): diff --git a/src/spdx/writer/xml/__init__.py b/src/spdx_tools/spdx/writer/xml/__init__.py similarity index 100% rename from src/spdx/writer/xml/__init__.py rename to src/spdx_tools/spdx/writer/xml/__init__.py diff --git a/src/spdx/writer/xml/xml_writer.py b/src/spdx_tools/spdx/writer/xml/xml_writer.py similarity index 75% rename from src/spdx/writer/xml/xml_writer.py rename to src/spdx_tools/spdx/writer/xml/xml_writer.py index d9176cccc..bcef88a70 100644 --- a/src/spdx/writer/xml/xml_writer.py +++ b/src/spdx_tools/spdx/writer/xml/xml_writer.py @@ -5,11 +5,11 @@ import xmltodict -from spdx.document_utils import create_document_without_duplicates -from spdx.jsonschema.document_converter import DocumentConverter -from spdx.model.document import Document -from spdx.validation.document_validator import validate_full_spdx_document -from spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.document_utils import create_document_without_duplicates +from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage def write_document_to_file( diff --git a/src/spdx/writer/yaml/__init__.py b/src/spdx_tools/spdx/writer/yaml/__init__.py similarity index 100% rename from src/spdx/writer/yaml/__init__.py rename to src/spdx_tools/spdx/writer/yaml/__init__.py diff --git a/src/spdx/writer/yaml/yaml_writer.py b/src/spdx_tools/spdx/writer/yaml/yaml_writer.py similarity index 75% rename from src/spdx/writer/yaml/yaml_writer.py rename to src/spdx_tools/spdx/writer/yaml/yaml_writer.py index e93915f21..00631b0e0 100644 --- a/src/spdx/writer/yaml/yaml_writer.py +++ b/src/spdx_tools/spdx/writer/yaml/yaml_writer.py @@ -5,11 +5,11 @@ import yaml -from spdx.document_utils import create_document_without_duplicates -from spdx.jsonschema.document_converter import DocumentConverter -from spdx.model.document import Document -from spdx.validation.document_validator import validate_full_spdx_document -from spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.document_utils import create_document_without_duplicates +from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage def write_document_to_file( diff --git a/tests/spdx/fixtures.py b/tests/spdx/fixtures.py index 3065bc824..189da5a61 100644 --- a/tests/spdx/fixtures.py +++ b/tests/spdx/fixtures.py @@ -5,26 +5,26 @@ from license_expression import get_spdx_licensing -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.actor import Actor, ActorType -from spdx.model.annotation import Annotation, AnnotationType -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.document import CreationInfo, Document -from spdx.model.external_document_ref import ExternalDocumentRef -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.model.file import File, FileType -from spdx.model.package import ( +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.document import CreationInfo, Document +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model.file import File, FileType +from spdx_tools.spdx.model.package import ( ExternalPackageRef, ExternalPackageRefCategory, Package, PackagePurpose, PackageVerificationCode, ) -from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.snippet import Snippet -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.model.version import Version +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model.version import Version # Utility methods to create data model instances. All properties have valid defaults, so they don't need to be # specified unless relevant for the test. diff --git a/tests/spdx/jsonschema/test_annotation_converter.py b/tests/spdx/jsonschema/test_annotation_converter.py index 885e1e07b..25d776848 100644 --- a/tests/spdx/jsonschema/test_annotation_converter.py +++ b/tests/spdx/jsonschema/test_annotation_converter.py @@ -5,11 +5,11 @@ import pytest -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.jsonschema.annotation_converter import AnnotationConverter -from spdx.jsonschema.annotation_properties import AnnotationProperty -from spdx.model.actor import Actor, ActorType -from spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.annotation_properties import AnnotationProperty +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType @pytest.fixture diff --git a/tests/spdx/jsonschema/test_checksum_converter.py b/tests/spdx/jsonschema/test_checksum_converter.py index 320082582..de960d62c 100644 --- a/tests/spdx/jsonschema/test_checksum_converter.py +++ b/tests/spdx/jsonschema/test_checksum_converter.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx.jsonschema.checksum_converter import ChecksumConverter -from spdx.jsonschema.checksum_properties import ChecksumProperty -from spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.jsonschema.checksum_converter import ChecksumConverter +from spdx_tools.spdx.jsonschema.checksum_properties import ChecksumProperty +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm @pytest.fixture diff --git a/tests/spdx/jsonschema/test_converter.py b/tests/spdx/jsonschema/test_converter.py index d5edeb647..c6ecfb9c1 100644 --- a/tests/spdx/jsonschema/test_converter.py +++ b/tests/spdx/jsonschema/test_converter.py @@ -6,12 +6,12 @@ import pytest -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx.jsonschema.converter import TypedConverter -from spdx.jsonschema.json_property import JsonProperty -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.document import Document +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx.jsonschema.converter import TypedConverter +from spdx_tools.spdx.jsonschema.json_property import JsonProperty +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.document import Document class TestPropertyType(JsonProperty): diff --git a/tests/spdx/jsonschema/test_creation_info_converter.py b/tests/spdx/jsonschema/test_creation_info_converter.py index 673a4c871..dcbc4de74 100644 --- a/tests/spdx/jsonschema/test_creation_info_converter.py +++ b/tests/spdx/jsonschema/test_creation_info_converter.py @@ -5,12 +5,12 @@ import pytest -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.jsonschema.creation_info_converter import CreationInfoConverter -from spdx.jsonschema.creation_info_properties import CreationInfoProperty -from spdx.model.actor import Actor, ActorType -from spdx.model.document import CreationInfo -from spdx.model.version import Version +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.jsonschema.creation_info_converter import CreationInfoConverter +from spdx_tools.spdx.jsonschema.creation_info_properties import CreationInfoProperty +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.model.version import Version from tests.spdx.fixtures import creation_info_fixture diff --git a/tests/spdx/jsonschema/test_document_converter.py b/tests/spdx/jsonschema/test_document_converter.py index ba964e718..9923c4f73 100644 --- a/tests/spdx/jsonschema/test_document_converter.py +++ b/tests/spdx/jsonschema/test_document_converter.py @@ -8,14 +8,14 @@ import pytest -from spdx.jsonschema.annotation_converter import AnnotationConverter -from spdx.jsonschema.document_converter import DocumentConverter -from spdx.jsonschema.document_properties import DocumentProperty -from spdx.model.actor import Actor, ActorType -from spdx.model.annotation import Annotation, AnnotationType -from spdx.model.document import Document -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter +from spdx_tools.spdx.jsonschema.document_properties import DocumentProperty +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType from tests.spdx.fixtures import ( annotation_fixture, creation_info_fixture, @@ -28,14 +28,16 @@ @pytest.fixture -@mock.patch("spdx.jsonschema.creation_info_converter.CreationInfoConverter", autospec=True) -@mock.patch("spdx.jsonschema.external_document_ref_converter.ExternalDocumentRefConverter", autospec=True) -@mock.patch("spdx.jsonschema.package_converter.PackageConverter", autospec=True) -@mock.patch("spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) -@mock.patch("spdx.jsonschema.extracted_licensing_info_converter.ExtractedLicensingInfoConverter", autospec=True) -@mock.patch("spdx.jsonschema.file_converter.FileConverter", autospec=True) -@mock.patch("spdx.jsonschema.snippet_converter.SnippetConverter", autospec=True) -@mock.patch("spdx.jsonschema.relationship_converter.RelationshipConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.creation_info_converter.CreationInfoConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.external_document_ref_converter.ExternalDocumentRefConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.package_converter.PackageConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) +@mock.patch( + "spdx_tools.spdx.jsonschema.extracted_licensing_info_converter.ExtractedLicensingInfoConverter", autospec=True +) +@mock.patch("spdx_tools.spdx.jsonschema.file_converter.FileConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.snippet_converter.SnippetConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.relationship_converter.RelationshipConverter", autospec=True) def converter( relationship_converter_mock: MagicMock, snippet_converter_mock: MagicMock, diff --git a/tests/spdx/jsonschema/test_external_document_ref_converter.py b/tests/spdx/jsonschema/test_external_document_ref_converter.py index f3a1d3743..4a36e2e73 100644 --- a/tests/spdx/jsonschema/test_external_document_ref_converter.py +++ b/tests/spdx/jsonschema/test_external_document_ref_converter.py @@ -6,14 +6,14 @@ import pytest -from spdx.jsonschema.external_document_ref_converter import ExternalDocumentRefConverter -from spdx.jsonschema.external_document_ref_properties import ExternalDocumentRefProperty -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.jsonschema.external_document_ref_converter import ExternalDocumentRefConverter +from spdx_tools.spdx.jsonschema.external_document_ref_properties import ExternalDocumentRefProperty +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef @pytest.fixture -@mock.patch("spdx.jsonschema.checksum_converter.ChecksumConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.checksum_converter.ChecksumConverter", autospec=True) def converter(checksum_converter_magic_mock: MagicMock) -> ExternalDocumentRefConverter: mocked_checksum_converter = checksum_converter_magic_mock() converter = ExternalDocumentRefConverter() diff --git a/tests/spdx/jsonschema/test_external_package_ref_converter.py b/tests/spdx/jsonschema/test_external_package_ref_converter.py index 7f9e6cb4f..9a4e8f7e5 100644 --- a/tests/spdx/jsonschema/test_external_package_ref_converter.py +++ b/tests/spdx/jsonschema/test_external_package_ref_converter.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx.jsonschema.external_package_ref_converter import ExternalPackageRefConverter -from spdx.jsonschema.external_package_ref_properties import ExternalPackageRefProperty -from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory +from spdx_tools.spdx.jsonschema.external_package_ref_converter import ExternalPackageRefConverter +from spdx_tools.spdx.jsonschema.external_package_ref_properties import ExternalPackageRefProperty +from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory @pytest.fixture diff --git a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py index 518ad2ab5..596ff8fa2 100644 --- a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py +++ b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py @@ -3,10 +3,10 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx.jsonschema.extracted_licensing_info_converter import ExtractedLicensingInfoConverter -from spdx.jsonschema.extracted_licensing_info_properties import ExtractedLicensingInfoProperty -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion +from spdx_tools.spdx.jsonschema.extracted_licensing_info_converter import ExtractedLicensingInfoConverter +from spdx_tools.spdx.jsonschema.extracted_licensing_info_properties import ExtractedLicensingInfoProperty +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion from tests.spdx.fixtures import extracted_licensing_info_fixture diff --git a/tests/spdx/jsonschema/test_file_converter.py b/tests/spdx/jsonschema/test_file_converter.py index 12cd3c22c..d38106f76 100644 --- a/tests/spdx/jsonschema/test_file_converter.py +++ b/tests/spdx/jsonschema/test_file_converter.py @@ -9,23 +9,23 @@ import pytest from license_expression import Licensing -from spdx.jsonschema.annotation_converter import AnnotationConverter -from spdx.jsonschema.file_converter import FileConverter -from spdx.jsonschema.file_properties import FileProperty -from spdx.model.actor import Actor, ActorType -from spdx.model.annotation import Annotation, AnnotationType -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.document import Document -from spdx.model.file import File, FileType -from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion -from spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.file_converter import FileConverter +from spdx_tools.spdx.jsonschema.file_properties import FileProperty +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.file import File, FileType +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone from tests.spdx.fixtures import annotation_fixture, creation_info_fixture, document_fixture, file_fixture from tests.spdx.mock_utils import assert_mock_method_called_with_arguments @pytest.fixture -@mock.patch("spdx.jsonschema.checksum_converter.ChecksumConverter", autospec=True) -@mock.patch("spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.checksum_converter.ChecksumConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) def converter(annotation_converter_mock: MagicMock, checksum_converter_mock: MagicMock) -> FileConverter: converter = FileConverter() converter.checksum_converter = checksum_converter_mock() diff --git a/tests/spdx/jsonschema/test_package_converter.py b/tests/spdx/jsonschema/test_package_converter.py index d35236563..12f4e7945 100644 --- a/tests/spdx/jsonschema/test_package_converter.py +++ b/tests/spdx/jsonschema/test_package_converter.py @@ -9,16 +9,16 @@ import pytest from license_expression import Licensing -from spdx.jsonschema.annotation_converter import AnnotationConverter -from spdx.jsonschema.package_converter import PackageConverter -from spdx.jsonschema.package_properties import PackageProperty -from spdx.model.actor import Actor, ActorType -from spdx.model.annotation import Annotation, AnnotationType -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.document import Document -from spdx.model.package import Package, PackagePurpose, PackageVerificationCode -from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion -from spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.package_converter import PackageConverter +from spdx_tools.spdx.jsonschema.package_properties import PackageProperty +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.package import Package, PackagePurpose, PackageVerificationCode +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone from tests.spdx.fixtures import ( annotation_fixture, creation_info_fixture, @@ -30,10 +30,12 @@ @pytest.fixture -@mock.patch("spdx.jsonschema.checksum_converter.ChecksumConverter", autospec=True) -@mock.patch("spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) -@mock.patch("spdx.jsonschema.package_verification_code_converter.PackageVerificationCodeConverter", autospec=True) -@mock.patch("spdx.jsonschema.external_package_ref_converter.ExternalPackageRefConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.checksum_converter.ChecksumConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) +@mock.patch( + "spdx_tools.spdx.jsonschema.package_verification_code_converter.PackageVerificationCodeConverter", autospec=True +) +@mock.patch("spdx_tools.spdx.jsonschema.external_package_ref_converter.ExternalPackageRefConverter", autospec=True) def converter( package_ref_converter_mock: MagicMock, verification_code_converter_mock: MagicMock, diff --git a/tests/spdx/jsonschema/test_package_verification_code_converter.py b/tests/spdx/jsonschema/test_package_verification_code_converter.py index c63b6829a..1ffb39468 100644 --- a/tests/spdx/jsonschema/test_package_verification_code_converter.py +++ b/tests/spdx/jsonschema/test_package_verification_code_converter.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx.jsonschema.package_verification_code_converter import PackageVerificationCodeConverter -from spdx.jsonschema.package_verification_code_properties import PackageVerificationCodeProperty -from spdx.model.package import PackageVerificationCode +from spdx_tools.spdx.jsonschema.package_verification_code_converter import PackageVerificationCodeConverter +from spdx_tools.spdx.jsonschema.package_verification_code_properties import PackageVerificationCodeProperty +from spdx_tools.spdx.model.package import PackageVerificationCode @pytest.fixture diff --git a/tests/spdx/jsonschema/test_relationship_converter.py b/tests/spdx/jsonschema/test_relationship_converter.py index 9b71fac27..87f0c8ec6 100644 --- a/tests/spdx/jsonschema/test_relationship_converter.py +++ b/tests/spdx/jsonschema/test_relationship_converter.py @@ -3,11 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx.jsonschema.relationship_converter import RelationshipConverter -from spdx.jsonschema.relationship_properties import RelationshipProperty -from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion -from spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from spdx_tools.spdx.jsonschema.relationship_converter import RelationshipConverter +from spdx_tools.spdx.jsonschema.relationship_properties import RelationshipProperty +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone from tests.spdx.fixtures import relationship_fixture diff --git a/tests/spdx/jsonschema/test_snippet_converter.py b/tests/spdx/jsonschema/test_snippet_converter.py index ca59e201b..00b1a48a1 100644 --- a/tests/spdx/jsonschema/test_snippet_converter.py +++ b/tests/spdx/jsonschema/test_snippet_converter.py @@ -9,21 +9,21 @@ import pytest from license_expression import Licensing -from spdx.jsonschema.annotation_converter import AnnotationConverter -from spdx.jsonschema.snippet_converter import SnippetConverter -from spdx.jsonschema.snippet_properties import SnippetProperty -from spdx.model.actor import Actor, ActorType -from spdx.model.annotation import Annotation, AnnotationType -from spdx.model.document import Document -from spdx.model.snippet import Snippet -from spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion -from spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter +from spdx_tools.spdx.jsonschema.snippet_converter import SnippetConverter +from spdx_tools.spdx.jsonschema.snippet_properties import SnippetProperty +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone from tests.spdx.fixtures import annotation_fixture, creation_info_fixture, document_fixture, snippet_fixture from tests.spdx.mock_utils import assert_mock_method_called_with_arguments @pytest.fixture -@mock.patch("spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) +@mock.patch("spdx_tools.spdx.jsonschema.annotation_converter.AnnotationConverter", autospec=True) def converter(annotation_converter_mock: MagicMock) -> SnippetConverter: converter = SnippetConverter() converter.annotation_converter = annotation_converter_mock() diff --git a/tests/spdx/model/test_actor.py b/tests/spdx/model/test_actor.py index 431e1434f..fa0fa0baf 100644 --- a/tests/spdx/model/test_actor.py +++ b/tests/spdx/model/test_actor.py @@ -4,7 +4,7 @@ import pytest -from spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.actor import Actor, ActorType def test_correct_initialization(): diff --git a/tests/spdx/model/test_annotation.py b/tests/spdx/model/test_annotation.py index 6b2410968..c96c94e0a 100644 --- a/tests/spdx/model/test_annotation.py +++ b/tests/spdx/model/test_annotation.py @@ -7,10 +7,10 @@ import pytest -from spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_correct_initialization(actor): annotation = Annotation("id", AnnotationType.OTHER, actor, datetime(2022, 1, 1), "comment") assert annotation.spdx_id == "id" @@ -20,31 +20,31 @@ def test_correct_initialization(actor): assert annotation.annotation_comment == "comment" -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_spdx_id(actor): with pytest.raises(TypeError): Annotation(42, AnnotationType.OTHER, actor, datetime(2022, 1, 1), "comment") -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_annotation_type(actor): with pytest.raises(TypeError): Annotation("id", 42, actor, datetime(2022, 1, 1), "comment") -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_annotator(actor): with pytest.raises(TypeError): Annotation("id", AnnotationType.OTHER, 42, datetime(2022, 1, 1), "comment") -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_annotation_date(actor): with pytest.raises(TypeError): Annotation("id", AnnotationType.OTHER, actor, 42, "comment") -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_annotation_comment(actor): with pytest.raises(TypeError): Annotation("id", AnnotationType.OTHER, actor, datetime(2022, 1, 1), 42) diff --git a/tests/spdx/model/test_checksum.py b/tests/spdx/model/test_checksum.py index d555180c5..3184534ac 100644 --- a/tests/spdx/model/test_checksum.py +++ b/tests/spdx/model/test_checksum.py @@ -4,7 +4,7 @@ import pytest -from spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm def test_correct_initialization(): diff --git a/tests/spdx/model/test_creation_info.py b/tests/spdx/model/test_creation_info.py index 4d544de11..9166ce714 100644 --- a/tests/spdx/model/test_creation_info.py +++ b/tests/spdx/model/test_creation_info.py @@ -7,12 +7,12 @@ import pytest -from spdx.model.document import CreationInfo -from spdx.model.version import Version +from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.model.version import Version -@mock.patch("spdx.model.external_document_ref.ExternalDocumentRef", autospec=True) -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.external_document_ref.ExternalDocumentRef", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_correct_initialization(actor, ext_ref): creation_info = CreationInfo( "version", @@ -40,25 +40,25 @@ def test_correct_initialization(actor, ext_ref): assert creation_info.document_comment == "doc_comment" -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_spdx_version(actor): with pytest.raises(TypeError): CreationInfo(42, "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1)) -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_spdx_id(actor): with pytest.raises(TypeError): CreationInfo("version", 42, "name", "namespace", [actor, actor], datetime(2022, 1, 1)) -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_name(actor): with pytest.raises(TypeError): CreationInfo("version", "id", 42, "namespace", [actor, actor], datetime(2022, 1, 1)) -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_document_namespace(actor): with pytest.raises(TypeError): CreationInfo("version", "id", "name", 42, [actor, actor], datetime(2022, 1, 1)) @@ -69,13 +69,13 @@ def test_wrong_type_in_creators(): CreationInfo("version", "id", "name", "namespace", ["person"], datetime(2022, 1, 1)) -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_created(actor): with pytest.raises(TypeError): CreationInfo("version", "id", "name", "namespace", [actor, actor], "2022-01-01") -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_creator_comment(actor): with pytest.raises(TypeError): CreationInfo( @@ -83,13 +83,13 @@ def test_wrong_type_in_creator_comment(actor): ) -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_data_license(actor): with pytest.raises(TypeError): CreationInfo("version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), data_license=42) -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_external_document_refs(actor): with pytest.raises(TypeError): CreationInfo( @@ -97,7 +97,7 @@ def test_wrong_type_in_external_document_refs(actor): ) -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_license_list_version(actor): with pytest.raises(TypeError): CreationInfo( @@ -105,7 +105,7 @@ def test_wrong_type_in_license_list_version(actor): ) -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_wrong_type_in_document_comment(actor): with pytest.raises(TypeError): CreationInfo( diff --git a/tests/spdx/model/test_document.py b/tests/spdx/model/test_document.py index 8043ab3cf..858404ae4 100644 --- a/tests/spdx/model/test_document.py +++ b/tests/spdx/model/test_document.py @@ -6,16 +6,16 @@ import pytest -from spdx.model.document import Document +from spdx_tools.spdx.model.document import Document -@mock.patch("spdx.model.extracted_licensing_info.ExtractedLicensingInfo", autospec=True) -@mock.patch("spdx.model.relationship.Relationship", autospec=True) -@mock.patch("spdx.model.annotation.Annotation", autospec=True) -@mock.patch("spdx.model.snippet.Snippet", autospec=True) -@mock.patch("spdx.model.file.File", autospec=True) -@mock.patch("spdx.model.package.Package", autospec=True) -@mock.patch("spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.extracted_licensing_info.ExtractedLicensingInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.relationship.Relationship", autospec=True) +@mock.patch("spdx_tools.spdx.model.annotation.Annotation", autospec=True) +@mock.patch("spdx_tools.spdx.model.snippet.Snippet", autospec=True) +@mock.patch("spdx_tools.spdx.model.file.File", autospec=True) +@mock.patch("spdx_tools.spdx.model.package.Package", autospec=True) +@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) def test_correct_initialization(creation_info, package, file, snippet, annotation, relationship, extracted_lic): document = Document( creation_info, @@ -35,7 +35,7 @@ def test_correct_initialization(creation_info, package, file, snippet, annotatio assert document.extracted_licensing_info == [extracted_lic, extracted_lic] -@mock.patch("spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) def test_correct_initialization_with_default_values(creation_info): document = Document(creation_info) assert document.creation_info == creation_info @@ -52,37 +52,37 @@ def test_wrong_type_in_creation_info(): Document("string") -@mock.patch("spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) def test_wrong_type_in_packages(creation_info): with pytest.raises(TypeError): Document(creation_info, packages=["string"]) -@mock.patch("spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) def test_wrong_type_in_files(creation_info): with pytest.raises(TypeError): Document(creation_info, files={}) -@mock.patch("spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) def test_wrong_type_in_snippets(creation_info): with pytest.raises(TypeError): Document(creation_info, snippets=()) -@mock.patch("spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) def test_wrong_type_in_annotations(creation_info): with pytest.raises(TypeError): Document(creation_info, annotations=["string"]) -@mock.patch("spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) def test_wrong_type_in_relationships(creation_info): with pytest.raises(TypeError): Document(creation_info, relationships="string") -@mock.patch("spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) def test_wrong_type_in_extracted_licensing_info(creation_info): with pytest.raises(TypeError): Document(creation_info, extracted_licensing_info=42) diff --git a/tests/spdx/model/test_external_document_ref.py b/tests/spdx/model/test_external_document_ref.py index befd2d95b..29e6a4824 100644 --- a/tests/spdx/model/test_external_document_ref.py +++ b/tests/spdx/model/test_external_document_ref.py @@ -6,10 +6,10 @@ import pytest -from spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_correct_initialization(checksum): external_document_ref = ExternalDocumentRef("id", "uri", checksum) assert external_document_ref.document_ref_id == "id" @@ -17,13 +17,13 @@ def test_correct_initialization(checksum): assert external_document_ref.checksum == checksum -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_spdx_id(checksum): with pytest.raises(TypeError): ExternalDocumentRef(42, "uri", checksum) -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_document_uri(checksum): with pytest.raises(TypeError): ExternalDocumentRef("id", 42, checksum) diff --git a/tests/spdx/model/test_external_package_reference.py b/tests/spdx/model/test_external_package_reference.py index adfb2b356..7ac967e2f 100644 --- a/tests/spdx/model/test_external_package_reference.py +++ b/tests/spdx/model/test_external_package_reference.py @@ -4,7 +4,7 @@ import pytest -from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory +from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory def test_correct_initialization(): diff --git a/tests/spdx/model/test_extracted_licensing_info.py b/tests/spdx/model/test_extracted_licensing_info.py index 72f2cf76d..1f54e9207 100644 --- a/tests/spdx/model/test_extracted_licensing_info.py +++ b/tests/spdx/model/test_extracted_licensing_info.py @@ -4,7 +4,7 @@ import pytest -from spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo def test_correct_initialization(): diff --git a/tests/spdx/model/test_file.py b/tests/spdx/model/test_file.py index c8fd79520..fb6d6b54e 100644 --- a/tests/spdx/model/test_file.py +++ b/tests/spdx/model/test_file.py @@ -6,13 +6,13 @@ import pytest -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.file import File, FileType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.file import File, FileType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_correct_initialization(checksum): file = File( "name", @@ -42,7 +42,7 @@ def test_correct_initialization(checksum): assert file.attribution_texts == ["attribution"] -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_correct_initialization_with_default_values(checksum): file = File("name", "id", [checksum, checksum]) assert file.name == "name" @@ -59,13 +59,13 @@ def test_correct_initialization_with_default_values(checksum): assert file.attribution_texts == [] -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_name(checksum): with pytest.raises(TypeError): File(42, "id", [checksum]) -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_spdx_id(checksum): with pytest.raises(TypeError): File("name", 42, [checksum]) @@ -77,55 +77,55 @@ def test_wrong_type_in_checksum(): File("name", "id", checksum) -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_file_type(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], file_types=FileType.OTHER) -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_license_concluded(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], license_concluded="NONE") -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_license_info_in_file(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], license_info_in_file=[SpdxNone]) -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_license_comment(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], license_comment=42) -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_copyright_text(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], copyright_text=[SpdxNone()]) -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_comment(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], comment=42) -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_notice(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], notice=["notice"]) -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_contributors(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], contributors="contributor") -@mock.patch("spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) def test_wrong_type_in_attribution_texts(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], attribution_texts=["attribution", 42]) diff --git a/tests/spdx/model/test_package.py b/tests/spdx/model/test_package.py index e6a5eeec7..afb7951a9 100644 --- a/tests/spdx/model/test_package.py +++ b/tests/spdx/model/test_package.py @@ -8,16 +8,16 @@ import pytest from license_expression import LicenseExpression, Licensing -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.package import Package, PackagePurpose -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.package import Package, PackagePurpose +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone -@mock.patch("spdx.model.package.ExternalPackageRef", autospec=True) -@mock.patch("spdx.model.checksum.Checksum", autospec=True) -@mock.patch("spdx.model.package.PackageVerificationCode", autospec=True) -@mock.patch("spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.package.ExternalPackageRef", autospec=True) +@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.package.PackageVerificationCode", autospec=True) +@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) def test_correct_initialization(actor, verif_code, checksum, ext_ref): package = Package( "id", diff --git a/tests/spdx/model/test_package_verification_code.py b/tests/spdx/model/test_package_verification_code.py index 8f81152b4..b6c0f9d1e 100644 --- a/tests/spdx/model/test_package_verification_code.py +++ b/tests/spdx/model/test_package_verification_code.py @@ -4,7 +4,7 @@ import pytest -from spdx.model.package import PackageVerificationCode +from spdx_tools.spdx.model.package import PackageVerificationCode def test_correct_initialization(): diff --git a/tests/spdx/model/test_relationship.py b/tests/spdx/model/test_relationship.py index 7fa813631..80ba441d1 100644 --- a/tests/spdx/model/test_relationship.py +++ b/tests/spdx/model/test_relationship.py @@ -4,8 +4,8 @@ import pytest -from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion def test_correct_initialization(): diff --git a/tests/spdx/model/test_snippet.py b/tests/spdx/model/test_snippet.py index 8f6bd8483..373e9b37f 100644 --- a/tests/spdx/model/test_snippet.py +++ b/tests/spdx/model/test_snippet.py @@ -4,9 +4,9 @@ import pytest -from spdx.model.snippet import Snippet -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone def test_correct_initialization(): diff --git a/tests/spdx/model/test_version.py b/tests/spdx/model/test_version.py index 310dcf7fd..b846703b3 100644 --- a/tests/spdx/model/test_version.py +++ b/tests/spdx/model/test_version.py @@ -4,7 +4,7 @@ import pytest -from spdx.model.version import Version +from spdx_tools.spdx.model.version import Version @pytest.mark.parametrize("input_string,expected", [("1.2", Version(1, 2)), ("12.345", Version(12, 345))]) diff --git a/tests/spdx/parser/all_formats/test_parse_from_file.py b/tests/spdx/parser/all_formats/test_parse_from_file.py index 083e7a0fa..bb63711b7 100644 --- a/tests/spdx/parser/all_formats/test_parse_from_file.py +++ b/tests/spdx/parser/all_formats/test_parse_from_file.py @@ -6,12 +6,12 @@ import pytest -from spdx.model.document import Document -from spdx.parser.json import json_parser -from spdx.parser.rdf import rdf_parser -from spdx.parser.tagvalue import tagvalue_parser -from spdx.parser.xml import xml_parser -from spdx.parser.yaml import yaml_parser +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.parser.json import json_parser +from spdx_tools.spdx.parser.rdf import rdf_parser +from spdx_tools.spdx.parser.tagvalue import tagvalue_parser +from spdx_tools.spdx.parser.xml import xml_parser +from spdx_tools.spdx.parser.yaml import yaml_parser @pytest.mark.parametrize( diff --git a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py index 1b6297eaf..b7a01d73e 100644 --- a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py @@ -6,11 +6,11 @@ import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.actor import Actor, ActorType -from spdx.model.annotation import Annotation, AnnotationType -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.annotation_parser import AnnotationParser +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.annotation_parser import AnnotationParser def test_parse_annotation(): @@ -128,7 +128,7 @@ def test_parse_all_annotations(): "Error while constructing Annotation: ['SetterError Annotation: type of " 'argument "spdx_id" must be str; got NoneType instead: None\', ' '\'SetterError Annotation: type of argument "annotation_type" must be ' - "spdx.model.annotation.AnnotationType; got NoneType instead: None', " + "spdx_tools.spdx.model.annotation.AnnotationType; got NoneType instead: None', " '\'SetterError Annotation: type of argument "annotation_date" must be ' "datetime.datetime; got NoneType instead: None', 'SetterError Annotation: " 'type of argument "annotation_comment" must be str; got NoneType instead: ' @@ -141,9 +141,9 @@ def test_parse_all_annotations(): "Error while constructing Annotation: ['SetterError Annotation: type of " 'argument "spdx_id" must be str; got NoneType instead: None\', ' '\'SetterError Annotation: type of argument "annotation_type" must be ' - "spdx.model.annotation.AnnotationType; got NoneType instead: None', " + "spdx_tools.spdx.model.annotation.AnnotationType; got NoneType instead: None', " '\'SetterError Annotation: type of argument "annotator" must be ' - "spdx.model.actor.Actor; got NoneType instead: None', 'SetterError Annotation: " + "spdx_tools.spdx.model.actor.Actor; got NoneType instead: None', 'SetterError Annotation: " 'type of argument "annotation_comment" must be str; got NoneType instead: ' "None']" ], diff --git a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py index bdb0de3e9..42efafd75 100644 --- a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py @@ -5,9 +5,9 @@ import pytest -from spdx.model.checksum import ChecksumAlgorithm -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.checksum_parser import ChecksumParser +from spdx_tools.spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser def test_parse_checksum(): diff --git a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py index a77dbba7a..ffaa0046a 100644 --- a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py @@ -6,13 +6,13 @@ import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.actor import Actor, ActorType -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.external_document_ref import ExternalDocumentRef -from spdx.model.version import Version -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.creation_info_parser import CreationInfoParser +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.creation_info_parser import CreationInfoParser def test_parse_creation_info(): diff --git a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py index 7fe85d33a..9eb4e49cf 100644 --- a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py +++ b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py @@ -5,10 +5,10 @@ import pytest -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.dict_parsing_functions import ( +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( json_str_to_enum_name, parse_field_or_no_assertion, parse_field_or_no_assertion_or_none, diff --git a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py index 859f1bf04..98bcc0c81 100644 --- a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py @@ -5,8 +5,8 @@ import pytest -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.extracted_licensing_info_parser import ExtractedLicensingInfoParser +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.extracted_licensing_info_parser import ExtractedLicensingInfoParser def test_parse_extracted_licensing_info(): diff --git a/tests/spdx/parser/jsonlikedict/test_file_parser.py b/tests/spdx/parser/jsonlikedict/test_file_parser.py index 6aacf44ad..a67d9cd69 100644 --- a/tests/spdx/parser/jsonlikedict/test_file_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_file_parser.py @@ -6,13 +6,13 @@ import pytest from license_expression import Licensing -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.file import FileType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements -from spdx.parser.jsonlikedict.file_parser import FileParser +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.file import FileType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements +from spdx_tools.spdx.parser.jsonlikedict.file_parser import FileParser @pytest.mark.parametrize( diff --git a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py index 26dbbc21b..8f0e50ad6 100644 --- a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py @@ -6,10 +6,10 @@ import pytest from license_expression import get_spdx_licensing -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser @pytest.mark.parametrize( diff --git a/tests/spdx/parser/jsonlikedict/test_package_parser.py b/tests/spdx/parser/jsonlikedict/test_package_parser.py index bb0fea497..c67ae871a 100644 --- a/tests/spdx/parser/jsonlikedict/test_package_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_package_parser.py @@ -7,14 +7,19 @@ import pytest from license_expression import Licensing -from spdx.model.actor import Actor, ActorType -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory, PackagePurpose, PackageVerificationCode -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements -from spdx.parser.jsonlikedict.package_parser import PackageParser +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.package import ( + ExternalPackageRef, + ExternalPackageRefCategory, + PackagePurpose, + PackageVerificationCode, +) +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements +from spdx_tools.spdx.parser.jsonlikedict.package_parser import PackageParser @pytest.mark.parametrize( @@ -228,8 +233,8 @@ def test_parse_package( [ "Error while constructing Package: ['SetterError Package: type of " "argument \"name\" must be str; got NoneType instead: None', 'SetterError Package: type of argument " - '"download_location" must be one of (str, spdx.model.spdx_no_assertion.SpdxNoAssertion, ' - "spdx.model.spdx_none.SpdxNone); " + '"download_location" must be one of (str, spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion, ' + "spdx_tools.spdx.model.spdx_none.SpdxNone); " "got NoneType instead: None']" ], ), @@ -307,7 +312,7 @@ def test_parse_external_ref(): [ "Error while constructing ExternalPackageRef: ['SetterError " 'ExternalPackageRef: type of argument "category" must be ' - "spdx.model.package.ExternalPackageRefCategory; got NoneType instead: None', " + "spdx_tools.spdx.model.package.ExternalPackageRefCategory; got NoneType instead: None', " '\'SetterError ExternalPackageRef: type of argument "locator" must be str; ' "got NoneType instead: None']" ], diff --git a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py index af394ef78..20eba29d0 100644 --- a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py @@ -5,11 +5,11 @@ import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.relationship_parser import RelationshipParser +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.relationship_parser import RelationshipParser def test_parse_relationship(): @@ -46,7 +46,7 @@ def test_parse_incomplete_relationship(): [ "Error while constructing Relationship: ['SetterError Relationship: type of " 'argument "relationship_type" must be ' - "spdx.model.relationship.RelationshipType; got NoneType instead: None']" + "spdx_tools.spdx.model.relationship.RelationshipType; got NoneType instead: None']" ], ) diff --git a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py index 1cbceb95e..c4ccba1c2 100644 --- a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py @@ -6,10 +6,10 @@ import pytest from license_expression import Licensing -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.parser.error import SPDXParsingError -from spdx.parser.jsonlikedict.snippet_parser import SnippetParser +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.snippet_parser import SnippetParser @pytest.mark.parametrize( diff --git a/tests/spdx/parser/rdf/test_annotation_parser.py b/tests/spdx/parser/rdf/test_annotation_parser.py index c98c34675..ac494381d 100644 --- a/tests/spdx/parser/rdf/test_annotation_parser.py +++ b/tests/spdx/parser/rdf/test_annotation_parser.py @@ -6,10 +6,10 @@ from rdflib import BNode, Graph, URIRef -from spdx.model.actor import Actor, ActorType -from spdx.model.annotation import AnnotationType -from spdx.parser.rdf.annotation_parser import parse_annotation -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.annotation import AnnotationType +from spdx_tools.spdx.parser.rdf.annotation_parser import parse_annotation +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def test_parse_annotation(): diff --git a/tests/spdx/parser/rdf/test_checksum_parser.py b/tests/spdx/parser/rdf/test_checksum_parser.py index 575d1f3cc..5b5be1c21 100644 --- a/tests/spdx/parser/rdf/test_checksum_parser.py +++ b/tests/spdx/parser/rdf/test_checksum_parser.py @@ -6,10 +6,10 @@ import pytest from rdflib import BNode, Graph, URIRef -from spdx.model.checksum import ChecksumAlgorithm -from spdx.parser.error import SPDXParsingError -from spdx.parser.rdf.checksum_parser import convert_rdf_to_algorithm, parse_checksum -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.rdf.checksum_parser import convert_rdf_to_algorithm, parse_checksum +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def test_parse_checksum(): diff --git a/tests/spdx/parser/rdf/test_creation_info_parser.py b/tests/spdx/parser/rdf/test_creation_info_parser.py index 9845dd0a7..a4dcb5b0c 100644 --- a/tests/spdx/parser/rdf/test_creation_info_parser.py +++ b/tests/spdx/parser/rdf/test_creation_info_parser.py @@ -9,16 +9,16 @@ from rdflib import RDF, Graph, URIRef from rdflib.term import Node -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.actor import Actor, ActorType -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.version import Version -from spdx.parser.rdf.creation_info_parser import ( +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.parser.rdf.creation_info_parser import ( parse_creation_info, parse_external_document_refs, parse_namespace_and_spdx_id, ) -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def test_parse_creation_info(): diff --git a/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py b/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py index 8b3977868..d6027aa7b 100644 --- a/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/rdf/test_extracted_licensing_info_parser.py @@ -6,8 +6,8 @@ import pytest from rdflib import RDF, Graph -from spdx.parser.rdf.extracted_licensing_info_parser import parse_extracted_licensing_info -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.parser.rdf.extracted_licensing_info_parser import parse_extracted_licensing_info +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE @pytest.mark.parametrize( diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py index 17b0edeef..d381a1567 100644 --- a/tests/spdx/parser/rdf/test_file_parser.py +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -7,11 +7,11 @@ from license_expression import get_spdx_licensing from rdflib import RDF, Graph, URIRef -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.file import FileType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.parser.rdf.file_parser import parse_file -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.file import FileType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.parser.rdf.file_parser import parse_file +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def test_parse_file(): diff --git a/tests/spdx/parser/rdf/test_graph_parsing_function.py b/tests/spdx/parser/rdf/test_graph_parsing_function.py index 61326fa0d..2a9fc8a43 100644 --- a/tests/spdx/parser/rdf/test_graph_parsing_function.py +++ b/tests/spdx/parser/rdf/test_graph_parsing_function.py @@ -4,7 +4,7 @@ import pytest from rdflib import Graph, Namespace, URIRef -from spdx.parser.rdf.graph_parsing_functions import parse_spdx_id, remove_prefix +from spdx_tools.spdx.parser.rdf.graph_parsing_functions import parse_spdx_id, remove_prefix @pytest.mark.parametrize( diff --git a/tests/spdx/parser/rdf/test_license_expression_parser.py b/tests/spdx/parser/rdf/test_license_expression_parser.py index 71772ae45..5f3ada8c7 100644 --- a/tests/spdx/parser/rdf/test_license_expression_parser.py +++ b/tests/spdx/parser/rdf/test_license_expression_parser.py @@ -7,9 +7,9 @@ from license_expression import get_spdx_licensing from rdflib import RDF, Graph -from spdx.parser.rdf import rdf_parser -from spdx.parser.rdf.license_expression_parser import parse_license_expression -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.parser.rdf import rdf_parser +from spdx_tools.spdx.parser.rdf.license_expression_parser import parse_license_expression +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def test_license_expression_parser(): diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index d48797a14..6e5850cf3 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -8,12 +8,12 @@ from license_expression import get_spdx_licensing from rdflib import RDF, BNode, Graph, Literal, URIRef -from spdx.model.actor import Actor, ActorType -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.package import ExternalPackageRefCategory, PackagePurpose, PackageVerificationCode -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.parser.rdf.package_parser import parse_external_package_ref, parse_package -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.package import ExternalPackageRefCategory, PackagePurpose, PackageVerificationCode +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.parser.rdf.package_parser import parse_external_package_ref, parse_package +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def test_package_parser(): diff --git a/tests/spdx/parser/rdf/test_relationship_parser.py b/tests/spdx/parser/rdf/test_relationship_parser.py index cb7b4572f..5bc60ee6c 100644 --- a/tests/spdx/parser/rdf/test_relationship_parser.py +++ b/tests/spdx/parser/rdf/test_relationship_parser.py @@ -6,10 +6,10 @@ import pytest from rdflib import RDF, Graph, URIRef -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.relationship import RelationshipType -from spdx.parser.rdf.relationship_parser import parse_implicit_relationship, parse_relationship -from spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.relationship import RelationshipType +from spdx_tools.spdx.parser.rdf.relationship_parser import parse_implicit_relationship, parse_relationship +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE def test_relationship_parser(): diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index 13dcf5fdc..4db77875b 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -8,10 +8,10 @@ from license_expression import get_spdx_licensing from rdflib import RDF, BNode, Graph, Literal, URIRef -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.parser.error import SPDXParsingError -from spdx.parser.rdf.snippet_parser import parse_ranges, parse_snippet -from spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.rdf.snippet_parser import parse_ranges, parse_snippet +from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE def test_parse_snippet(): diff --git a/tests/spdx/parser/tagvalue/test_annotation_parser.py b/tests/spdx/parser/tagvalue/test_annotation_parser.py index d7d130476..cfbd1f40f 100644 --- a/tests/spdx/parser/tagvalue/test_annotation_parser.py +++ b/tests/spdx/parser/tagvalue/test_annotation_parser.py @@ -5,10 +5,10 @@ import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.annotation import AnnotationType -from spdx.parser.error import SPDXParsingError -from spdx.parser.tagvalue.parser import Parser +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.annotation import AnnotationType +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/parser/tagvalue/test_creation_info_parser.py b/tests/spdx/parser/tagvalue/test_creation_info_parser.py index e7b07d4bf..7fd0d275b 100644 --- a/tests/spdx/parser/tagvalue/test_creation_info_parser.py +++ b/tests/spdx/parser/tagvalue/test_creation_info_parser.py @@ -6,13 +6,13 @@ import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.actor import Actor, ActorType -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.model.external_document_ref import ExternalDocumentRef -from spdx.model.version import Version -from spdx.parser.error import SPDXParsingError -from spdx.parser.tagvalue.parser import Parser +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser DOCUMENT_STR = "\n".join( [ diff --git a/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py b/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py index e272a2992..06fb85520 100644 --- a/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/tagvalue/test_extracted_licensing_info_parser.py @@ -5,8 +5,8 @@ import pytest -from spdx.parser.error import SPDXParsingError -from spdx.parser.tagvalue.parser import Parser +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/parser/tagvalue/test_file_parser.py b/tests/spdx/parser/tagvalue/test_file_parser.py index 18b0c5091..d4e0df719 100644 --- a/tests/spdx/parser/tagvalue/test_file_parser.py +++ b/tests/spdx/parser/tagvalue/test_file_parser.py @@ -4,10 +4,10 @@ import pytest from license_expression import get_spdx_licensing -from spdx.model.file import FileType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.parser.error import SPDXParsingError -from spdx.parser.tagvalue.parser import Parser +from spdx_tools.spdx.model.file import FileType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/parser/tagvalue/test_helper_methods.py b/tests/spdx/parser/tagvalue/test_helper_methods.py index 27e7ea7c8..4419902f3 100644 --- a/tests/spdx/parser/tagvalue/test_helper_methods.py +++ b/tests/spdx/parser/tagvalue/test_helper_methods.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx.model.checksum import ChecksumAlgorithm -from spdx.parser.tagvalue.helper_methods import parse_checksum +from spdx_tools.spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx.parser.tagvalue.helper_methods import parse_checksum @pytest.mark.parametrize( diff --git a/tests/spdx/parser/tagvalue/test_package_parser.py b/tests/spdx/parser/tagvalue/test_package_parser.py index 40794473d..76d8ddb0a 100644 --- a/tests/spdx/parser/tagvalue/test_package_parser.py +++ b/tests/spdx/parser/tagvalue/test_package_parser.py @@ -7,11 +7,11 @@ import pytest from license_expression import get_spdx_licensing -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory, PackagePurpose -from spdx.model.spdx_none import SpdxNone -from spdx.parser.error import SPDXParsingError -from spdx.parser.tagvalue.parser import Parser +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory, PackagePurpose +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/parser/tagvalue/test_relationship_parser.py b/tests/spdx/parser/tagvalue/test_relationship_parser.py index 212d1c261..59016c5a9 100644 --- a/tests/spdx/parser/tagvalue/test_relationship_parser.py +++ b/tests/spdx/parser/tagvalue/test_relationship_parser.py @@ -3,12 +3,12 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.parser.error import SPDXParsingError -from spdx.parser.tagvalue.parser import Parser +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/parser/tagvalue/test_snippet_parser.py b/tests/spdx/parser/tagvalue/test_snippet_parser.py index de4af17a9..42a170b87 100644 --- a/tests/spdx/parser/tagvalue/test_snippet_parser.py +++ b/tests/spdx/parser/tagvalue/test_snippet_parser.py @@ -6,9 +6,9 @@ import pytest from license_expression import get_spdx_licensing -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.parser.error import SPDXParsingError -from spdx.parser.tagvalue.parser import Parser +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py index 8136a4c50..c61ee6200 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_lexer.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_lexer.py @@ -4,8 +4,8 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.parser.tagvalue.lexer import SPDXLexer +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.parser.tagvalue.lexer import SPDXLexer @pytest.fixture diff --git a/tests/spdx/parser/tagvalue/test_tag_value_parser.py b/tests/spdx/parser/tagvalue/test_tag_value_parser.py index 44b4375e9..dfb20fad6 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_parser.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_parser.py @@ -5,10 +5,10 @@ import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.relationship import Relationship, RelationshipType -from spdx.parser.error import SPDXParsingError -from spdx.parser.tagvalue.parser import Parser +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/test_actor_parser.py b/tests/spdx/test_actor_parser.py index fda13d4ba..73eac6366 100644 --- a/tests/spdx/test_actor_parser.py +++ b/tests/spdx/test_actor_parser.py @@ -5,9 +5,9 @@ import pytest -from spdx.model.actor import ActorType -from spdx.parser.actor_parser import ActorParser -from spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.model.actor import ActorType +from spdx_tools.spdx.parser.actor_parser import ActorParser +from spdx_tools.spdx.parser.error import SPDXParsingError @pytest.mark.parametrize( diff --git a/tests/spdx/test_casing_tools.py b/tests/spdx/test_casing_tools.py index 78da1a9cb..928935e94 100644 --- a/tests/spdx/test_casing_tools.py +++ b/tests/spdx/test_casing_tools.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx.casing_tools import camel_case_to_snake_case, snake_case_to_camel_case +from spdx_tools.spdx.casing_tools import camel_case_to_snake_case, snake_case_to_camel_case @pytest.mark.parametrize("snake_case_str,camel_case_str", [("snake_case", "snakeCase")]) diff --git a/tests/spdx/test_cli.py b/tests/spdx/test_cli.py index 39660392d..8bdedbb8e 100644 --- a/tests/spdx/test_cli.py +++ b/tests/spdx/test_cli.py @@ -3,7 +3,7 @@ import pytest from click.testing import CliRunner -from spdx.clitools.pyspdxtools import main +from spdx_tools.spdx.clitools.pyspdxtools import main @pytest.mark.parametrize( diff --git a/tests/spdx/test_datetime_conversions.py b/tests/spdx/test_datetime_conversions.py index 184ef8ab1..4c4b8070f 100644 --- a/tests/spdx/test_datetime_conversions.py +++ b/tests/spdx/test_datetime_conversions.py @@ -5,7 +5,7 @@ import pytest -from spdx.datetime_conversions import datetime_from_str, datetime_to_iso_string +from spdx_tools.spdx.datetime_conversions import datetime_from_str, datetime_to_iso_string def test_datetime_to_iso_string(): diff --git a/tests/spdx/test_document_utils.py b/tests/spdx/test_document_utils.py index bb40da4ff..a49e6af1e 100644 --- a/tests/spdx/test_document_utils.py +++ b/tests/spdx/test_document_utils.py @@ -5,16 +5,16 @@ import pytest -from spdx.document_utils import ( +from spdx_tools.spdx.document_utils import ( create_document_without_duplicates, create_list_without_duplicates, get_contained_spdx_element_ids, get_contained_spdx_elements, get_element_from_spdx_id, ) -from spdx.model.file import FileType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model.file import FileType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone from tests.spdx.fixtures import ( actor_fixture, checksum_fixture, diff --git a/tests/spdx/test_graph_generation.py b/tests/spdx/test_graph_generation.py index 492841847..9961cb71f 100644 --- a/tests/spdx/test_graph_generation.py +++ b/tests/spdx/test_graph_generation.py @@ -7,10 +7,10 @@ import pytest -from spdx.graph_generation import generate_relationship_graph_from_spdx -from spdx.model.document import Document -from spdx.model.relationship import Relationship, RelationshipType -from spdx.parser.parse_anything import parse_file +from spdx_tools.spdx.graph_generation import generate_relationship_graph_from_spdx +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.parser.parse_anything import parse_file from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture try: diff --git a/tests/spdx/validation/test_actor_validator.py b/tests/spdx/validation/test_actor_validator.py index bd9803707..14b8dc1c1 100644 --- a/tests/spdx/validation/test_actor_validator.py +++ b/tests/spdx/validation/test_actor_validator.py @@ -6,10 +6,10 @@ import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.actor import ActorType -from spdx.validation.actor_validator import validate_actor -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.actor import ActorType +from spdx_tools.spdx.validation.actor_validator import validate_actor +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import actor_fixture diff --git a/tests/spdx/validation/test_annotation_validator.py b/tests/spdx/validation/test_annotation_validator.py index eeb473264..86787f858 100644 --- a/tests/spdx/validation/test_annotation_validator.py +++ b/tests/spdx/validation/test_annotation_validator.py @@ -6,10 +6,10 @@ import pytest -from spdx.model.annotation import Annotation -from spdx.model.document import Document -from spdx.validation.annotation_validator import validate_annotation -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.annotation import Annotation +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.validation.annotation_validator import validate_annotation +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import annotation_fixture, document_fixture, file_fixture diff --git a/tests/spdx/validation/test_checksum_validator.py b/tests/spdx/validation/test_checksum_validator.py index 1112774b2..e93b1d9dc 100644 --- a/tests/spdx/validation/test_checksum_validator.py +++ b/tests/spdx/validation/test_checksum_validator.py @@ -6,9 +6,9 @@ import pytest -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.validation.checksum_validator import validate_checksum -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.validation.checksum_validator import validate_checksum +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import checksum_fixture diff --git a/tests/spdx/validation/test_creation_info_validator.py b/tests/spdx/validation/test_creation_info_validator.py index a015d258e..340993ebf 100644 --- a/tests/spdx/validation/test_creation_info_validator.py +++ b/tests/spdx/validation/test_creation_info_validator.py @@ -6,9 +6,9 @@ import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.validation.creation_info_validator import validate_creation_info -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.validation.creation_info_validator import validate_creation_info +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import creation_info_fixture diff --git a/tests/spdx/validation/test_document_validator.py b/tests/spdx/validation/test_document_validator.py index 41733db9a..d0c021bc7 100644 --- a/tests/spdx/validation/test_document_validator.py +++ b/tests/spdx/validation/test_document_validator.py @@ -6,12 +6,12 @@ import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.document import CreationInfo, Document -from spdx.model.relationship import Relationship, RelationshipType -from spdx.parser.parse_anything import parse_file -from spdx.validation.document_validator import validate_full_spdx_document -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.document import CreationInfo, Document +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.parser.parse_anything import parse_file +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import creation_info_fixture, document_fixture, file_fixture, package_fixture, snippet_fixture diff --git a/tests/spdx/validation/test_external_document_ref_validator.py b/tests/spdx/validation/test_external_document_ref_validator.py index 2e31beeb3..ce67b6d4d 100644 --- a/tests/spdx/validation/test_external_document_ref_validator.py +++ b/tests/spdx/validation/test_external_document_ref_validator.py @@ -4,8 +4,8 @@ from typing import List -from spdx.validation.external_document_ref_validator import validate_external_document_ref -from spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.validation.external_document_ref_validator import validate_external_document_ref +from spdx_tools.spdx.validation.validation_message import ValidationMessage from tests.spdx.fixtures import external_document_ref_fixture diff --git a/tests/spdx/validation/test_external_package_ref_validator.py b/tests/spdx/validation/test_external_package_ref_validator.py index 644496ffa..16d41f1ae 100644 --- a/tests/spdx/validation/test_external_package_ref_validator.py +++ b/tests/spdx/validation/test_external_package_ref_validator.py @@ -6,8 +6,8 @@ import pytest -from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory -from spdx.validation.external_package_ref_validator import ( +from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory +from spdx_tools.spdx.validation.external_package_ref_validator import ( BOWER_REGEX, CPE22TYPE_REGEX, CPE23TYPE_REGEX, @@ -19,7 +19,7 @@ SWH_REGEX, validate_external_package_ref, ) -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage @pytest.mark.parametrize( diff --git a/tests/spdx/validation/test_extracted_licensing_info_validator.py b/tests/spdx/validation/test_extracted_licensing_info_validator.py index f0057fbf3..911bea71c 100644 --- a/tests/spdx/validation/test_extracted_licensing_info_validator.py +++ b/tests/spdx/validation/test_extracted_licensing_info_validator.py @@ -6,8 +6,8 @@ import pytest -from spdx.validation.extracted_licensing_info_validator import validate_extracted_licensing_info -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.validation.extracted_licensing_info_validator import validate_extracted_licensing_info +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import extracted_licensing_info_fixture diff --git a/tests/spdx/validation/test_file_validator.py b/tests/spdx/validation/test_file_validator.py index 954b0285a..2c26632a6 100644 --- a/tests/spdx/validation/test_file_validator.py +++ b/tests/spdx/validation/test_file_validator.py @@ -7,9 +7,9 @@ import pytest -from spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx.validation.file_validator import validate_file, validate_file_within_document -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.validation.file_validator import validate_file, validate_file_within_document +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import document_fixture, file_fixture diff --git a/tests/spdx/validation/test_license_expression_validator.py b/tests/spdx/validation/test_license_expression_validator.py index 071d49d59..2b2dabed6 100644 --- a/tests/spdx/validation/test_license_expression_validator.py +++ b/tests/spdx/validation/test_license_expression_validator.py @@ -8,11 +8,14 @@ import pytest from license_expression import LicenseExpression, get_spdx_licensing -from spdx.model.document import Document -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.validation.license_expression_validator import validate_license_expression, validate_license_expressions -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.validation.license_expression_validator import ( + validate_license_expression, + validate_license_expressions, +) +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import document_fixture, extracted_licensing_info_fixture FIXTURE_LICENSE_ID = extracted_licensing_info_fixture().license_id diff --git a/tests/spdx/validation/test_package_validator.py b/tests/spdx/validation/test_package_validator.py index 02f4c3942..335c744b9 100644 --- a/tests/spdx/validation/test_package_validator.py +++ b/tests/spdx/validation/test_package_validator.py @@ -8,12 +8,12 @@ import pytest from license_expression import Licensing -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.validation.package_validator import validate_package, validate_package_within_document -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.validation.package_validator import validate_package, validate_package_within_document +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture, package_verification_code_fixture diff --git a/tests/spdx/validation/test_package_verification_code_validator.py b/tests/spdx/validation/test_package_verification_code_validator.py index a19415b14..948904ef7 100644 --- a/tests/spdx/validation/test_package_verification_code_validator.py +++ b/tests/spdx/validation/test_package_verification_code_validator.py @@ -4,9 +4,9 @@ import pytest -from spdx.model.package import PackageVerificationCode -from spdx.validation.package_verification_code_validator import validate_verification_code -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.model.package import PackageVerificationCode +from spdx_tools.spdx.validation.package_verification_code_validator import validate_verification_code +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage def test_valid_package_verification_code(): diff --git a/tests/spdx/validation/test_relationship_validator.py b/tests/spdx/validation/test_relationship_validator.py index 3b68df0c5..b72bc0a82 100644 --- a/tests/spdx/validation/test_relationship_validator.py +++ b/tests/spdx/validation/test_relationship_validator.py @@ -6,13 +6,13 @@ import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.document import Document -from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.validation.relationship_validator import validate_relationship -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.validation.relationship_validator import validate_relationship +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import document_fixture, relationship_fixture diff --git a/tests/spdx/validation/test_snippet_validator.py b/tests/spdx/validation/test_snippet_validator.py index b13f6f011..8b8d2af4b 100644 --- a/tests/spdx/validation/test_snippet_validator.py +++ b/tests/spdx/validation/test_snippet_validator.py @@ -7,8 +7,8 @@ import pytest -from spdx.validation.snippet_validator import validate_snippet, validate_snippet_within_document -from spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage +from spdx_tools.spdx.validation.snippet_validator import validate_snippet, validate_snippet_within_document +from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import document_fixture, snippet_fixture diff --git a/tests/spdx/validation/test_spdx_id_validators.py b/tests/spdx/validation/test_spdx_id_validators.py index 1a36f0b99..8cc2d3b11 100644 --- a/tests/spdx/validation/test_spdx_id_validators.py +++ b/tests/spdx/validation/test_spdx_id_validators.py @@ -5,8 +5,8 @@ import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.validation.spdx_id_validators import ( +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.validation.spdx_id_validators import ( get_list_of_all_spdx_ids, is_external_doc_ref_present_in_document, is_spdx_id_present_in_document, diff --git a/tests/spdx/validation/test_uri_validators.py b/tests/spdx/validation/test_uri_validators.py index 3aaf75475..ffe30084c 100644 --- a/tests/spdx/validation/test_uri_validators.py +++ b/tests/spdx/validation/test_uri_validators.py @@ -4,7 +4,7 @@ import pytest -from spdx.validation.uri_validators import validate_download_location, validate_uri, validate_url +from spdx_tools.spdx.validation.uri_validators import validate_download_location, validate_uri, validate_url @pytest.mark.parametrize( diff --git a/tests/spdx/writer/json/test_json_writer.py b/tests/spdx/writer/json/test_json_writer.py index ee6013275..523b11ea8 100644 --- a/tests/spdx/writer/json/test_json_writer.py +++ b/tests/spdx/writer/json/test_json_writer.py @@ -6,7 +6,7 @@ import pytest -from spdx.writer.json.json_writer import write_document_to_file +from spdx_tools.spdx.writer.json.json_writer import write_document_to_file from tests.spdx.fixtures import document_fixture diff --git a/tests/spdx/writer/rdf/test_annotation_writer.py b/tests/spdx/writer/rdf/test_annotation_writer.py index fc0238761..62f8b13a1 100644 --- a/tests/spdx/writer/rdf/test_annotation_writer.py +++ b/tests/spdx/writer/rdf/test_annotation_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, Graph, Literal, URIRef -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.writer.rdf.annotation_writer import add_annotation_to_graph +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.annotation_writer import add_annotation_to_graph from tests.spdx.fixtures import annotation_fixture diff --git a/tests/spdx/writer/rdf/test_checksum_writer.py b/tests/spdx/writer/rdf/test_checksum_writer.py index b768cf19c..28b4012be 100644 --- a/tests/spdx/writer/rdf/test_checksum_writer.py +++ b/tests/spdx/writer/rdf/test_checksum_writer.py @@ -4,9 +4,9 @@ import pytest from rdflib import RDF, Graph, Literal, URIRef -from spdx.model.checksum import ChecksumAlgorithm -from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.writer.rdf.checksum_writer import add_checksum_to_graph, algorithm_to_rdf_string +from spdx_tools.spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph, algorithm_to_rdf_string from tests.spdx.fixtures import checksum_fixture diff --git a/tests/spdx/writer/rdf/test_creation_info_writer.py b/tests/spdx/writer/rdf/test_creation_info_writer.py index 2ad508e34..4a0656e70 100644 --- a/tests/spdx/writer/rdf/test_creation_info_writer.py +++ b/tests/spdx/writer/rdf/test_creation_info_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, Graph, Literal, URIRef -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE -from spdx.writer.rdf.creation_info_writer import add_creation_info_to_graph +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.creation_info_writer import add_creation_info_to_graph from tests.spdx.fixtures import creation_info_fixture diff --git a/tests/spdx/writer/rdf/test_external_document_ref_writer.py b/tests/spdx/writer/rdf/test_external_document_ref_writer.py index 718de8483..9197b39d9 100644 --- a/tests/spdx/writer/rdf/test_external_document_ref_writer.py +++ b/tests/spdx/writer/rdf/test_external_document_ref_writer.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, Graph, URIRef -from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.writer.rdf.external_document_ref_writer import add_external_document_ref_to_graph +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.external_document_ref_writer import add_external_document_ref_to_graph from tests.spdx.fixtures import external_document_ref_fixture diff --git a/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py b/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py index c763bcec4..b8fa1f871 100644 --- a/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py +++ b/tests/spdx/writer/rdf/test_extracted_licensing_info_writer.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, Graph, Literal, URIRef -from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.writer.rdf.extracted_licensing_info_writer import add_extracted_licensing_info_to_graph +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.extracted_licensing_info_writer import add_extracted_licensing_info_to_graph from tests.spdx.fixtures import extracted_licensing_info_fixture diff --git a/tests/spdx/writer/rdf/test_file_writer.py b/tests/spdx/writer/rdf/test_file_writer.py index bb05e8656..bcba0fd4e 100644 --- a/tests/spdx/writer/rdf/test_file_writer.py +++ b/tests/spdx/writer/rdf/test_file_writer.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, Graph, Literal, URIRef -from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE -from spdx.writer.rdf.file_writer import add_file_to_graph +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.file_writer import add_file_to_graph from tests.spdx.fixtures import file_fixture diff --git a/tests/spdx/writer/rdf/test_license_expression_writer.py b/tests/spdx/writer/rdf/test_license_expression_writer.py index ff9b7bd71..d77d08ffb 100644 --- a/tests/spdx/writer/rdf/test_license_expression_writer.py +++ b/tests/spdx/writer/rdf/test_license_expression_writer.py @@ -5,8 +5,8 @@ from license_expression import get_spdx_licensing from rdflib import RDF, Graph, Literal, URIRef -from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.writer.rdf.license_expression_writer import add_license_expression_to_graph +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_to_graph def test_add_conjunctive_license_set_to_graph(): diff --git a/tests/spdx/writer/rdf/test_package_writer.py b/tests/spdx/writer/rdf/test_package_writer.py index 856b38906..3b5fde09b 100644 --- a/tests/spdx/writer/rdf/test_package_writer.py +++ b/tests/spdx/writer/rdf/test_package_writer.py @@ -4,10 +4,10 @@ import pytest from rdflib import DOAP, RDF, RDFS, XSD, Graph, Literal, URIRef -from spdx.datetime_conversions import datetime_to_iso_string -from spdx.model.package import ExternalPackageRefCategory -from spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE -from spdx.writer.rdf.package_writer import ( +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx.model.package import ExternalPackageRefCategory +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.package_writer import ( add_external_package_ref_to_graph, add_package_to_graph, add_package_verification_code_to_graph, diff --git a/tests/spdx/writer/rdf/test_rdf_writer.py b/tests/spdx/writer/rdf/test_rdf_writer.py index 45cc7dc45..8b19eef0d 100644 --- a/tests/spdx/writer/rdf/test_rdf_writer.py +++ b/tests/spdx/writer/rdf/test_rdf_writer.py @@ -5,8 +5,8 @@ import pytest -from spdx.model.document import Document -from spdx.writer.rdf.rdf_writer import write_document_to_file +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.writer.rdf.rdf_writer import write_document_to_file from tests.spdx.fixtures import document_fixture diff --git a/tests/spdx/writer/rdf/test_relationship_writer.py b/tests/spdx/writer/rdf/test_relationship_writer.py index 9257976e4..3019d9ec5 100644 --- a/tests/spdx/writer/rdf/test_relationship_writer.py +++ b/tests/spdx/writer/rdf/test_relationship_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, Literal, URIRef -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.rdfschema.namespace import SPDX_NAMESPACE -from spdx.writer.rdf.relationship_writer import add_relationship_to_graph +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.relationship_writer import add_relationship_to_graph from tests.spdx.fixtures import relationship_fixture diff --git a/tests/spdx/writer/rdf/test_snippet_writer.py b/tests/spdx/writer/rdf/test_snippet_writer.py index 1fad0e46e..6bc121396 100644 --- a/tests/spdx/writer/rdf/test_snippet_writer.py +++ b/tests/spdx/writer/rdf/test_snippet_writer.py @@ -4,8 +4,8 @@ import pytest from rdflib import RDF, RDFS, Graph, Literal, URIRef -from spdx.rdfschema.namespace import LICENSE_NAMESPACE, POINTER_NAMESPACE, SPDX_NAMESPACE -from spdx.writer.rdf.snippet_writer import add_range_to_graph, add_snippet_to_graph +from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, POINTER_NAMESPACE, SPDX_NAMESPACE +from spdx_tools.spdx.writer.rdf.snippet_writer import add_range_to_graph, add_snippet_to_graph from tests.spdx.fixtures import snippet_fixture diff --git a/tests/spdx/writer/rdf/test_writer_utils.py b/tests/spdx/writer/rdf/test_writer_utils.py index f26f56eee..150dd8405 100644 --- a/tests/spdx/writer/rdf/test_writer_utils.py +++ b/tests/spdx/writer/rdf/test_writer_utils.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id +from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id @pytest.mark.parametrize( diff --git a/tests/spdx/writer/tagvalue/test_annotation_writer.py b/tests/spdx/writer/tagvalue/test_annotation_writer.py index 5b36f5c32..974f01ec4 100644 --- a/tests/spdx/writer/tagvalue/test_annotation_writer.py +++ b/tests/spdx/writer/tagvalue/test_annotation_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from unittest.mock import MagicMock, call, mock_open, patch -from spdx.writer.tagvalue.annotation_writer import write_annotation +from spdx_tools.spdx.writer.tagvalue.annotation_writer import write_annotation from tests.spdx.fixtures import annotation_fixture diff --git a/tests/spdx/writer/tagvalue/test_checksum_writer.py b/tests/spdx/writer/tagvalue/test_checksum_writer.py index 535b56088..2208fc207 100644 --- a/tests/spdx/writer/tagvalue/test_checksum_writer.py +++ b/tests/spdx/writer/tagvalue/test_checksum_writer.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx.model.checksum import ChecksumAlgorithm -from spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value +from spdx_tools.spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value from tests.spdx.fixtures import checksum_fixture diff --git a/tests/spdx/writer/tagvalue/test_creation_info_writer.py b/tests/spdx/writer/tagvalue/test_creation_info_writer.py index be5d023d1..a1a6a982b 100644 --- a/tests/spdx/writer/tagvalue/test_creation_info_writer.py +++ b/tests/spdx/writer/tagvalue/test_creation_info_writer.py @@ -6,9 +6,9 @@ import pytest -from spdx.constants import DOCUMENT_SPDX_ID -from spdx.model.document import CreationInfo -from spdx.writer.tagvalue.creation_info_writer import write_creation_info +from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID +from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.writer.tagvalue.creation_info_writer import write_creation_info from tests.spdx.fixtures import actor_fixture, creation_info_fixture diff --git a/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py b/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py index 55354835a..a0c70440a 100644 --- a/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py +++ b/tests/spdx/writer/tagvalue/test_extracted_licensing_info_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from unittest.mock import MagicMock, call, mock_open, patch -from spdx.writer.tagvalue.extracted_licensing_info_writer import write_extracted_licensing_info +from spdx_tools.spdx.writer.tagvalue.extracted_licensing_info_writer import write_extracted_licensing_info from tests.spdx.fixtures import extracted_licensing_info_fixture diff --git a/tests/spdx/writer/tagvalue/test_file_writer.py b/tests/spdx/writer/tagvalue/test_file_writer.py index 27eb7ef49..c25998089 100644 --- a/tests/spdx/writer/tagvalue/test_file_writer.py +++ b/tests/spdx/writer/tagvalue/test_file_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from unittest.mock import MagicMock, call, mock_open, patch -from spdx.writer.tagvalue.file_writer import write_file +from spdx_tools.spdx.writer.tagvalue.file_writer import write_file from tests.spdx.fixtures import file_fixture diff --git a/tests/spdx/writer/tagvalue/test_package_writer.py b/tests/spdx/writer/tagvalue/test_package_writer.py index 958ff9931..26c8f9a61 100644 --- a/tests/spdx/writer/tagvalue/test_package_writer.py +++ b/tests/spdx/writer/tagvalue/test_package_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from unittest.mock import MagicMock, call, mock_open, patch -from spdx.writer.tagvalue.package_writer import write_package +from spdx_tools.spdx.writer.tagvalue.package_writer import write_package from tests.spdx.fixtures import package_fixture diff --git a/tests/spdx/writer/tagvalue/test_relationship_writer.py b/tests/spdx/writer/tagvalue/test_relationship_writer.py index 2d0a129f1..8ff940809 100644 --- a/tests/spdx/writer/tagvalue/test_relationship_writer.py +++ b/tests/spdx/writer/tagvalue/test_relationship_writer.py @@ -5,9 +5,9 @@ import pytest -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone -from spdx.writer.tagvalue.relationship_writer import write_relationship +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.writer.tagvalue.relationship_writer import write_relationship from tests.spdx.fixtures import relationship_fixture diff --git a/tests/spdx/writer/tagvalue/test_snippet_writer.py b/tests/spdx/writer/tagvalue/test_snippet_writer.py index 39e661c87..4015908c1 100644 --- a/tests/spdx/writer/tagvalue/test_snippet_writer.py +++ b/tests/spdx/writer/tagvalue/test_snippet_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from unittest.mock import MagicMock, call, mock_open, patch -from spdx.writer.tagvalue.snippet_writer import write_snippet +from spdx_tools.spdx.writer.tagvalue.snippet_writer import write_snippet from tests.spdx.fixtures import snippet_fixture diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py index 6aeda9030..ad2ccd6ef 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py @@ -7,12 +7,12 @@ import pytest -from spdx.model.file import File -from spdx.model.package import Package -from spdx.model.relationship import Relationship, RelationshipType -from spdx.model.snippet import Snippet -from spdx.parser.tagvalue import tagvalue_parser -from spdx.writer.tagvalue.tagvalue_writer import write_document, write_document_to_file +from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.model.package import Package +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.parser.tagvalue import tagvalue_parser +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer import write_document, write_document_to_file from tests.spdx.fixtures import checksum_fixture, document_fixture diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py index 4d2446213..b7c884dc2 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py @@ -5,10 +5,10 @@ import pytest -from spdx.model.actor import ActorType -from spdx.model.relationship import RelationshipType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import scan_relationships, write_actor +from spdx_tools.spdx.model.actor import ActorType +from spdx_tools.spdx.model.relationship import RelationshipType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import scan_relationships, write_actor from tests.spdx.fixtures import actor_fixture, file_fixture, package_fixture, relationship_fixture From 8d7d7b7d38ba5c50ddaa3d0023c620566dfc4e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 19 Apr 2023 10:54:36 +0200 Subject: [PATCH 062/354] [issue-593] expose model classes in model package init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .flake8 | 2 +- README.md | 10 +++--- pyproject.toml | 1 + src/spdx_tools/spdx/clitools/pyspdxtools.py | 2 +- src/spdx_tools/spdx/document_utils.py | 5 +-- src/spdx_tools/spdx/graph_generation.py | 7 ++-- .../spdx/jsonschema/annotation_converter.py | 3 +- .../spdx/jsonschema/checksum_converter.py | 3 +- src/spdx_tools/spdx/jsonschema/converter.py | 2 +- .../jsonschema/creation_info_converter.py | 2 +- .../spdx/jsonschema/document_converter.py | 2 +- .../external_document_ref_converter.py | 3 +- .../external_package_ref_converter.py | 3 +- .../extracted_licensing_info_converter.py | 3 +- .../spdx/jsonschema/file_converter.py | 3 +- .../spdx/jsonschema/package_converter.py | 4 +-- .../package_verification_code_converter.py | 3 +- .../spdx/jsonschema/relationship_converter.py | 3 +- .../spdx/jsonschema/snippet_converter.py | 3 +- src/spdx_tools/spdx/model/__init__.py | 19 +++++++++++ src/spdx_tools/spdx/model/annotation.py | 2 +- src/spdx_tools/spdx/model/document.py | 20 ++++++------ .../spdx/model/external_document_ref.py | 2 +- .../spdx/model/extracted_licensing_info.py | 2 +- src/spdx_tools/spdx/model/file.py | 4 +-- src/spdx_tools/spdx/model/package.py | 5 +-- src/spdx_tools/spdx/model/relationship.py | 3 +- .../spdx/model/relationship_filters.py | 4 +-- src/spdx_tools/spdx/model/snippet.py | 3 +- src/spdx_tools/spdx/parser/actor_parser.py | 2 +- .../spdx/parser/json/json_parser.py | 2 +- .../parser/jsonlikedict/annotation_parser.py | 3 +- .../parser/jsonlikedict/checksum_parser.py | 2 +- .../jsonlikedict/creation_info_parser.py | 6 +--- .../jsonlikedict/dict_parsing_functions.py | 3 +- .../extracted_licensing_info_parser.py | 3 +- .../spdx/parser/jsonlikedict/file_parser.py | 5 +-- .../jsonlikedict/json_like_dict_parser.py | 2 +- .../jsonlikedict/license_expression_parser.py | 3 +- .../parser/jsonlikedict/package_parser.py | 8 ++--- .../jsonlikedict/relationship_parser.py | 2 +- .../parser/jsonlikedict/snippet_parser.py | 4 +-- .../spdx/parser/rdf/annotation_parser.py | 2 +- .../spdx/parser/rdf/checksum_parser.py | 2 +- .../spdx/parser/rdf/creation_info_parser.py | 4 +-- .../rdf/extracted_licensing_info_parser.py | 2 +- src/spdx_tools/spdx/parser/rdf/file_parser.py | 2 +- .../parser/rdf/graph_parsing_functions.py | 5 +-- .../spdx/parser/rdf/package_parser.py | 2 +- src/spdx_tools/spdx/parser/rdf/rdf_parser.py | 3 +- .../spdx/parser/rdf/relationship_parser.py | 2 +- .../spdx/parser/rdf/snippet_parser.py | 2 +- .../spdx/parser/tagvalue/helper_methods.py | 17 ++++++---- src/spdx_tools/spdx/parser/tagvalue/parser.py | 26 ++++++++------- .../spdx/parser/tagvalue/tagvalue_parser.py | 2 +- src/spdx_tools/spdx/parser/xml/xml_parser.py | 2 +- .../spdx/parser/yaml/yaml_parser.py | 2 +- .../spdx/validation/actor_validator.py | 2 +- .../spdx/validation/annotation_validator.py | 3 +- .../spdx/validation/checksum_validator.py | 2 +- .../validation/creation_info_validator.py | 2 +- .../spdx/validation/document_validator.py | 3 +- .../external_document_ref_validator.py | 2 +- .../external_package_ref_validator.py | 7 ++-- .../extracted_licensing_info_validator.py | 2 +- .../spdx/validation/file_validator.py | 4 +-- .../license_expression_validator.py | 4 +-- .../spdx/validation/package_validator.py | 4 +-- .../package_verification_code_validator.py | 2 +- .../spdx/validation/relationship_validator.py | 5 +-- .../spdx/validation/snippet_validator.py | 3 +- .../spdx/validation/spdx_id_validators.py | 3 +- .../spdx/writer/json/json_writer.py | 2 +- .../spdx/writer/rdf/annotation_writer.py | 2 +- .../spdx/writer/rdf/checksum_writer.py | 2 +- .../spdx/writer/rdf/creation_info_writer.py | 2 +- .../rdf/external_document_ref_writer.py | 2 +- .../rdf/extracted_licensing_info_writer.py | 2 +- src/spdx_tools/spdx/writer/rdf/file_writer.py | 2 +- .../writer/rdf/license_expression_writer.py | 3 +- .../spdx/writer/rdf/package_writer.py | 8 ++--- src/spdx_tools/spdx/writer/rdf/rdf_writer.py | 2 +- .../spdx/writer/rdf/relationship_writer.py | 4 +-- .../spdx/writer/rdf/snippet_writer.py | 2 +- .../spdx/writer/rdf/writer_utils.py | 3 +- .../spdx/writer/tagvalue/annotation_writer.py | 2 +- .../spdx/writer/tagvalue/checksum_writer.py | 2 +- .../writer/tagvalue/creation_info_writer.py | 2 +- .../extracted_licensing_info_writer.py | 2 +- .../spdx/writer/tagvalue/file_writer.py | 2 +- .../spdx/writer/tagvalue/package_writer.py | 2 +- .../writer/tagvalue/relationship_writer.py | 2 +- .../spdx/writer/tagvalue/snippet_writer.py | 2 +- .../spdx/writer/tagvalue/tagvalue_writer.py | 2 +- .../tagvalue_writer_helper_functions.py | 17 ++++++---- src/spdx_tools/spdx/writer/write_anything.py | 2 +- src/spdx_tools/spdx/writer/xml/xml_writer.py | 2 +- .../spdx/writer/yaml/yaml_writer.py | 2 +- tests/spdx/fixtures.py | 32 +++++++++++-------- .../jsonschema/test_annotation_converter.py | 3 +- .../jsonschema/test_checksum_converter.py | 2 +- tests/spdx/jsonschema/test_converter.py | 3 +- .../test_creation_info_converter.py | 4 +-- .../jsonschema/test_document_converter.py | 15 ++++++--- .../test_external_document_ref_converter.py | 3 +- .../test_external_package_ref_converter.py | 2 +- ...test_extracted_licensing_info_converter.py | 4 +-- tests/spdx/jsonschema/test_file_converter.py | 22 +++++++++---- .../spdx/jsonschema/test_package_converter.py | 23 +++++++++---- ...est_package_verification_code_converter.py | 2 +- .../jsonschema/test_relationship_converter.py | 6 ++-- .../spdx/jsonschema/test_snippet_converter.py | 18 +++++++---- tests/spdx/model/test_actor.py | 2 +- tests/spdx/model/test_annotation.py | 14 ++++---- tests/spdx/model/test_checksum.py | 2 +- tests/spdx/model/test_creation_info.py | 27 ++++++++-------- tests/spdx/model/test_document.py | 30 ++++++++--------- .../spdx/model/test_external_document_ref.py | 8 ++--- .../model/test_external_package_reference.py | 2 +- .../model/test_extracted_licensing_info.py | 2 +- tests/spdx/model/test_file.py | 31 ++++++++---------- tests/spdx/model/test_package.py | 13 +++----- .../model/test_package_verification_code.py | 2 +- tests/spdx/model/test_relationship.py | 3 +- tests/spdx/model/test_snippet.py | 4 +-- tests/spdx/model/test_version.py | 2 +- .../all_formats/test_parse_from_file.py | 2 +- .../jsonlikedict/test_annotation_parser.py | 3 +- .../jsonlikedict/test_checksum_parser.py | 2 +- .../jsonlikedict/test_creation_info_parser.py | 5 +-- .../test_dict_parsing_functions.py | 3 +- .../parser/jsonlikedict/test_file_parser.py | 5 +-- .../test_license_expression_parser.py | 3 +- .../jsonlikedict/test_package_parser.py | 12 ++++--- .../jsonlikedict/test_relationship_parser.py | 3 +- .../jsonlikedict/test_snippet_parser.py | 3 +- .../spdx/parser/rdf/test_annotation_parser.py | 3 +- tests/spdx/parser/rdf/test_checksum_parser.py | 2 +- .../parser/rdf/test_creation_info_parser.py | 4 +-- tests/spdx/parser/rdf/test_file_parser.py | 4 +-- tests/spdx/parser/rdf/test_package_parser.py | 14 +++++--- .../parser/rdf/test_relationship_parser.py | 2 +- tests/spdx/parser/rdf/test_snippet_parser.py | 2 +- .../parser/tagvalue/test_annotation_parser.py | 2 +- .../tagvalue/test_creation_info_parser.py | 5 +-- .../spdx/parser/tagvalue/test_file_parser.py | 3 +- .../parser/tagvalue/test_helper_methods.py | 2 +- .../parser/tagvalue/test_package_parser.py | 3 +- .../tagvalue/test_relationship_parser.py | 4 +-- .../parser/tagvalue/test_snippet_parser.py | 2 +- .../parser/tagvalue/test_tag_value_parser.py | 2 +- tests/spdx/test_actor_parser.py | 2 +- tests/spdx/test_document_utils.py | 4 +-- tests/spdx/test_graph_generation.py | 3 +- tests/spdx/validation/test_actor_validator.py | 2 +- .../validation/test_annotation_validator.py | 3 +- .../validation/test_checksum_validator.py | 2 +- .../validation/test_document_validator.py | 3 +- .../test_external_package_ref_validator.py | 2 +- tests/spdx/validation/test_file_validator.py | 2 +- .../test_license_expression_validator.py | 4 +-- .../spdx/validation/test_package_validator.py | 4 +-- ...est_package_verification_code_validator.py | 2 +- .../validation/test_relationship_validator.py | 5 +-- tests/spdx/writer/rdf/test_checksum_writer.py | 2 +- tests/spdx/writer/rdf/test_package_writer.py | 2 +- tests/spdx/writer/rdf/test_rdf_writer.py | 2 +- .../writer/tagvalue/test_checksum_writer.py | 2 +- .../tagvalue/test_creation_info_writer.py | 2 +- .../tagvalue/test_relationship_writer.py | 3 +- .../writer/tagvalue/test_tagvalue_writer.py | 5 +-- .../test_tagvalue_writer_helper_functions.py | 4 +-- 172 files changed, 381 insertions(+), 428 deletions(-) diff --git a/.flake8 b/.flake8 index 3ca504408..9402046ea 100644 --- a/.flake8 +++ b/.flake8 @@ -1,4 +1,4 @@ [flake8] max-line-length = 119 -exclude = src/spdx_tools/spdx/parser/tagvalue/parsetab.py +exclude = src/spdx_tools/spdx/parser/tagvalue/parsetab.py, src/spdx_tools/spdx/model/__init__.py extend-ignore = E203 diff --git a/README.md b/README.md index 9c82d6ff9..e5c345b26 100644 --- a/README.md +++ b/README.md @@ -94,13 +94,13 @@ instead of `bin`. ## Library usage 1. **DATA MODEL** - * The `src.spdx.model` package constitutes the internal SPDX v2.3 data model (v2.2 is a simply a subset of this). + * The `spdx_tools.spdx.model` package constitutes the internal SPDX v2.3 data model (v2.2 is a simply a subset of this). All relevant classes for SPDX document creation are exposed in the [__init__.py](src%2Fspdx_tools%2Fspdx%2Fmodel%2F__init__.py). * SPDX objects are implemented via `@dataclass_with_properties`, a custom extension of `@dataclass`. * Each class starts with a list of its properties and their possible types. When no default value is provided, the property is mandatory and must be set during initialization. * Using the type hints, type checking is enforced when initializing a new instance or setting/getting a property on an instance (wrong types will raise `ConstructorTypeError` or `TypeError`, respectively). This makes it easy to catch invalid properties early and only construct valid documents. * Note: in-place manipulations like `list.append(item)` will circumvent the type checking (a `TypeError` will still be raised when reading `list` again). We recommend using `list = list + [item]` instead. - * The main entry point of an SPDX document is the `Document` class, which links to all other classes. + * The main entry point of an SPDX document is the `Document` class from the [document.py](src%2Fspdx_tools%2Fspdx%2Fmodel%2Fdocument.py) module, which links to all other classes. * For license handling, the [license_expression](https://github.com/nexB/license-expression) library is used. * Note on `documentDescribes` and `hasFiles`: These fields will be converted to relationships in the internal data model. As they are deprecated, these fields will not be written in the output. 2. **PARSING** @@ -123,9 +123,9 @@ import logging from license_expression import get_spdx_licensing -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.file import File, FileType -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model import File, FileType +from spdx_tools.spdx.model import Relationship, RelationshipType from spdx_tools.spdx.parser.parse_anything import parse_file from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document from spdx_tools.spdx.writer.write_anything import write_file diff --git a/pyproject.toml b/pyproject.toml index c9756834b..7ec03780b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,3 +61,4 @@ include = "(^/src/.*.py|^/tests/.*.py)" [tool.isort] profile = "black" line_length = 119 +skip = ["__init__.py"] diff --git a/src/spdx_tools/spdx/clitools/pyspdxtools.py b/src/spdx_tools/spdx/clitools/pyspdxtools.py index 1983106d6..556033aee 100644 --- a/src/spdx_tools/spdx/clitools/pyspdxtools.py +++ b/src/spdx_tools/spdx/clitools/pyspdxtools.py @@ -19,7 +19,7 @@ import click from spdx_tools.spdx.graph_generation import export_graph_from_document -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.parse_anything import parse_file from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document diff --git a/src/spdx_tools/spdx/document_utils.py b/src/spdx_tools/spdx/document_utils.py index 0afc01702..eb3612ab6 100644 --- a/src/spdx_tools/spdx/document_utils.py +++ b/src/spdx_tools/spdx/document_utils.py @@ -4,10 +4,7 @@ from copy import deepcopy from typing import Any, Dict, List, Union -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.file import File -from spdx_tools.spdx.model.package import Package -from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model import Document, File, Package, Snippet def get_contained_spdx_element_ids(document: Document) -> List[str]: diff --git a/src/spdx_tools/spdx/graph_generation.py b/src/spdx_tools/spdx/graph_generation.py index 6052af995..1ef70a1c8 100644 --- a/src/spdx_tools/spdx/graph_generation.py +++ b/src/spdx_tools/spdx/graph_generation.py @@ -3,17 +3,14 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Dict, List, Union -from spdx_tools.spdx.model.file import File -from spdx_tools.spdx.model.package import Package -from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model import File, Package, Snippet try: from networkx import DiGraph except ImportError: DiGraph = None from spdx_tools.spdx.document_utils import get_contained_spdx_elements -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.relationship import Relationship +from spdx_tools.spdx.model import Document, Relationship def export_graph_from_document(document: Document, file_name: str) -> None: diff --git a/src/spdx_tools/spdx/jsonschema/annotation_converter.py b/src/spdx_tools/spdx/jsonschema/annotation_converter.py index a345353e4..7fbedf51f 100644 --- a/src/spdx_tools/spdx/jsonschema/annotation_converter.py +++ b/src/spdx_tools/spdx/jsonschema/annotation_converter.py @@ -7,8 +7,7 @@ from spdx_tools.spdx.jsonschema.annotation_properties import AnnotationProperty from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.json_property import JsonProperty -from spdx_tools.spdx.model.annotation import Annotation -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Annotation, Document class AnnotationConverter(TypedConverter[Annotation]): diff --git a/src/spdx_tools/spdx/jsonschema/checksum_converter.py b/src/spdx_tools/spdx/jsonschema/checksum_converter.py index 536e65974..a1d2bb9fd 100644 --- a/src/spdx_tools/spdx/jsonschema/checksum_converter.py +++ b/src/spdx_tools/spdx/jsonschema/checksum_converter.py @@ -6,8 +6,7 @@ from spdx_tools.spdx.jsonschema.checksum_properties import ChecksumProperty from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.json_property import JsonProperty -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, Document class ChecksumConverter(TypedConverter[Checksum]): diff --git a/src/spdx_tools/spdx/jsonschema/converter.py b/src/spdx_tools/spdx/jsonschema/converter.py index a613e3f3c..4ec479623 100644 --- a/src/spdx_tools/spdx/jsonschema/converter.py +++ b/src/spdx_tools/spdx/jsonschema/converter.py @@ -6,7 +6,7 @@ from spdx_tools.spdx.casing_tools import snake_case_to_camel_case from spdx_tools.spdx.jsonschema.json_property import JsonProperty -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document MISSING_IMPLEMENTATION_MESSAGE = "Must be implemented" diff --git a/src/spdx_tools/spdx/jsonschema/creation_info_converter.py b/src/spdx_tools/spdx/jsonschema/creation_info_converter.py index 9d8832a03..6e84bfe19 100644 --- a/src/spdx_tools/spdx/jsonschema/creation_info_converter.py +++ b/src/spdx_tools/spdx/jsonschema/creation_info_converter.py @@ -8,7 +8,7 @@ from spdx_tools.spdx.jsonschema.creation_info_properties import CreationInfoProperty from spdx_tools.spdx.jsonschema.json_property import JsonProperty from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present -from spdx_tools.spdx.model.document import CreationInfo, Document +from spdx_tools.spdx.model import CreationInfo, Document class CreationInfoConverter(TypedConverter[CreationInfo]): diff --git a/src/spdx_tools/spdx/jsonschema/document_converter.py b/src/spdx_tools/spdx/jsonschema/document_converter.py index 1ccf74fd4..4d001c75c 100644 --- a/src/spdx_tools/spdx/jsonschema/document_converter.py +++ b/src/spdx_tools/spdx/jsonschema/document_converter.py @@ -15,7 +15,7 @@ from spdx_tools.spdx.jsonschema.package_converter import PackageConverter from spdx_tools.spdx.jsonschema.relationship_converter import RelationshipConverter from spdx_tools.spdx.jsonschema.snippet_converter import SnippetConverter -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document class DocumentConverter(TypedConverter[Document]): diff --git a/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py b/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py index f9d483a9b..c2e803662 100644 --- a/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py +++ b/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py @@ -7,8 +7,7 @@ from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.external_document_ref_properties import ExternalDocumentRefProperty from spdx_tools.spdx.jsonschema.json_property import JsonProperty -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model import Document, ExternalDocumentRef class ExternalDocumentRefConverter(TypedConverter[ExternalDocumentRef]): diff --git a/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py b/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py index f6fec734e..36d528e26 100644 --- a/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py +++ b/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py @@ -6,8 +6,7 @@ from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.external_package_ref_properties import ExternalPackageRefProperty from spdx_tools.spdx.jsonschema.json_property import JsonProperty -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.package import ExternalPackageRef +from spdx_tools.spdx.model import Document, ExternalPackageRef class ExternalPackageRefConverter(TypedConverter[ExternalPackageRef]): diff --git a/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py b/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py index 6f49c2505..d7ada1c95 100644 --- a/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py +++ b/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py @@ -7,8 +7,7 @@ from spdx_tools.spdx.jsonschema.extracted_licensing_info_properties import ExtractedLicensingInfoProperty from spdx_tools.spdx.jsonschema.json_property import JsonProperty from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model import Document, ExtractedLicensingInfo class ExtractedLicensingInfoConverter(TypedConverter[ExtractedLicensingInfo]): diff --git a/src/spdx_tools/spdx/jsonschema/file_converter.py b/src/spdx_tools/spdx/jsonschema/file_converter.py index 6ce642110..20173f606 100644 --- a/src/spdx_tools/spdx/jsonschema/file_converter.py +++ b/src/spdx_tools/spdx/jsonschema/file_converter.py @@ -9,8 +9,7 @@ from spdx_tools.spdx.jsonschema.file_properties import FileProperty from spdx_tools.spdx.jsonschema.json_property import JsonProperty from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.model import Document, File class FileConverter(TypedConverter[File]): diff --git a/src/spdx_tools/spdx/jsonschema/package_converter.py b/src/spdx_tools/spdx/jsonschema/package_converter.py index 992eb649a..279eeb473 100644 --- a/src/spdx_tools/spdx/jsonschema/package_converter.py +++ b/src/spdx_tools/spdx/jsonschema/package_converter.py @@ -12,9 +12,7 @@ from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present from spdx_tools.spdx.jsonschema.package_properties import PackageProperty from spdx_tools.spdx.jsonschema.package_verification_code_converter import PackageVerificationCodeConverter -from spdx_tools.spdx.model.actor import Actor -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.package import Package +from spdx_tools.spdx.model import Actor, Document, Package class PackageConverter(TypedConverter[Package]): diff --git a/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py b/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py index f2a2f27e2..4076bb151 100644 --- a/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py +++ b/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py @@ -6,8 +6,7 @@ from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.json_property import JsonProperty from spdx_tools.spdx.jsonschema.package_verification_code_properties import PackageVerificationCodeProperty -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.package import PackageVerificationCode +from spdx_tools.spdx.model import Document, PackageVerificationCode class PackageVerificationCodeConverter(TypedConverter[PackageVerificationCode]): diff --git a/src/spdx_tools/spdx/jsonschema/relationship_converter.py b/src/spdx_tools/spdx/jsonschema/relationship_converter.py index e3be442b9..23b479e9e 100644 --- a/src/spdx_tools/spdx/jsonschema/relationship_converter.py +++ b/src/spdx_tools/spdx/jsonschema/relationship_converter.py @@ -6,8 +6,7 @@ from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.json_property import JsonProperty from spdx_tools.spdx.jsonschema.relationship_properties import RelationshipProperty -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.relationship import Relationship +from spdx_tools.spdx.model import Document, Relationship class RelationshipConverter(TypedConverter[Relationship]): diff --git a/src/spdx_tools/spdx/jsonschema/snippet_converter.py b/src/spdx_tools/spdx/jsonschema/snippet_converter.py index 1d74a9c4d..d0736a943 100644 --- a/src/spdx_tools/spdx/jsonschema/snippet_converter.py +++ b/src/spdx_tools/spdx/jsonschema/snippet_converter.py @@ -8,8 +8,7 @@ from spdx_tools.spdx.jsonschema.json_property import JsonProperty from spdx_tools.spdx.jsonschema.optional_utils import apply_if_present from spdx_tools.spdx.jsonschema.snippet_properties import SnippetProperty -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model import Document, Snippet class SnippetConverter(TypedConverter[Snippet]): diff --git a/src/spdx_tools/spdx/model/__init__.py b/src/spdx_tools/spdx/model/__init__.py index e69de29bb..cec8cfe19 100644 --- a/src/spdx_tools/spdx/model/__init__.py +++ b/src/spdx_tools/spdx/model/__init__.py @@ -0,0 +1,19 @@ +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model.file import File, FileType +from spdx_tools.spdx.model.package import ( + ExternalPackageRef, + ExternalPackageRefCategory, + Package, + PackagePurpose, + PackageVerificationCode, +) +from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model.document import CreationInfo, Document diff --git a/src/spdx_tools/spdx/model/annotation.py b/src/spdx_tools/spdx/model/annotation.py index d128e57a9..6ada0607b 100644 --- a/src/spdx_tools/spdx/model/annotation.py +++ b/src/spdx_tools/spdx/model/annotation.py @@ -6,7 +6,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx.model.actor import Actor +from spdx_tools.spdx.model import Actor class AnnotationType(Enum): diff --git a/src/spdx_tools/spdx/model/document.py b/src/spdx_tools/spdx/model/document.py index b6c7128b5..ecfddc6a1 100644 --- a/src/spdx_tools/spdx/model/document.py +++ b/src/spdx_tools/spdx/model/document.py @@ -7,15 +7,17 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx.model.actor import Actor -from spdx_tools.spdx.model.annotation import Annotation -from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx_tools.spdx.model.file import File -from spdx_tools.spdx.model.package import Package -from spdx_tools.spdx.model.relationship import Relationship -from spdx_tools.spdx.model.snippet import Snippet -from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.model import ( + Actor, + Annotation, + ExternalDocumentRef, + ExtractedLicensingInfo, + File, + Package, + Relationship, + Snippet, + Version, +) @dataclass_with_properties diff --git a/src/spdx_tools/spdx/model/external_document_ref.py b/src/spdx_tools/spdx/model/external_document_ref.py index 5d8233ba9..fbbaf4847 100644 --- a/src/spdx_tools/spdx/model/external_document_ref.py +++ b/src/spdx_tools/spdx/model/external_document_ref.py @@ -4,7 +4,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx.model.checksum import Checksum +from spdx_tools.spdx.model import Checksum @dataclass_with_properties diff --git a/src/spdx_tools/spdx/model/extracted_licensing_info.py b/src/spdx_tools/spdx/model/extracted_licensing_info.py index 017f82bf3..22df3ec19 100644 --- a/src/spdx_tools/spdx/model/extracted_licensing_info.py +++ b/src/spdx_tools/spdx/model/extracted_licensing_info.py @@ -6,7 +6,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model import SpdxNoAssertion @dataclass_with_properties diff --git a/src/spdx_tools/spdx/model/file.py b/src/spdx_tools/spdx/model/file.py index c46ba3f97..1573f7475 100644 --- a/src/spdx_tools/spdx/model/file.py +++ b/src/spdx_tools/spdx/model/file.py @@ -9,9 +9,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx.model.checksum import Checksum -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Checksum, SpdxNoAssertion, SpdxNone class FileType(Enum): diff --git a/src/spdx_tools/spdx/model/package.py b/src/spdx_tools/spdx/model/package.py index be54abcaf..53bc5e9db 100644 --- a/src/spdx_tools/spdx/model/package.py +++ b/src/spdx_tools/spdx/model/package.py @@ -10,10 +10,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx.model.actor import Actor -from spdx_tools.spdx.model.checksum import Checksum -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Actor, Checksum, SpdxNoAssertion, SpdxNone class PackagePurpose(Enum): diff --git a/src/spdx_tools/spdx/model/relationship.py b/src/spdx_tools/spdx/model/relationship.py index e8fe282c5..6005f7e2b 100644 --- a/src/spdx_tools/spdx/model/relationship.py +++ b/src/spdx_tools/spdx/model/relationship.py @@ -6,8 +6,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone class RelationshipType(Enum): diff --git a/src/spdx_tools/spdx/model/relationship_filters.py b/src/spdx_tools/spdx/model/relationship_filters.py index 073ee80fc..be04b34b9 100644 --- a/src/spdx_tools/spdx/model/relationship_filters.py +++ b/src/spdx_tools/spdx/model/relationship_filters.py @@ -3,9 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.package import Package -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model import Document, Package, Relationship, RelationshipType def find_package_contains_file_relationships(document: Document, package: Package) -> List[Relationship]: diff --git a/src/spdx_tools/spdx/model/snippet.py b/src/spdx_tools/spdx/model/snippet.py index d755cdff3..308c726cb 100644 --- a/src/spdx_tools/spdx/model/snippet.py +++ b/src/spdx_tools/spdx/model/snippet.py @@ -8,8 +8,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone @dataclass_with_properties diff --git a/src/spdx_tools/spdx/parser/actor_parser.py b/src/spdx_tools/spdx/parser/actor_parser.py index 7a5240f0e..4d20f4629 100644 --- a/src/spdx_tools/spdx/parser/actor_parser.py +++ b/src/spdx_tools/spdx/parser/actor_parser.py @@ -4,7 +4,7 @@ import re from typing import Match, Optional, Pattern -from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model import Actor, ActorType from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.parsing_functions import construct_or_raise_parsing_error diff --git a/src/spdx_tools/spdx/parser/json/json_parser.py b/src/spdx_tools/spdx/parser/json/json_parser.py index 3ef908ec9..0864caec6 100644 --- a/src/spdx_tools/spdx/parser/json/json_parser.py +++ b/src/spdx_tools/spdx/parser/json/json_parser.py @@ -4,7 +4,7 @@ import json from typing import Dict -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py index 5d38aa616..02e47a1b0 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py @@ -5,8 +5,7 @@ from typing import Dict, List, Optional from spdx_tools.spdx.datetime_conversions import datetime_from_str -from spdx_tools.spdx.model.actor import Actor -from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model import Actor, Annotation, AnnotationType from spdx_tools.spdx.parser.actor_parser import ActorParser from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py index e9d0b3ad5..de1eada17 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Dict, Optional -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import json_str_to_enum_name from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.parser.parsing_functions import ( diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py index 98af85e97..dbad22d11 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py @@ -5,11 +5,7 @@ from typing import Dict, List, Optional from spdx_tools.spdx.datetime_conversions import datetime_from_str -from spdx_tools.spdx.model.actor import Actor -from spdx_tools.spdx.model.checksum import Checksum -from spdx_tools.spdx.model.document import CreationInfo -from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef -from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.model import Actor, Checksum, CreationInfo, ExternalDocumentRef, Version from spdx_tools.spdx.parser.actor_parser import ActorParser from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py b/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py index b8cbef483..6320b5bc0 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py @@ -3,8 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Any, Callable, Dict, List, Optional -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.parser.parsing_functions import raise_parsing_error_if_logger_has_messages diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py index 8b22f8443..8a75de24d 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py @@ -3,8 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Dict, List, Optional, Union -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model import ExtractedLicensingInfo, SpdxNoAssertion from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_no_assertion from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.parser.parsing_functions import construct_or_raise_parsing_error diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py index 94aa31b04..53a9078db 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py @@ -5,10 +5,7 @@ from license_expression import LicenseExpression -from spdx_tools.spdx.model.checksum import Checksum -from spdx_tools.spdx.model.file import File, FileType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Checksum, File, FileType, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( parse_field_or_log_error, diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py index 3f9b43a11..9465c0c76 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Dict -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.annotation_parser import AnnotationParser from spdx_tools.spdx.parser.jsonlikedict.creation_info_parser import CreationInfoParser diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py index 08b17f9da..de0b36cab 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py @@ -5,8 +5,7 @@ from license_expression import ExpressionError, LicenseExpression, Licensing -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py index 55b6e064d..fb4924a63 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py @@ -7,16 +7,16 @@ from license_expression import LicenseExpression from spdx_tools.spdx.datetime_conversions import datetime_from_str -from spdx_tools.spdx.model.actor import Actor -from spdx_tools.spdx.model.package import ( +from spdx_tools.spdx.model import ( + Actor, ExternalPackageRef, ExternalPackageRefCategory, Package, PackagePurpose, PackageVerificationCode, + SpdxNoAssertion, + SpdxNone, ) -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone from spdx_tools.spdx.parser.actor_parser import ActorParser from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py index e541070b2..5ffc5c6e6 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py @@ -4,7 +4,7 @@ from typing import Dict, List, Optional from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model import Relationship, RelationshipType from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( delete_duplicates_from_list, diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py index 55745884f..4f501608f 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py @@ -6,9 +6,7 @@ from license_expression import LicenseExpression -from spdx_tools.spdx.model.snippet import Snippet -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Snippet, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( parse_field_or_log_error, diff --git a/src/spdx_tools/spdx/parser/rdf/annotation_parser.py b/src/spdx_tools/spdx/parser/rdf/annotation_parser.py index 1a8e2746c..880637bf1 100644 --- a/src/spdx_tools/spdx/parser/rdf/annotation_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/annotation_parser.py @@ -4,7 +4,7 @@ from rdflib import RDFS, BNode, Graph, URIRef from spdx_tools.spdx.datetime_conversions import datetime_from_str -from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model import Annotation, AnnotationType from spdx_tools.spdx.parser.actor_parser import ActorParser from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.parser.parsing_functions import ( diff --git a/src/spdx_tools/spdx/parser/rdf/checksum_parser.py b/src/spdx_tools/spdx/parser/rdf/checksum_parser.py index 633b2ad65..722f20340 100644 --- a/src/spdx_tools/spdx/parser/rdf/checksum_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/checksum_parser.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import BNode, Graph -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.parser.parsing_functions import ( diff --git a/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py b/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py index ca83a122c..c21276a53 100644 --- a/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py @@ -12,9 +12,7 @@ from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID from spdx_tools.spdx.datetime_conversions import datetime_from_str -from spdx_tools.spdx.model.document import CreationInfo -from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef -from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.model import CreationInfo, ExternalDocumentRef, Version from spdx_tools.spdx.parser.actor_parser import ActorParser from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.logger import Logger diff --git a/src/spdx_tools/spdx/parser/rdf/extracted_licensing_info_parser.py b/src/spdx_tools/spdx/parser/rdf/extracted_licensing_info_parser.py index b61b83d48..e77e8e8ad 100644 --- a/src/spdx_tools/spdx/parser/rdf/extracted_licensing_info_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/extracted_licensing_info_parser.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model import ExtractedLicensingInfo from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.parser.parsing_functions import ( construct_or_raise_parsing_error, diff --git a/src/spdx_tools/spdx/parser/rdf/file_parser.py b/src/spdx_tools/spdx/parser/rdf/file_parser.py index 69067ed24..18512fe6c 100644 --- a/src/spdx_tools/spdx/parser/rdf/file_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/file_parser.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDFS, Graph, URIRef -from spdx_tools.spdx.model.file import File, FileType +from spdx_tools.spdx.model import File, FileType from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.parser.parsing_functions import ( construct_or_raise_parsing_error, diff --git a/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py b/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py index 12d78e680..8ed8faff0 100644 --- a/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py +++ b/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py @@ -10,8 +10,9 @@ from rdflib.term import BNode, Literal, Node from spdx_tools.spdx.casing_tools import camel_case_to_snake_case -from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/src/spdx_tools/spdx/parser/rdf/package_parser.py b/src/spdx_tools/spdx/parser/rdf/package_parser.py index 61d94a667..a3de07749 100644 --- a/src/spdx_tools/spdx/parser/rdf/package_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/package_parser.py @@ -7,7 +7,7 @@ from rdflib.term import BNode from spdx_tools.spdx.datetime_conversions import datetime_from_str -from spdx_tools.spdx.model.package import ( +from spdx_tools.spdx.model import ( ExternalPackageRef, ExternalPackageRefCategory, Package, diff --git a/src/spdx_tools/spdx/parser/rdf/rdf_parser.py b/src/spdx_tools/spdx/parser/rdf/rdf_parser.py index 42d7c7ecc..70236cd0d 100644 --- a/src/spdx_tools/spdx/parser/rdf/rdf_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/rdf_parser.py @@ -5,8 +5,7 @@ from rdflib import RDF, Graph -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.relationship import RelationshipType +from spdx_tools.spdx.model import Document, RelationshipType from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.parser.parsing_functions import ( diff --git a/src/spdx_tools/spdx/parser/rdf/relationship_parser.py b/src/spdx_tools/spdx/parser/rdf/relationship_parser.py index c043cb8ca..562e0ab92 100644 --- a/src/spdx_tools/spdx/parser/rdf/relationship_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/relationship_parser.py @@ -4,7 +4,7 @@ from rdflib import RDFS, Graph, URIRef from rdflib.term import Node -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model import Relationship, RelationshipType from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.parser.parsing_functions import ( construct_or_raise_parsing_error, diff --git a/src/spdx_tools/spdx/parser/rdf/snippet_parser.py b/src/spdx_tools/spdx/parser/rdf/snippet_parser.py index 073d7d9c8..b26d6cdfc 100644 --- a/src/spdx_tools/spdx/parser/rdf/snippet_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/snippet_parser.py @@ -7,7 +7,7 @@ from rdflib.exceptions import UniquenessError from rdflib.term import BNode, Node, URIRef -from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model import Snippet from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.parser.parsing_functions import ( diff --git a/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py b/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py index 484067841..d8cfef77a 100644 --- a/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py +++ b/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py @@ -7,13 +7,16 @@ from ply.yacc import YaccProduction from spdx_tools.spdx.casing_tools import camel_case_to_snake_case -from spdx_tools.spdx.model.annotation import Annotation -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.document import CreationInfo -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx_tools.spdx.model.file import File -from spdx_tools.spdx.model.package import Package -from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model import ( + Annotation, + Checksum, + ChecksumAlgorithm, + CreationInfo, + ExtractedLicensingInfo, + File, + Package, + Snippet, +) from spdx_tools.spdx.parser.error import SPDXParsingError diff --git a/src/spdx_tools/spdx/parser/tagvalue/parser.py b/src/spdx_tools/spdx/parser/tagvalue/parser.py index e4376fbe0..e6ce74dc4 100644 --- a/src/spdx_tools/spdx/parser/tagvalue/parser.py +++ b/src/spdx_tools/spdx/parser/tagvalue/parser.py @@ -19,23 +19,27 @@ from ply.yacc import LRParser from spdx_tools.spdx.datetime_conversions import datetime_from_str -from spdx_tools.spdx.model.annotation import Annotation, AnnotationType -from spdx_tools.spdx.model.document import CreationInfo, Document -from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx_tools.spdx.model.file import File, FileType -from spdx_tools.spdx.model.package import ( +from spdx_tools.spdx.model import ( + Annotation, + AnnotationType, + CreationInfo, + Document, + ExternalDocumentRef, ExternalPackageRef, ExternalPackageRefCategory, + ExtractedLicensingInfo, + File, + FileType, Package, PackagePurpose, PackageVerificationCode, + Relationship, + RelationshipType, + Snippet, + SpdxNoAssertion, + SpdxNone, + Version, ) -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType -from spdx_tools.spdx.model.snippet import Snippet -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone -from spdx_tools.spdx.model.version import Version from spdx_tools.spdx.parser.actor_parser import ActorParser from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.logger import Logger diff --git a/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py b/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py index a617cac96..c28596363 100644 --- a/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py +++ b/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.tagvalue.parser import Parser diff --git a/src/spdx_tools/spdx/parser/xml/xml_parser.py b/src/spdx_tools/spdx/parser/xml/xml_parser.py index bef87d86b..52863f389 100644 --- a/src/spdx_tools/spdx/parser/xml/xml_parser.py +++ b/src/spdx_tools/spdx/parser/xml/xml_parser.py @@ -5,7 +5,7 @@ import xmltodict -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser diff --git a/src/spdx_tools/spdx/parser/yaml/yaml_parser.py b/src/spdx_tools/spdx/parser/yaml/yaml_parser.py index 86bcd6e49..021858137 100644 --- a/src/spdx_tools/spdx/parser/yaml/yaml_parser.py +++ b/src/spdx_tools/spdx/parser/yaml/yaml_parser.py @@ -5,7 +5,7 @@ import yaml -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser diff --git a/src/spdx_tools/spdx/validation/actor_validator.py b/src/spdx_tools/spdx/validation/actor_validator.py index c15b99e02..313f7d3e1 100644 --- a/src/spdx_tools/spdx/validation/actor_validator.py +++ b/src/spdx_tools/spdx/validation/actor_validator.py @@ -4,7 +4,7 @@ from typing import List -from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model import Actor, ActorType from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage diff --git a/src/spdx_tools/spdx/validation/annotation_validator.py b/src/spdx_tools/spdx/validation/annotation_validator.py index 309f7c9fa..dbfa1bed2 100644 --- a/src/spdx_tools/spdx/validation/annotation_validator.py +++ b/src/spdx_tools/spdx/validation/annotation_validator.py @@ -4,8 +4,7 @@ from typing import List -from spdx_tools.spdx.model.annotation import Annotation -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Annotation, Document from spdx_tools.spdx.validation.actor_validator import validate_actor from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage diff --git a/src/spdx_tools/spdx/validation/checksum_validator.py b/src/spdx_tools/spdx/validation/checksum_validator.py index 53f40e473..67df436ca 100644 --- a/src/spdx_tools/spdx/validation/checksum_validator.py +++ b/src/spdx_tools/spdx/validation/checksum_validator.py @@ -5,7 +5,7 @@ import re from typing import Dict, List -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage # in hexadecimal digits diff --git a/src/spdx_tools/spdx/validation/creation_info_validator.py b/src/spdx_tools/spdx/validation/creation_info_validator.py index 32de32673..55bac981d 100644 --- a/src/spdx_tools/spdx/validation/creation_info_validator.py +++ b/src/spdx_tools/spdx/validation/creation_info_validator.py @@ -5,7 +5,7 @@ from typing import List from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.model import CreationInfo from spdx_tools.spdx.validation.actor_validator import validate_actors from spdx_tools.spdx.validation.external_document_ref_validator import validate_external_document_refs from spdx_tools.spdx.validation.uri_validators import validate_uri diff --git a/src/spdx_tools/spdx/validation/document_validator.py b/src/spdx_tools/spdx/validation/document_validator.py index b368ff576..41e5c7d9b 100644 --- a/src/spdx_tools/spdx/validation/document_validator.py +++ b/src/spdx_tools/spdx/validation/document_validator.py @@ -3,8 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.relationship import RelationshipType +from spdx_tools.spdx.model import Document, RelationshipType from spdx_tools.spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target from spdx_tools.spdx.validation.annotation_validator import validate_annotations from spdx_tools.spdx.validation.creation_info_validator import validate_creation_info diff --git a/src/spdx_tools/spdx/validation/external_document_ref_validator.py b/src/spdx_tools/spdx/validation/external_document_ref_validator.py index 2bbf95566..1dd7da0c3 100644 --- a/src/spdx_tools/spdx/validation/external_document_ref_validator.py +++ b/src/spdx_tools/spdx/validation/external_document_ref_validator.py @@ -4,7 +4,7 @@ from typing import List -from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model import ExternalDocumentRef from spdx_tools.spdx.validation.checksum_validator import validate_checksum from spdx_tools.spdx.validation.spdx_id_validators import is_valid_external_doc_ref_id from spdx_tools.spdx.validation.uri_validators import validate_uri diff --git a/src/spdx_tools/spdx/validation/external_package_ref_validator.py b/src/spdx_tools/spdx/validation/external_package_ref_validator.py index c37187f4b..e785891fb 100644 --- a/src/spdx_tools/spdx/validation/external_package_ref_validator.py +++ b/src/spdx_tools/spdx/validation/external_package_ref_validator.py @@ -6,11 +6,8 @@ import uritools -from spdx_tools.spdx.model.package import ( - CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES, - ExternalPackageRef, - ExternalPackageRefCategory, -) +from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory +from spdx_tools.spdx.model.package import CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES from spdx_tools.spdx.validation.uri_validators import validate_url from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage diff --git a/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py b/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py index 7779c2d80..86df9ca77 100644 --- a/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py +++ b/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py @@ -5,7 +5,7 @@ import re from typing import List, Optional -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model import ExtractedLicensingInfo from spdx_tools.spdx.validation.uri_validators import validate_url from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage diff --git a/src/spdx_tools/spdx/validation/file_validator.py b/src/spdx_tools/spdx/validation/file_validator.py index e461c14b0..77cf6a5d1 100644 --- a/src/spdx_tools/spdx/validation/file_validator.py +++ b/src/spdx_tools/spdx/validation/file_validator.py @@ -4,9 +4,7 @@ from typing import List, Optional -from spdx_tools.spdx.model.checksum import ChecksumAlgorithm -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.model import ChecksumAlgorithm, Document, File from spdx_tools.spdx.validation.checksum_validator import validate_checksums from spdx_tools.spdx.validation.license_expression_validator import ( validate_license_expression, diff --git a/src/spdx_tools/spdx/validation/license_expression_validator.py b/src/spdx_tools/spdx/validation/license_expression_validator.py index 72dabe548..e9b52ca7a 100644 --- a/src/spdx_tools/spdx/validation/license_expression_validator.py +++ b/src/spdx_tools/spdx/validation/license_expression_validator.py @@ -6,9 +6,7 @@ from license_expression import ExpressionError, ExpressionParseError, LicenseExpression, get_spdx_licensing -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Document, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage diff --git a/src/spdx_tools/spdx/validation/package_validator.py b/src/spdx_tools/spdx/validation/package_validator.py index 51d887963..dc41dcf4c 100644 --- a/src/spdx_tools/spdx/validation/package_validator.py +++ b/src/spdx_tools/spdx/validation/package_validator.py @@ -4,9 +4,7 @@ from typing import List, Optional -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.package import Package -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model import Document, Package, Relationship, RelationshipType from spdx_tools.spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target from spdx_tools.spdx.validation.checksum_validator import validate_checksums from spdx_tools.spdx.validation.external_package_ref_validator import validate_external_package_refs diff --git a/src/spdx_tools/spdx/validation/package_verification_code_validator.py b/src/spdx_tools/spdx/validation/package_verification_code_validator.py index db1a0edf2..fb79135ba 100644 --- a/src/spdx_tools/spdx/validation/package_verification_code_validator.py +++ b/src/spdx_tools/spdx/validation/package_verification_code_validator.py @@ -5,7 +5,7 @@ import re from typing import List -from spdx_tools.spdx.model.package import PackageVerificationCode +from spdx_tools.spdx.model import PackageVerificationCode from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage diff --git a/src/spdx_tools/spdx/validation/relationship_validator.py b/src/spdx_tools/spdx/validation/relationship_validator.py index 84e97f6d1..1f9430683 100644 --- a/src/spdx_tools/spdx/validation/relationship_validator.py +++ b/src/spdx_tools/spdx/validation/relationship_validator.py @@ -4,10 +4,7 @@ from typing import List -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Document, Relationship, RelationshipType, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage diff --git a/src/spdx_tools/spdx/validation/snippet_validator.py b/src/spdx_tools/spdx/validation/snippet_validator.py index db696e45e..aab0e606d 100644 --- a/src/spdx_tools/spdx/validation/snippet_validator.py +++ b/src/spdx_tools/spdx/validation/snippet_validator.py @@ -4,8 +4,7 @@ from typing import List, Optional -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model import Document, Snippet from spdx_tools.spdx.validation.license_expression_validator import ( validate_license_expression, validate_license_expressions, diff --git a/src/spdx_tools/spdx/validation/spdx_id_validators.py b/src/spdx_tools/spdx/validation/spdx_id_validators.py index 86952a4fc..0d78900a6 100644 --- a/src/spdx_tools/spdx/validation/spdx_id_validators.py +++ b/src/spdx_tools/spdx/validation/spdx_id_validators.py @@ -6,8 +6,7 @@ from typing import List from spdx_tools.spdx.document_utils import get_contained_spdx_element_ids -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.model import Document, File def is_valid_internal_spdx_id(spdx_id: str) -> bool: diff --git a/src/spdx_tools/spdx/writer/json/json_writer.py b/src/spdx_tools/spdx/writer/json/json_writer.py index 58c4acbee..0b939c039 100644 --- a/src/spdx_tools/spdx/writer/json/json_writer.py +++ b/src/spdx_tools/spdx/writer/json/json_writer.py @@ -6,7 +6,7 @@ from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document from spdx_tools.spdx.validation.validation_message import ValidationMessage diff --git a/src/spdx_tools/spdx/writer/rdf/annotation_writer.py b/src/spdx_tools/spdx/writer/rdf/annotation_writer.py index 529f0ccd2..dd51b47e6 100644 --- a/src/spdx_tools/spdx/writer/rdf/annotation_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/annotation_writer.py @@ -7,7 +7,7 @@ from spdx_tools.spdx.casing_tools import snake_case_to_camel_case from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string -from spdx_tools.spdx.model.annotation import Annotation +from spdx_tools.spdx.model import Annotation from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id diff --git a/src/spdx_tools/spdx/writer/rdf/checksum_writer.py b/src/spdx_tools/spdx/writer/rdf/checksum_writer.py index 8af75f53b..1f7172e88 100644 --- a/src/spdx_tools/spdx/writer/rdf/checksum_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/checksum_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, BNode, Graph, Literal, URIRef -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/src/spdx_tools/spdx/writer/rdf/creation_info_writer.py b/src/spdx_tools/spdx/writer/rdf/creation_info_writer.py index b457101b6..6e77bc8d9 100644 --- a/src/spdx_tools/spdx/writer/rdf/creation_info_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/creation_info_writer.py @@ -4,7 +4,7 @@ from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string -from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.model import CreationInfo from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE from spdx_tools.spdx.writer.rdf.external_document_ref_writer import add_external_document_ref_to_graph from spdx_tools.spdx.writer.rdf.writer_utils import add_optional_literal diff --git a/src/spdx_tools/spdx/writer/rdf/external_document_ref_writer.py b/src/spdx_tools/spdx/writer/rdf/external_document_ref_writer.py index 536a96434..958ac8b5e 100644 --- a/src/spdx_tools/spdx/writer/rdf/external_document_ref_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/external_document_ref_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, Graph, URIRef -from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model import ExternalDocumentRef from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph diff --git a/src/spdx_tools/spdx/writer/rdf/extracted_licensing_info_writer.py b/src/spdx_tools/spdx/writer/rdf/extracted_licensing_info_writer.py index 89f163b8f..f30ab5d60 100644 --- a/src/spdx_tools/spdx/writer/rdf/extracted_licensing_info_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/extracted_licensing_info_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model import ExtractedLicensingInfo from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx_tools.spdx.writer.rdf.writer_utils import add_literal_or_no_assertion, add_optional_literal diff --git a/src/spdx_tools/spdx/writer/rdf/file_writer.py b/src/spdx_tools/spdx/writer/rdf/file_writer.py index d3454cc96..649a1e6e0 100644 --- a/src/spdx_tools/spdx/writer/rdf/file_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/file_writer.py @@ -6,7 +6,7 @@ from rdflib import RDF, RDFS, Graph, Literal, URIRef from spdx_tools.spdx.casing_tools import snake_case_to_camel_case -from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.model import File from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion diff --git a/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py b/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py index 6df0d9800..b6acfe1ad 100644 --- a/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py @@ -16,8 +16,7 @@ from rdflib import RDF, BNode, Graph, URIRef from rdflib.term import Literal, Node -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE diff --git a/src/spdx_tools/spdx/writer/rdf/package_writer.py b/src/spdx_tools/spdx/writer/rdf/package_writer.py index d678ba99d..90d21c145 100644 --- a/src/spdx_tools/spdx/writer/rdf/package_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/package_writer.py @@ -6,12 +6,8 @@ from rdflib import DOAP, RDF, RDFS, XSD, BNode, Graph, Literal, URIRef from spdx_tools.spdx.casing_tools import snake_case_to_camel_case -from spdx_tools.spdx.model.package import ( - CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES, - ExternalPackageRef, - Package, - PackageVerificationCode, -) +from spdx_tools.spdx.model import ExternalPackageRef, Package, PackageVerificationCode +from spdx_tools.spdx.model.package import CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES from spdx_tools.spdx.rdfschema.namespace import REFERENCE_NAMESPACE, SPDX_NAMESPACE from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion diff --git a/src/spdx_tools/spdx/writer/rdf/rdf_writer.py b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py index 32ba50c80..360337abc 100644 --- a/src/spdx_tools/spdx/writer/rdf/rdf_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py @@ -7,7 +7,7 @@ from rdflib.compare import to_isomorphic from spdx_tools.spdx.document_utils import create_document_without_duplicates -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document from spdx_tools.spdx.validation.validation_message import ValidationMessage diff --git a/src/spdx_tools/spdx/writer/rdf/relationship_writer.py b/src/spdx_tools/spdx/writer/rdf/relationship_writer.py index f33018074..82b5b59d5 100644 --- a/src/spdx_tools/spdx/writer/rdf/relationship_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/relationship_writer.py @@ -6,9 +6,7 @@ from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef from spdx_tools.spdx.casing_tools import snake_case_to_camel_case -from spdx_tools.spdx.model.relationship import Relationship -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Relationship, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id diff --git a/src/spdx_tools/spdx/writer/rdf/snippet_writer.py b/src/spdx_tools/spdx/writer/rdf/snippet_writer.py index 2f46cc3c1..f45759c9b 100644 --- a/src/spdx_tools/spdx/writer/rdf/snippet_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/snippet_writer.py @@ -5,7 +5,7 @@ from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef -from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model import Snippet from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_or_none_or_no_assertion from spdx_tools.spdx.writer.rdf.writer_utils import add_namespace_to_spdx_id, add_optional_literal diff --git a/src/spdx_tools/spdx/writer/rdf/writer_utils.py b/src/spdx_tools/spdx/writer/rdf/writer_utils.py index a6118208d..9bca3f470 100644 --- a/src/spdx_tools/spdx/writer/rdf/writer_utils.py +++ b/src/spdx_tools/spdx/writer/rdf/writer_utils.py @@ -9,8 +9,7 @@ from rdflib.term import Node from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx_tools.spdx.validation.spdx_id_validators import is_valid_internal_spdx_id diff --git a/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py b/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py index 7828b903f..0be7663c4 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py @@ -11,7 +11,7 @@ from typing import TextIO from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string -from spdx_tools.spdx.model.annotation import Annotation +from spdx_tools.spdx.model import Annotation from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value diff --git a/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py b/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py index 91d89dd8a..b641c0f53 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm def write_checksum_to_tag_value(checksum: Checksum) -> str: diff --git a/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py b/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py index fca4d0bc3..9e87b0925 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py @@ -11,7 +11,7 @@ from typing import TextIO from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string -from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.model import CreationInfo from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( write_optional_heading, write_separator, diff --git a/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py b/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py index ee728efca..89734c8c8 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py @@ -10,7 +10,7 @@ # limitations under the License. from typing import TextIO -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model import ExtractedLicensingInfo from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value diff --git a/src/spdx_tools/spdx/writer/tagvalue/file_writer.py b/src/spdx_tools/spdx/writer/tagvalue/file_writer.py index 1bfc07ff2..8848d9aae 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/file_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/file_writer.py @@ -10,7 +10,7 @@ # limitations under the License. from typing import TextIO -from spdx_tools.spdx.model.file import File +from spdx_tools.spdx.model import File from spdx_tools.spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value diff --git a/src/spdx_tools/spdx/writer/tagvalue/package_writer.py b/src/spdx_tools/spdx/writer/tagvalue/package_writer.py index f70259eae..d690773e0 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/package_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/package_writer.py @@ -11,7 +11,7 @@ from typing import TextIO from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string -from spdx_tools.spdx.model.package import Package, PackageVerificationCode +from spdx_tools.spdx.model import Package, PackageVerificationCode from spdx_tools.spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import ( transform_enum_name_to_tv, diff --git a/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py b/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py index b124e81eb..a46f0c7cc 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py @@ -10,7 +10,7 @@ # limitations under the License. from typing import TextIO -from spdx_tools.spdx.model.relationship import Relationship +from spdx_tools.spdx.model import Relationship from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value diff --git a/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py b/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py index 2d404a17e..de8ce16d4 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py @@ -10,7 +10,7 @@ # limitations under the License. from typing import TextIO -from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model import Snippet from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range, write_text_value, write_value diff --git a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py index 13013d385..37a54cae3 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py @@ -11,7 +11,7 @@ from typing import List, TextIO from spdx_tools.spdx.document_utils import create_document_without_duplicates -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document from spdx_tools.spdx.validation.validation_message import ValidationMessage from spdx_tools.spdx.writer.tagvalue.annotation_writer import write_annotation diff --git a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py index 55acdf466..2e638f943 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py @@ -12,13 +12,16 @@ from license_expression import LicenseExpression -from spdx_tools.spdx.model.actor import Actor -from spdx_tools.spdx.model.file import File -from spdx_tools.spdx.model.package import Package -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType -from spdx_tools.spdx.model.snippet import Snippet -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import ( + Actor, + File, + Package, + Relationship, + RelationshipType, + Snippet, + SpdxNoAssertion, + SpdxNone, +) def write_separator(out: TextIO): diff --git a/src/spdx_tools/spdx/writer/write_anything.py b/src/spdx_tools/spdx/writer/write_anything.py index 26f238d74..d811b35c9 100644 --- a/src/spdx_tools/spdx/writer/write_anything.py +++ b/src/spdx_tools/spdx/writer/write_anything.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 from spdx_tools.spdx.formats import FileFormat, file_name_to_format -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.writer.json import json_writer from spdx_tools.spdx.writer.rdf import rdf_writer from spdx_tools.spdx.writer.tagvalue import tagvalue_writer diff --git a/src/spdx_tools/spdx/writer/xml/xml_writer.py b/src/spdx_tools/spdx/writer/xml/xml_writer.py index bcef88a70..73070b123 100644 --- a/src/spdx_tools/spdx/writer/xml/xml_writer.py +++ b/src/spdx_tools/spdx/writer/xml/xml_writer.py @@ -7,7 +7,7 @@ from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document from spdx_tools.spdx.validation.validation_message import ValidationMessage diff --git a/src/spdx_tools/spdx/writer/yaml/yaml_writer.py b/src/spdx_tools/spdx/writer/yaml/yaml_writer.py index 00631b0e0..4c354a157 100644 --- a/src/spdx_tools/spdx/writer/yaml/yaml_writer.py +++ b/src/spdx_tools/spdx/writer/yaml/yaml_writer.py @@ -7,7 +7,7 @@ from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document from spdx_tools.spdx.validation.validation_message import ValidationMessage diff --git a/tests/spdx/fixtures.py b/tests/spdx/fixtures.py index 189da5a61..f0d8f14b7 100644 --- a/tests/spdx/fixtures.py +++ b/tests/spdx/fixtures.py @@ -6,25 +6,31 @@ from license_expression import get_spdx_licensing from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.annotation import Annotation, AnnotationType -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.document import CreationInfo, Document -from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx_tools.spdx.model.file import File, FileType -from spdx_tools.spdx.model.package import ( +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Annotation, + AnnotationType, + Checksum, + ChecksumAlgorithm, + CreationInfo, + Document, + ExternalDocumentRef, ExternalPackageRef, ExternalPackageRefCategory, + ExtractedLicensingInfo, + File, + FileType, Package, PackagePurpose, PackageVerificationCode, + Relationship, + RelationshipType, + Snippet, + SpdxNoAssertion, + SpdxNone, + Version, ) -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType -from spdx_tools.spdx.model.snippet import Snippet -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone -from spdx_tools.spdx.model.version import Version # Utility methods to create data model instances. All properties have valid defaults, so they don't need to be # specified unless relevant for the test. diff --git a/tests/spdx/jsonschema/test_annotation_converter.py b/tests/spdx/jsonschema/test_annotation_converter.py index 25d776848..fdc2e6ce2 100644 --- a/tests/spdx/jsonschema/test_annotation_converter.py +++ b/tests/spdx/jsonschema/test_annotation_converter.py @@ -8,8 +8,7 @@ from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter from spdx_tools.spdx.jsonschema.annotation_properties import AnnotationProperty -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model import Actor, ActorType, Annotation, AnnotationType @pytest.fixture diff --git a/tests/spdx/jsonschema/test_checksum_converter.py b/tests/spdx/jsonschema/test_checksum_converter.py index de960d62c..892c35f85 100644 --- a/tests/spdx/jsonschema/test_checksum_converter.py +++ b/tests/spdx/jsonschema/test_checksum_converter.py @@ -5,7 +5,7 @@ from spdx_tools.spdx.jsonschema.checksum_converter import ChecksumConverter from spdx_tools.spdx.jsonschema.checksum_properties import ChecksumProperty -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm @pytest.fixture diff --git a/tests/spdx/jsonschema/test_converter.py b/tests/spdx/jsonschema/test_converter.py index c6ecfb9c1..46558d904 100644 --- a/tests/spdx/jsonschema/test_converter.py +++ b/tests/spdx/jsonschema/test_converter.py @@ -10,8 +10,7 @@ from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.json_property import JsonProperty -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, Document class TestPropertyType(JsonProperty): diff --git a/tests/spdx/jsonschema/test_creation_info_converter.py b/tests/spdx/jsonschema/test_creation_info_converter.py index dcbc4de74..e8445f23b 100644 --- a/tests/spdx/jsonschema/test_creation_info_converter.py +++ b/tests/spdx/jsonschema/test_creation_info_converter.py @@ -8,9 +8,7 @@ from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string from spdx_tools.spdx.jsonschema.creation_info_converter import CreationInfoConverter from spdx_tools.spdx.jsonschema.creation_info_properties import CreationInfoProperty -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.document import CreationInfo -from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.model import Actor, ActorType, CreationInfo, Version from tests.spdx.fixtures import creation_info_fixture diff --git a/tests/spdx/jsonschema/test_document_converter.py b/tests/spdx/jsonschema/test_document_converter.py index 9923c4f73..e9966b87e 100644 --- a/tests/spdx/jsonschema/test_document_converter.py +++ b/tests/spdx/jsonschema/test_document_converter.py @@ -11,11 +11,16 @@ from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter from spdx_tools.spdx.jsonschema.document_properties import DocumentProperty -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.annotation import Annotation, AnnotationType -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Annotation, + AnnotationType, + Document, + ExtractedLicensingInfo, + Relationship, + RelationshipType, +) from tests.spdx.fixtures import ( annotation_fixture, creation_info_fixture, diff --git a/tests/spdx/jsonschema/test_external_document_ref_converter.py b/tests/spdx/jsonschema/test_external_document_ref_converter.py index 4a36e2e73..fabce5939 100644 --- a/tests/spdx/jsonschema/test_external_document_ref_converter.py +++ b/tests/spdx/jsonschema/test_external_document_ref_converter.py @@ -8,8 +8,7 @@ from spdx_tools.spdx.jsonschema.external_document_ref_converter import ExternalDocumentRefConverter from spdx_tools.spdx.jsonschema.external_document_ref_properties import ExternalDocumentRefProperty -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, ExternalDocumentRef @pytest.fixture diff --git a/tests/spdx/jsonschema/test_external_package_ref_converter.py b/tests/spdx/jsonschema/test_external_package_ref_converter.py index 9a4e8f7e5..303eb375d 100644 --- a/tests/spdx/jsonschema/test_external_package_ref_converter.py +++ b/tests/spdx/jsonschema/test_external_package_ref_converter.py @@ -5,7 +5,7 @@ from spdx_tools.spdx.jsonschema.external_package_ref_converter import ExternalPackageRefConverter from spdx_tools.spdx.jsonschema.external_package_ref_properties import ExternalPackageRefProperty -from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory +from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory @pytest.fixture diff --git a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py index 596ff8fa2..ee8488f4a 100644 --- a/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py +++ b/tests/spdx/jsonschema/test_extracted_licensing_info_converter.py @@ -5,8 +5,8 @@ from spdx_tools.spdx.jsonschema.extracted_licensing_info_converter import ExtractedLicensingInfoConverter from spdx_tools.spdx.jsonschema.extracted_licensing_info_properties import ExtractedLicensingInfoProperty -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo -from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion +from spdx_tools.spdx.model import ExtractedLicensingInfo, SpdxNoAssertion +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING from tests.spdx.fixtures import extracted_licensing_info_fixture diff --git a/tests/spdx/jsonschema/test_file_converter.py b/tests/spdx/jsonschema/test_file_converter.py index d38106f76..8e6c14049 100644 --- a/tests/spdx/jsonschema/test_file_converter.py +++ b/tests/spdx/jsonschema/test_file_converter.py @@ -12,13 +12,21 @@ from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter from spdx_tools.spdx.jsonschema.file_converter import FileConverter from spdx_tools.spdx.jsonschema.file_properties import FileProperty -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.annotation import Annotation, AnnotationType -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.file import File, FileType -from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Annotation, + AnnotationType, + Checksum, + ChecksumAlgorithm, + Document, + File, + FileType, + SpdxNoAssertion, + SpdxNone, +) +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING from tests.spdx.fixtures import annotation_fixture, creation_info_fixture, document_fixture, file_fixture from tests.spdx.mock_utils import assert_mock_method_called_with_arguments diff --git a/tests/spdx/jsonschema/test_package_converter.py b/tests/spdx/jsonschema/test_package_converter.py index 12f4e7945..9365c8214 100644 --- a/tests/spdx/jsonschema/test_package_converter.py +++ b/tests/spdx/jsonschema/test_package_converter.py @@ -12,13 +12,22 @@ from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter from spdx_tools.spdx.jsonschema.package_converter import PackageConverter from spdx_tools.spdx.jsonschema.package_properties import PackageProperty -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.annotation import Annotation, AnnotationType -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.package import Package, PackagePurpose, PackageVerificationCode -from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Annotation, + AnnotationType, + Checksum, + ChecksumAlgorithm, + Document, + Package, + PackagePurpose, + PackageVerificationCode, + SpdxNoAssertion, + SpdxNone, +) +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING from tests.spdx.fixtures import ( annotation_fixture, creation_info_fixture, diff --git a/tests/spdx/jsonschema/test_package_verification_code_converter.py b/tests/spdx/jsonschema/test_package_verification_code_converter.py index 1ffb39468..e55993dc9 100644 --- a/tests/spdx/jsonschema/test_package_verification_code_converter.py +++ b/tests/spdx/jsonschema/test_package_verification_code_converter.py @@ -5,7 +5,7 @@ from spdx_tools.spdx.jsonschema.package_verification_code_converter import PackageVerificationCodeConverter from spdx_tools.spdx.jsonschema.package_verification_code_properties import PackageVerificationCodeProperty -from spdx_tools.spdx.model.package import PackageVerificationCode +from spdx_tools.spdx.model import PackageVerificationCode @pytest.fixture diff --git a/tests/spdx/jsonschema/test_relationship_converter.py b/tests/spdx/jsonschema/test_relationship_converter.py index 87f0c8ec6..65b2d8803 100644 --- a/tests/spdx/jsonschema/test_relationship_converter.py +++ b/tests/spdx/jsonschema/test_relationship_converter.py @@ -5,9 +5,9 @@ from spdx_tools.spdx.jsonschema.relationship_converter import RelationshipConverter from spdx_tools.spdx.jsonschema.relationship_properties import RelationshipProperty -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType -from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING from tests.spdx.fixtures import relationship_fixture diff --git a/tests/spdx/jsonschema/test_snippet_converter.py b/tests/spdx/jsonschema/test_snippet_converter.py index 00b1a48a1..a677343b0 100644 --- a/tests/spdx/jsonschema/test_snippet_converter.py +++ b/tests/spdx/jsonschema/test_snippet_converter.py @@ -12,12 +12,18 @@ from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter from spdx_tools.spdx.jsonschema.snippet_converter import SnippetConverter from spdx_tools.spdx.jsonschema.snippet_properties import SnippetProperty -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.annotation import Annotation, AnnotationType -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.snippet import Snippet -from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING, SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING, SpdxNone +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Annotation, + AnnotationType, + Document, + Snippet, + SpdxNoAssertion, + SpdxNone, +) +from spdx_tools.spdx.model.spdx_no_assertion import SPDX_NO_ASSERTION_STRING +from spdx_tools.spdx.model.spdx_none import SPDX_NONE_STRING from tests.spdx.fixtures import annotation_fixture, creation_info_fixture, document_fixture, snippet_fixture from tests.spdx.mock_utils import assert_mock_method_called_with_arguments diff --git a/tests/spdx/model/test_actor.py b/tests/spdx/model/test_actor.py index fa0fa0baf..e41e40b4e 100644 --- a/tests/spdx/model/test_actor.py +++ b/tests/spdx/model/test_actor.py @@ -4,7 +4,7 @@ import pytest -from spdx_tools.spdx.model.actor import Actor, ActorType +from spdx_tools.spdx.model import Actor, ActorType def test_correct_initialization(): diff --git a/tests/spdx/model/test_annotation.py b/tests/spdx/model/test_annotation.py index c96c94e0a..5638b0b98 100644 --- a/tests/spdx/model/test_annotation.py +++ b/tests/spdx/model/test_annotation.py @@ -7,10 +7,10 @@ import pytest -from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model import Annotation, AnnotationType -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_correct_initialization(actor): annotation = Annotation("id", AnnotationType.OTHER, actor, datetime(2022, 1, 1), "comment") assert annotation.spdx_id == "id" @@ -20,31 +20,31 @@ def test_correct_initialization(actor): assert annotation.annotation_comment == "comment" -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_spdx_id(actor): with pytest.raises(TypeError): Annotation(42, AnnotationType.OTHER, actor, datetime(2022, 1, 1), "comment") -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_annotation_type(actor): with pytest.raises(TypeError): Annotation("id", 42, actor, datetime(2022, 1, 1), "comment") -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_annotator(actor): with pytest.raises(TypeError): Annotation("id", AnnotationType.OTHER, 42, datetime(2022, 1, 1), "comment") -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_annotation_date(actor): with pytest.raises(TypeError): Annotation("id", AnnotationType.OTHER, actor, 42, "comment") -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_annotation_comment(actor): with pytest.raises(TypeError): Annotation("id", AnnotationType.OTHER, actor, datetime(2022, 1, 1), 42) diff --git a/tests/spdx/model/test_checksum.py b/tests/spdx/model/test_checksum.py index 3184534ac..308d95486 100644 --- a/tests/spdx/model/test_checksum.py +++ b/tests/spdx/model/test_checksum.py @@ -4,7 +4,7 @@ import pytest -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm def test_correct_initialization(): diff --git a/tests/spdx/model/test_creation_info.py b/tests/spdx/model/test_creation_info.py index 9166ce714..c0912005c 100644 --- a/tests/spdx/model/test_creation_info.py +++ b/tests/spdx/model/test_creation_info.py @@ -7,12 +7,11 @@ import pytest -from spdx_tools.spdx.model.document import CreationInfo -from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.model import CreationInfo, Version -@mock.patch("spdx_tools.spdx.model.external_document_ref.ExternalDocumentRef", autospec=True) -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.ExternalDocumentRef", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_correct_initialization(actor, ext_ref): creation_info = CreationInfo( "version", @@ -40,25 +39,25 @@ def test_correct_initialization(actor, ext_ref): assert creation_info.document_comment == "doc_comment" -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_spdx_version(actor): with pytest.raises(TypeError): CreationInfo(42, "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1)) -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_spdx_id(actor): with pytest.raises(TypeError): CreationInfo("version", 42, "name", "namespace", [actor, actor], datetime(2022, 1, 1)) -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_name(actor): with pytest.raises(TypeError): CreationInfo("version", "id", 42, "namespace", [actor, actor], datetime(2022, 1, 1)) -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_document_namespace(actor): with pytest.raises(TypeError): CreationInfo("version", "id", "name", 42, [actor, actor], datetime(2022, 1, 1)) @@ -69,13 +68,13 @@ def test_wrong_type_in_creators(): CreationInfo("version", "id", "name", "namespace", ["person"], datetime(2022, 1, 1)) -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_created(actor): with pytest.raises(TypeError): CreationInfo("version", "id", "name", "namespace", [actor, actor], "2022-01-01") -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_creator_comment(actor): with pytest.raises(TypeError): CreationInfo( @@ -83,13 +82,13 @@ def test_wrong_type_in_creator_comment(actor): ) -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_data_license(actor): with pytest.raises(TypeError): CreationInfo("version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), data_license=42) -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_external_document_refs(actor): with pytest.raises(TypeError): CreationInfo( @@ -97,7 +96,7 @@ def test_wrong_type_in_external_document_refs(actor): ) -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_license_list_version(actor): with pytest.raises(TypeError): CreationInfo( @@ -105,7 +104,7 @@ def test_wrong_type_in_license_list_version(actor): ) -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_wrong_type_in_document_comment(actor): with pytest.raises(TypeError): CreationInfo( diff --git a/tests/spdx/model/test_document.py b/tests/spdx/model/test_document.py index 858404ae4..9d4079cb4 100644 --- a/tests/spdx/model/test_document.py +++ b/tests/spdx/model/test_document.py @@ -6,16 +6,16 @@ import pytest -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document -@mock.patch("spdx_tools.spdx.model.extracted_licensing_info.ExtractedLicensingInfo", autospec=True) -@mock.patch("spdx_tools.spdx.model.relationship.Relationship", autospec=True) -@mock.patch("spdx_tools.spdx.model.annotation.Annotation", autospec=True) -@mock.patch("spdx_tools.spdx.model.snippet.Snippet", autospec=True) -@mock.patch("spdx_tools.spdx.model.file.File", autospec=True) -@mock.patch("spdx_tools.spdx.model.package.Package", autospec=True) -@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.ExtractedLicensingInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.Relationship", autospec=True) +@mock.patch("spdx_tools.spdx.model.Annotation", autospec=True) +@mock.patch("spdx_tools.spdx.model.Snippet", autospec=True) +@mock.patch("spdx_tools.spdx.model.File", autospec=True) +@mock.patch("spdx_tools.spdx.model.Package", autospec=True) +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) def test_correct_initialization(creation_info, package, file, snippet, annotation, relationship, extracted_lic): document = Document( creation_info, @@ -35,7 +35,7 @@ def test_correct_initialization(creation_info, package, file, snippet, annotatio assert document.extracted_licensing_info == [extracted_lic, extracted_lic] -@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) def test_correct_initialization_with_default_values(creation_info): document = Document(creation_info) assert document.creation_info == creation_info @@ -52,37 +52,37 @@ def test_wrong_type_in_creation_info(): Document("string") -@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) def test_wrong_type_in_packages(creation_info): with pytest.raises(TypeError): Document(creation_info, packages=["string"]) -@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) def test_wrong_type_in_files(creation_info): with pytest.raises(TypeError): Document(creation_info, files={}) -@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) def test_wrong_type_in_snippets(creation_info): with pytest.raises(TypeError): Document(creation_info, snippets=()) -@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) def test_wrong_type_in_annotations(creation_info): with pytest.raises(TypeError): Document(creation_info, annotations=["string"]) -@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) def test_wrong_type_in_relationships(creation_info): with pytest.raises(TypeError): Document(creation_info, relationships="string") -@mock.patch("spdx_tools.spdx.model.document.CreationInfo", autospec=True) +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) def test_wrong_type_in_extracted_licensing_info(creation_info): with pytest.raises(TypeError): Document(creation_info, extracted_licensing_info=42) diff --git a/tests/spdx/model/test_external_document_ref.py b/tests/spdx/model/test_external_document_ref.py index 29e6a4824..4b32d6bf3 100644 --- a/tests/spdx/model/test_external_document_ref.py +++ b/tests/spdx/model/test_external_document_ref.py @@ -6,10 +6,10 @@ import pytest -from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx.model import ExternalDocumentRef -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_correct_initialization(checksum): external_document_ref = ExternalDocumentRef("id", "uri", checksum) assert external_document_ref.document_ref_id == "id" @@ -17,13 +17,13 @@ def test_correct_initialization(checksum): assert external_document_ref.checksum == checksum -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_spdx_id(checksum): with pytest.raises(TypeError): ExternalDocumentRef(42, "uri", checksum) -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_document_uri(checksum): with pytest.raises(TypeError): ExternalDocumentRef("id", 42, checksum) diff --git a/tests/spdx/model/test_external_package_reference.py b/tests/spdx/model/test_external_package_reference.py index 7ac967e2f..d81bcc221 100644 --- a/tests/spdx/model/test_external_package_reference.py +++ b/tests/spdx/model/test_external_package_reference.py @@ -4,7 +4,7 @@ import pytest -from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory +from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory def test_correct_initialization(): diff --git a/tests/spdx/model/test_extracted_licensing_info.py b/tests/spdx/model/test_extracted_licensing_info.py index 1f54e9207..75dc79aab 100644 --- a/tests/spdx/model/test_extracted_licensing_info.py +++ b/tests/spdx/model/test_extracted_licensing_info.py @@ -4,7 +4,7 @@ import pytest -from spdx_tools.spdx.model.extracted_licensing_info import ExtractedLicensingInfo +from spdx_tools.spdx.model import ExtractedLicensingInfo def test_correct_initialization(): diff --git a/tests/spdx/model/test_file.py b/tests/spdx/model/test_file.py index fb6d6b54e..592e8dc4f 100644 --- a/tests/spdx/model/test_file.py +++ b/tests/spdx/model/test_file.py @@ -6,13 +6,10 @@ import pytest -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.file import File, FileType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, File, FileType, SpdxNoAssertion, SpdxNone -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_correct_initialization(checksum): file = File( "name", @@ -42,7 +39,7 @@ def test_correct_initialization(checksum): assert file.attribution_texts == ["attribution"] -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_correct_initialization_with_default_values(checksum): file = File("name", "id", [checksum, checksum]) assert file.name == "name" @@ -59,13 +56,13 @@ def test_correct_initialization_with_default_values(checksum): assert file.attribution_texts == [] -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_name(checksum): with pytest.raises(TypeError): File(42, "id", [checksum]) -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_spdx_id(checksum): with pytest.raises(TypeError): File("name", 42, [checksum]) @@ -77,55 +74,55 @@ def test_wrong_type_in_checksum(): File("name", "id", checksum) -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_file_type(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], file_types=FileType.OTHER) -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_license_concluded(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], license_concluded="NONE") -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_license_info_in_file(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], license_info_in_file=[SpdxNone]) -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_license_comment(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], license_comment=42) -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_copyright_text(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], copyright_text=[SpdxNone()]) -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_comment(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], comment=42) -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_notice(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], notice=["notice"]) -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_contributors(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], contributors="contributor") -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_attribution_texts(checksum): with pytest.raises(TypeError): File("name", "id", [checksum], attribution_texts=["attribution", 42]) diff --git a/tests/spdx/model/test_package.py b/tests/spdx/model/test_package.py index afb7951a9..c533b2812 100644 --- a/tests/spdx/model/test_package.py +++ b/tests/spdx/model/test_package.py @@ -8,16 +8,13 @@ import pytest from license_expression import LicenseExpression, Licensing -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.package import Package, PackagePurpose -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, Package, PackagePurpose, SpdxNoAssertion, SpdxNone -@mock.patch("spdx_tools.spdx.model.package.ExternalPackageRef", autospec=True) -@mock.patch("spdx_tools.spdx.model.checksum.Checksum", autospec=True) -@mock.patch("spdx_tools.spdx.model.package.PackageVerificationCode", autospec=True) -@mock.patch("spdx_tools.spdx.model.actor.Actor", autospec=True) +@mock.patch("spdx_tools.spdx.model.ExternalPackageRef", autospec=True) +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +@mock.patch("spdx_tools.spdx.model.PackageVerificationCode", autospec=True) +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) def test_correct_initialization(actor, verif_code, checksum, ext_ref): package = Package( "id", diff --git a/tests/spdx/model/test_package_verification_code.py b/tests/spdx/model/test_package_verification_code.py index b6c0f9d1e..e1492a91d 100644 --- a/tests/spdx/model/test_package_verification_code.py +++ b/tests/spdx/model/test_package_verification_code.py @@ -4,7 +4,7 @@ import pytest -from spdx_tools.spdx.model.package import PackageVerificationCode +from spdx_tools.spdx.model import PackageVerificationCode def test_correct_initialization(): diff --git a/tests/spdx/model/test_relationship.py b/tests/spdx/model/test_relationship.py index 80ba441d1..0ffb62482 100644 --- a/tests/spdx/model/test_relationship.py +++ b/tests/spdx/model/test_relationship.py @@ -4,8 +4,7 @@ import pytest -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion def test_correct_initialization(): diff --git a/tests/spdx/model/test_snippet.py b/tests/spdx/model/test_snippet.py index 373e9b37f..7fcf21581 100644 --- a/tests/spdx/model/test_snippet.py +++ b/tests/spdx/model/test_snippet.py @@ -4,9 +4,7 @@ import pytest -from spdx_tools.spdx.model.snippet import Snippet -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Snippet, SpdxNoAssertion, SpdxNone def test_correct_initialization(): diff --git a/tests/spdx/model/test_version.py b/tests/spdx/model/test_version.py index b846703b3..a10817b7e 100644 --- a/tests/spdx/model/test_version.py +++ b/tests/spdx/model/test_version.py @@ -4,7 +4,7 @@ import pytest -from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.model import Version @pytest.mark.parametrize("input_string,expected", [("1.2", Version(1, 2)), ("12.345", Version(12, 345))]) diff --git a/tests/spdx/parser/all_formats/test_parse_from_file.py b/tests/spdx/parser/all_formats/test_parse_from_file.py index bb63711b7..2b9bb2b45 100644 --- a/tests/spdx/parser/all_formats/test_parse_from_file.py +++ b/tests/spdx/parser/all_formats/test_parse_from_file.py @@ -6,7 +6,7 @@ import pytest -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.json import json_parser from spdx_tools.spdx.parser.rdf import rdf_parser from spdx_tools.spdx.parser.tagvalue import tagvalue_parser diff --git a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py index b7a01d73e..0460598e7 100644 --- a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py @@ -7,8 +7,7 @@ import pytest from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx.model import Actor, ActorType, Annotation, AnnotationType from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.annotation_parser import AnnotationParser diff --git a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py index 42efafd75..aa2bbbe8a 100644 --- a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py @@ -5,7 +5,7 @@ import pytest -from spdx_tools.spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx.model import ChecksumAlgorithm from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser diff --git a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py index ffaa0046a..86535d703 100644 --- a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py @@ -7,10 +7,7 @@ import pytest from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef -from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.model import Actor, ActorType, Checksum, ChecksumAlgorithm, ExternalDocumentRef, Version from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.creation_info_parser import CreationInfoParser diff --git a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py index 9eb4e49cf..ce35e3611 100644 --- a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py +++ b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py @@ -5,8 +5,7 @@ import pytest -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( json_str_to_enum_name, diff --git a/tests/spdx/parser/jsonlikedict/test_file_parser.py b/tests/spdx/parser/jsonlikedict/test_file_parser.py index a67d9cd69..53eec3f0e 100644 --- a/tests/spdx/parser/jsonlikedict/test_file_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_file_parser.py @@ -6,10 +6,7 @@ import pytest from license_expression import Licensing -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.file import FileType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, FileType, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements from spdx_tools.spdx.parser.jsonlikedict.file_parser import FileParser diff --git a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py index 8f0e50ad6..a1364d556 100644 --- a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py @@ -6,8 +6,7 @@ import pytest from license_expression import get_spdx_licensing -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser diff --git a/tests/spdx/parser/jsonlikedict/test_package_parser.py b/tests/spdx/parser/jsonlikedict/test_package_parser.py index c67ae871a..494f612b7 100644 --- a/tests/spdx/parser/jsonlikedict/test_package_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_package_parser.py @@ -7,16 +7,18 @@ import pytest from license_expression import Licensing -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.package import ( +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Checksum, + ChecksumAlgorithm, ExternalPackageRef, ExternalPackageRefCategory, PackagePurpose, PackageVerificationCode, + SpdxNoAssertion, + SpdxNone, ) -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_list_of_elements from spdx_tools.spdx.parser.jsonlikedict.package_parser import PackageParser diff --git a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py index 20eba29d0..f5e65fe50 100644 --- a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py @@ -6,8 +6,7 @@ import pytest from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.relationship_parser import RelationshipParser diff --git a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py index c4ccba1c2..55397af24 100644 --- a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py @@ -6,8 +6,7 @@ import pytest from license_expression import Licensing -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.snippet_parser import SnippetParser diff --git a/tests/spdx/parser/rdf/test_annotation_parser.py b/tests/spdx/parser/rdf/test_annotation_parser.py index ac494381d..c0ed4b1b6 100644 --- a/tests/spdx/parser/rdf/test_annotation_parser.py +++ b/tests/spdx/parser/rdf/test_annotation_parser.py @@ -6,8 +6,7 @@ from rdflib import BNode, Graph, URIRef -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.annotation import AnnotationType +from spdx_tools.spdx.model import Actor, ActorType, AnnotationType from spdx_tools.spdx.parser.rdf.annotation_parser import parse_annotation from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/tests/spdx/parser/rdf/test_checksum_parser.py b/tests/spdx/parser/rdf/test_checksum_parser.py index 5b5be1c21..904febb35 100644 --- a/tests/spdx/parser/rdf/test_checksum_parser.py +++ b/tests/spdx/parser/rdf/test_checksum_parser.py @@ -6,7 +6,7 @@ import pytest from rdflib import BNode, Graph, URIRef -from spdx_tools.spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx.model import ChecksumAlgorithm from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.rdf.checksum_parser import convert_rdf_to_algorithm, parse_checksum from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/tests/spdx/parser/rdf/test_creation_info_parser.py b/tests/spdx/parser/rdf/test_creation_info_parser.py index a4dcb5b0c..606a2f126 100644 --- a/tests/spdx/parser/rdf/test_creation_info_parser.py +++ b/tests/spdx/parser/rdf/test_creation_info_parser.py @@ -10,9 +10,7 @@ from rdflib.term import Node from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.model import Actor, ActorType, Checksum, ChecksumAlgorithm, Version from spdx_tools.spdx.parser.rdf.creation_info_parser import ( parse_creation_info, parse_external_document_refs, diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py index d381a1567..fb24ed0da 100644 --- a/tests/spdx/parser/rdf/test_file_parser.py +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -7,9 +7,7 @@ from license_expression import get_spdx_licensing from rdflib import RDF, Graph, URIRef -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.file import FileType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, FileType, SpdxNoAssertion from spdx_tools.spdx.parser.rdf.file_parser import parse_file from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index 6e5850cf3..f6c968073 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -8,10 +8,16 @@ from license_expression import get_spdx_licensing from rdflib import RDF, BNode, Graph, Literal, URIRef -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.package import ExternalPackageRefCategory, PackagePurpose, PackageVerificationCode -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Checksum, + ChecksumAlgorithm, + ExternalPackageRefCategory, + PackagePurpose, + PackageVerificationCode, + SpdxNoAssertion, +) from spdx_tools.spdx.parser.rdf.package_parser import parse_external_package_ref, parse_package from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/tests/spdx/parser/rdf/test_relationship_parser.py b/tests/spdx/parser/rdf/test_relationship_parser.py index 5bc60ee6c..33024fad3 100644 --- a/tests/spdx/parser/rdf/test_relationship_parser.py +++ b/tests/spdx/parser/rdf/test_relationship_parser.py @@ -7,7 +7,7 @@ from rdflib import RDF, Graph, URIRef from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.relationship import RelationshipType +from spdx_tools.spdx.model import RelationshipType from spdx_tools.spdx.parser.rdf.relationship_parser import parse_implicit_relationship, parse_relationship from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index 4db77875b..1b4022827 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -8,7 +8,7 @@ from license_expression import get_spdx_licensing from rdflib import RDF, BNode, Graph, Literal, URIRef -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model import SpdxNoAssertion from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.rdf.snippet_parser import parse_ranges, parse_snippet from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE diff --git a/tests/spdx/parser/tagvalue/test_annotation_parser.py b/tests/spdx/parser/tagvalue/test_annotation_parser.py index cfbd1f40f..204756187 100644 --- a/tests/spdx/parser/tagvalue/test_annotation_parser.py +++ b/tests/spdx/parser/tagvalue/test_annotation_parser.py @@ -6,7 +6,7 @@ import pytest from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.annotation import AnnotationType +from spdx_tools.spdx.model import AnnotationType from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/parser/tagvalue/test_creation_info_parser.py b/tests/spdx/parser/tagvalue/test_creation_info_parser.py index 7fd0d275b..45f472642 100644 --- a/tests/spdx/parser/tagvalue/test_creation_info_parser.py +++ b/tests/spdx/parser/tagvalue/test_creation_info_parser.py @@ -7,10 +7,7 @@ import pytest from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.actor import Actor, ActorType -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef -from spdx_tools.spdx.model.version import Version +from spdx_tools.spdx.model import Actor, ActorType, Checksum, ChecksumAlgorithm, ExternalDocumentRef, Version from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.tagvalue.parser import Parser diff --git a/tests/spdx/parser/tagvalue/test_file_parser.py b/tests/spdx/parser/tagvalue/test_file_parser.py index d4e0df719..859516cbf 100644 --- a/tests/spdx/parser/tagvalue/test_file_parser.py +++ b/tests/spdx/parser/tagvalue/test_file_parser.py @@ -4,8 +4,7 @@ import pytest from license_expression import get_spdx_licensing -from spdx_tools.spdx.model.file import FileType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model import FileType, SpdxNoAssertion from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/parser/tagvalue/test_helper_methods.py b/tests/spdx/parser/tagvalue/test_helper_methods.py index 4419902f3..8ca601828 100644 --- a/tests/spdx/parser/tagvalue/test_helper_methods.py +++ b/tests/spdx/parser/tagvalue/test_helper_methods.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx_tools.spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx.model import ChecksumAlgorithm from spdx_tools.spdx.parser.tagvalue.helper_methods import parse_checksum diff --git a/tests/spdx/parser/tagvalue/test_package_parser.py b/tests/spdx/parser/tagvalue/test_package_parser.py index 76d8ddb0a..dbbeef415 100644 --- a/tests/spdx/parser/tagvalue/test_package_parser.py +++ b/tests/spdx/parser/tagvalue/test_package_parser.py @@ -8,8 +8,7 @@ from license_expression import get_spdx_licensing from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory, PackagePurpose -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory, PackagePurpose, SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/parser/tagvalue/test_relationship_parser.py b/tests/spdx/parser/tagvalue/test_relationship_parser.py index 59016c5a9..d351a0c06 100644 --- a/tests/spdx/parser/tagvalue/test_relationship_parser.py +++ b/tests/spdx/parser/tagvalue/test_relationship_parser.py @@ -4,9 +4,7 @@ import pytest from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/parser/tagvalue/test_snippet_parser.py b/tests/spdx/parser/tagvalue/test_snippet_parser.py index 42a170b87..8bd82595c 100644 --- a/tests/spdx/parser/tagvalue/test_snippet_parser.py +++ b/tests/spdx/parser/tagvalue/test_snippet_parser.py @@ -6,7 +6,7 @@ import pytest from license_expression import get_spdx_licensing -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model import SpdxNoAssertion from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/parser/tagvalue/test_tag_value_parser.py b/tests/spdx/parser/tagvalue/test_tag_value_parser.py index dfb20fad6..cb5381489 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_parser.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_parser.py @@ -6,7 +6,7 @@ import pytest from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model import Relationship, RelationshipType from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.tagvalue.parser import Parser from tests.spdx.parser.tagvalue.test_creation_info_parser import DOCUMENT_STR diff --git a/tests/spdx/test_actor_parser.py b/tests/spdx/test_actor_parser.py index 73eac6366..17d12a296 100644 --- a/tests/spdx/test_actor_parser.py +++ b/tests/spdx/test_actor_parser.py @@ -5,7 +5,7 @@ import pytest -from spdx_tools.spdx.model.actor import ActorType +from spdx_tools.spdx.model import ActorType from spdx_tools.spdx.parser.actor_parser import ActorParser from spdx_tools.spdx.parser.error import SPDXParsingError diff --git a/tests/spdx/test_document_utils.py b/tests/spdx/test_document_utils.py index a49e6af1e..4e05de869 100644 --- a/tests/spdx/test_document_utils.py +++ b/tests/spdx/test_document_utils.py @@ -12,9 +12,7 @@ get_contained_spdx_elements, get_element_from_spdx_id, ) -from spdx_tools.spdx.model.file import FileType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import FileType, SpdxNoAssertion, SpdxNone from tests.spdx.fixtures import ( actor_fixture, checksum_fixture, diff --git a/tests/spdx/test_graph_generation.py b/tests/spdx/test_graph_generation.py index 9961cb71f..f51d9590b 100644 --- a/tests/spdx/test_graph_generation.py +++ b/tests/spdx/test_graph_generation.py @@ -8,8 +8,7 @@ import pytest from spdx_tools.spdx.graph_generation import generate_relationship_graph_from_spdx -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model import Document, Relationship, RelationshipType from spdx_tools.spdx.parser.parse_anything import parse_file from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture diff --git a/tests/spdx/validation/test_actor_validator.py b/tests/spdx/validation/test_actor_validator.py index 14b8dc1c1..0ab122473 100644 --- a/tests/spdx/validation/test_actor_validator.py +++ b/tests/spdx/validation/test_actor_validator.py @@ -7,7 +7,7 @@ import pytest from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.actor import ActorType +from spdx_tools.spdx.model import ActorType from spdx_tools.spdx.validation.actor_validator import validate_actor from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import actor_fixture diff --git a/tests/spdx/validation/test_annotation_validator.py b/tests/spdx/validation/test_annotation_validator.py index 86787f858..2462f9cda 100644 --- a/tests/spdx/validation/test_annotation_validator.py +++ b/tests/spdx/validation/test_annotation_validator.py @@ -6,8 +6,7 @@ import pytest -from spdx_tools.spdx.model.annotation import Annotation -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Annotation, Document from spdx_tools.spdx.validation.annotation_validator import validate_annotation from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import annotation_fixture, document_fixture, file_fixture diff --git a/tests/spdx/validation/test_checksum_validator.py b/tests/spdx/validation/test_checksum_validator.py index e93b1d9dc..9340de5db 100644 --- a/tests/spdx/validation/test_checksum_validator.py +++ b/tests/spdx/validation/test_checksum_validator.py @@ -6,7 +6,7 @@ import pytest -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm from spdx_tools.spdx.validation.checksum_validator import validate_checksum from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import checksum_fixture diff --git a/tests/spdx/validation/test_document_validator.py b/tests/spdx/validation/test_document_validator.py index d0c021bc7..1b1897f52 100644 --- a/tests/spdx/validation/test_document_validator.py +++ b/tests/spdx/validation/test_document_validator.py @@ -7,8 +7,7 @@ import pytest from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.document import CreationInfo, Document -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType +from spdx_tools.spdx.model import CreationInfo, Document, Relationship, RelationshipType from spdx_tools.spdx.parser.parse_anything import parse_file from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage diff --git a/tests/spdx/validation/test_external_package_ref_validator.py b/tests/spdx/validation/test_external_package_ref_validator.py index 16d41f1ae..eafa31941 100644 --- a/tests/spdx/validation/test_external_package_ref_validator.py +++ b/tests/spdx/validation/test_external_package_ref_validator.py @@ -6,7 +6,7 @@ import pytest -from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory +from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory from spdx_tools.spdx.validation.external_package_ref_validator import ( BOWER_REGEX, CPE22TYPE_REGEX, diff --git a/tests/spdx/validation/test_file_validator.py b/tests/spdx/validation/test_file_validator.py index 2c26632a6..73f107a9f 100644 --- a/tests/spdx/validation/test_file_validator.py +++ b/tests/spdx/validation/test_file_validator.py @@ -7,7 +7,7 @@ import pytest -from spdx_tools.spdx.model.checksum import Checksum, ChecksumAlgorithm +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm from spdx_tools.spdx.validation.file_validator import validate_file, validate_file_within_document from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import document_fixture, file_fixture diff --git a/tests/spdx/validation/test_license_expression_validator.py b/tests/spdx/validation/test_license_expression_validator.py index 2b2dabed6..03c0eddad 100644 --- a/tests/spdx/validation/test_license_expression_validator.py +++ b/tests/spdx/validation/test_license_expression_validator.py @@ -8,9 +8,7 @@ import pytest from license_expression import LicenseExpression, get_spdx_licensing -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Document, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.validation.license_expression_validator import ( validate_license_expression, validate_license_expressions, diff --git a/tests/spdx/validation/test_package_validator.py b/tests/spdx/validation/test_package_validator.py index 335c744b9..c2b6640d2 100644 --- a/tests/spdx/validation/test_package_validator.py +++ b/tests/spdx/validation/test_package_validator.py @@ -9,9 +9,7 @@ from license_expression import Licensing from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.validation.package_validator import validate_package, validate_package_within_document from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import document_fixture, file_fixture, package_fixture, package_verification_code_fixture diff --git a/tests/spdx/validation/test_package_verification_code_validator.py b/tests/spdx/validation/test_package_verification_code_validator.py index 948904ef7..020bd8dd3 100644 --- a/tests/spdx/validation/test_package_verification_code_validator.py +++ b/tests/spdx/validation/test_package_verification_code_validator.py @@ -4,7 +4,7 @@ import pytest -from spdx_tools.spdx.model.package import PackageVerificationCode +from spdx_tools.spdx.model import PackageVerificationCode from spdx_tools.spdx.validation.package_verification_code_validator import validate_verification_code from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage diff --git a/tests/spdx/validation/test_relationship_validator.py b/tests/spdx/validation/test_relationship_validator.py index b72bc0a82..28cae9d7d 100644 --- a/tests/spdx/validation/test_relationship_validator.py +++ b/tests/spdx/validation/test_relationship_validator.py @@ -7,10 +7,7 @@ import pytest from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.document import Document -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import Document, Relationship, RelationshipType, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.validation.relationship_validator import validate_relationship from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage from tests.spdx.fixtures import document_fixture, relationship_fixture diff --git a/tests/spdx/writer/rdf/test_checksum_writer.py b/tests/spdx/writer/rdf/test_checksum_writer.py index 28b4012be..bbfa7358a 100644 --- a/tests/spdx/writer/rdf/test_checksum_writer.py +++ b/tests/spdx/writer/rdf/test_checksum_writer.py @@ -4,7 +4,7 @@ import pytest from rdflib import RDF, Graph, Literal, URIRef -from spdx_tools.spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx.model import ChecksumAlgorithm from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx_tools.spdx.writer.rdf.checksum_writer import add_checksum_to_graph, algorithm_to_rdf_string from tests.spdx.fixtures import checksum_fixture diff --git a/tests/spdx/writer/rdf/test_package_writer.py b/tests/spdx/writer/rdf/test_package_writer.py index 3b5fde09b..2c0d5abbd 100644 --- a/tests/spdx/writer/rdf/test_package_writer.py +++ b/tests/spdx/writer/rdf/test_package_writer.py @@ -5,7 +5,7 @@ from rdflib import DOAP, RDF, RDFS, XSD, Graph, Literal, URIRef from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string -from spdx_tools.spdx.model.package import ExternalPackageRefCategory +from spdx_tools.spdx.model import ExternalPackageRefCategory from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE from spdx_tools.spdx.writer.rdf.package_writer import ( add_external_package_ref_to_graph, diff --git a/tests/spdx/writer/rdf/test_rdf_writer.py b/tests/spdx/writer/rdf/test_rdf_writer.py index 8b19eef0d..da6ae01bf 100644 --- a/tests/spdx/writer/rdf/test_rdf_writer.py +++ b/tests/spdx/writer/rdf/test_rdf_writer.py @@ -5,7 +5,7 @@ import pytest -from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.writer.rdf.rdf_writer import write_document_to_file from tests.spdx.fixtures import document_fixture diff --git a/tests/spdx/writer/tagvalue/test_checksum_writer.py b/tests/spdx/writer/tagvalue/test_checksum_writer.py index 2208fc207..ddc2474e0 100644 --- a/tests/spdx/writer/tagvalue/test_checksum_writer.py +++ b/tests/spdx/writer/tagvalue/test_checksum_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx_tools.spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx.model import ChecksumAlgorithm from spdx_tools.spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value from tests.spdx.fixtures import checksum_fixture diff --git a/tests/spdx/writer/tagvalue/test_creation_info_writer.py b/tests/spdx/writer/tagvalue/test_creation_info_writer.py index a1a6a982b..133364c37 100644 --- a/tests/spdx/writer/tagvalue/test_creation_info_writer.py +++ b/tests/spdx/writer/tagvalue/test_creation_info_writer.py @@ -7,7 +7,7 @@ import pytest from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID -from spdx_tools.spdx.model.document import CreationInfo +from spdx_tools.spdx.model import CreationInfo from spdx_tools.spdx.writer.tagvalue.creation_info_writer import write_creation_info from tests.spdx.fixtures import actor_fixture, creation_info_fixture diff --git a/tests/spdx/writer/tagvalue/test_relationship_writer.py b/tests/spdx/writer/tagvalue/test_relationship_writer.py index 8ff940809..9b207c33b 100644 --- a/tests/spdx/writer/tagvalue/test_relationship_writer.py +++ b/tests/spdx/writer/tagvalue/test_relationship_writer.py @@ -5,8 +5,7 @@ import pytest -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx_tools.spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone from spdx_tools.spdx.writer.tagvalue.relationship_writer import write_relationship from tests.spdx.fixtures import relationship_fixture diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py index ad2ccd6ef..995687ce5 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py @@ -7,10 +7,7 @@ import pytest -from spdx_tools.spdx.model.file import File -from spdx_tools.spdx.model.package import Package -from spdx_tools.spdx.model.relationship import Relationship, RelationshipType -from spdx_tools.spdx.model.snippet import Snippet +from spdx_tools.spdx.model import File, Package, Relationship, RelationshipType, Snippet from spdx_tools.spdx.parser.tagvalue import tagvalue_parser from spdx_tools.spdx.writer.tagvalue.tagvalue_writer import write_document, write_document_to_file from tests.spdx.fixtures import checksum_fixture, document_fixture diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py index b7c884dc2..d101fd37c 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer_helper_functions.py @@ -5,9 +5,7 @@ import pytest -from spdx_tools.spdx.model.actor import ActorType -from spdx_tools.spdx.model.relationship import RelationshipType -from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model import ActorType, RelationshipType, SpdxNoAssertion from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import scan_relationships, write_actor from tests.spdx.fixtures import actor_fixture, file_fixture, package_fixture, relationship_fixture From c1f0b1f4ed1979f83c6c1c1cb53e9ed9fa49470b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 19 Apr 2023 16:12:18 +0200 Subject: [PATCH 063/354] [issue-593] add spdx2_document_from_scratch example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- README.md | 10 +- examples/spdx2_document_from_scratch.py | 145 ++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 examples/spdx2_document_from_scratch.py diff --git a/README.md b/README.md index e5c345b26..eeb17f368 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ instead of `bin`. ## Library usage 1. **DATA MODEL** - * The `spdx_tools.spdx.model` package constitutes the internal SPDX v2.3 data model (v2.2 is a simply a subset of this). All relevant classes for SPDX document creation are exposed in the [__init__.py](src%2Fspdx_tools%2Fspdx%2Fmodel%2F__init__.py). + * The `spdx_tools.spdx.model` package constitutes the internal SPDX v2.3 data model (v2.2 is simply a subset of this). All relevant classes for SPDX document creation are exposed in the `__init__.py` found [here](src%2Fspdx_tools%2Fspdx%2Fmodel%2F__init__.py). * SPDX objects are implemented via `@dataclass_with_properties`, a custom extension of `@dataclass`. * Each class starts with a list of its properties and their possible types. When no default value is provided, the property is mandatory and must be set during initialization. * Using the type hints, type checking is enforced when initializing a new instance or setting/getting a property on an instance @@ -117,15 +117,15 @@ instead of `bin`. Caution: Only valid documents can be serialized reliably; serialization of invalid documents is not supported. ## Example -Here are some examples of possible use cases to quickly get you started with the spdx-tools: +Here are some examples of possible use cases to quickly get you started with the spdx-tools. +If you want a more comprehensive example about how to create an SPDX document from scratch, have a look [here](examples%2Fspdx2_document_from_scratch.py). ```python import logging from license_expression import get_spdx_licensing -from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm -from spdx_tools.spdx.model import File, FileType -from spdx_tools.spdx.model import Relationship, RelationshipType +from spdx_tools.spdx.model import (Checksum, ChecksumAlgorithm, File, + FileType, Relationship, RelationshipType) from spdx_tools.spdx.parser.parse_anything import parse_file from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document from spdx_tools.spdx.writer.write_anything import write_file diff --git a/examples/spdx2_document_from_scratch.py b/examples/spdx2_document_from_scratch.py new file mode 100644 index 000000000..24276d307 --- /dev/null +++ b/examples/spdx2_document_from_scratch.py @@ -0,0 +1,145 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import logging +from datetime import datetime +from typing import List + +from license_expression import get_spdx_licensing + +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Checksum, + ChecksumAlgorithm, + CreationInfo, + Document, + ExternalPackageRef, + ExternalPackageRefCategory, + File, + FileType, + Package, + PackagePurpose, + PackageVerificationCode, + Relationship, + RelationshipType, +) +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.writer.write_anything import write_file + +# This example shows how to use the spdx-tools to create an SPDX document from scratch, +# validate it and write it to a file. + +# First up, we need general information about the creation of the document, summarised by the CreationInfo class. +creation_info = CreationInfo( + spdx_version="SPDX-2.3", + spdx_id="SPDXRef-DOCUMENT", + name="document name", + data_license="CC0-1.0", + document_namespace="https://some.namespace", + creators=[Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com")], + created=datetime(2022, 1, 1), +) + +# creation_info is the only required property of the Document class (have a look there!), the rest are optional lists. +# So, we are set up to create a new document instance. +document = Document(creation_info) + +# The document currently does not describe anything. Let's create a package that we can add to it. +# The Package class has quite a few properties (have a look there!), +# but only name, spdx_id and download_location are mandatory in SPDX v2.3. +package = Package( + name="package name", + spdx_id="SPDXRef-Package", + download_location="https://download.com", + version="2.2.1", + file_name="./foo.bar", + supplier=Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com"), + originator=Actor(ActorType.ORGANIZATION, "some organization", "contact@example.com"), + files_analyzed=True, + verification_code=PackageVerificationCode( + value="d6a770ba38583ed4bb4525bd96e50461655d2758", excluded_files=["./some.file"] + ), + checksums=[ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), + Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), + ], + license_concluded=get_spdx_licensing().parse("GPL-2.0-only OR MIT"), + license_info_from_files=[get_spdx_licensing().parse("GPL-2.0-only"), get_spdx_licensing().parse("MIT")], + license_declared=get_spdx_licensing().parse("GPL-2.0-only AND MIT"), + license_comment="license comment", + copyright_text="Copyright 2022 Jane Doe", + description="package description", + attribution_texts=["package attribution"], + primary_package_purpose=PackagePurpose.LIBRARY, + release_date=datetime(2015, 1, 1), + external_references=[ + ExternalPackageRef( + category=ExternalPackageRefCategory.OTHER, + reference_type="http://reference.type", + locator="reference/locator", + comment="external reference comment", + ) + ], +) + +# Now that we have a package defined, we can add it to the document's package property. +document.packages = [package] + +# A DESCRIBES relationship asserts that the document indeed describes the package. +describes_relationship = Relationship("SPDXRef-Document", RelationshipType.DESCRIBES, "SPDXRef-Package") +document.relationships = [describes_relationship] + +# Let's add two files. Have a look at the file class for all possible properties a file can have. +file1 = File( + name="./package/file1.py", + spdx_id="SPDXRef-File1", + file_types=[FileType.SOURCE], + checksums=[ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), + Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), + ], + license_concluded=get_spdx_licensing().parse("MIT"), + license_info_in_file=[get_spdx_licensing().parse("MIT")], + copyright_text="Copyright 2022 Jane Doe", +) +file2 = File( + name="./package/file2.py", + spdx_id="SPDXRef-File2", + checksums=[ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2759"), + ], + license_concluded=get_spdx_licensing().parse("GPL-2.0-only"), +) + +# Assuming the package contains those two files, we create two CONTAINS relationships. +contains_relationship1 = Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File1") +contains_relationship2 = Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File2") + +# This library uses run-time type checks when assigning properties. +# Because in-place alterations like .append() circumvent these checks, we don't use them here. +document.relationships += [contains_relationship1, contains_relationship2] + +# We now have created a document with basic creation information, describing a package that contains two files. +# You can also add Annotations, Snippets and ExtractedLicensingInfo to the document in an analogous manner to the above. +# Have a look at their respective classes if you are unsure about their properties. + + +# This library provides comprehensive validation against the SPDX specification. +# Note that details of the validation depend on the SPDX version of the document. +validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) + +# You can have a look at each entry's message and context (like spdx_id, parent_id, full_element) +# which will help you pinpoint the location of the invalidity. +for message in validation_messages: + logging.warning(message.validation_message) + logging.warning(message.context) + +# If the document is valid, validation_messages will be empty. +assert validation_messages == [] + +# Finally, we can serialize the document to any of the five supported formats. +# Using the write_file() method from the write_anything module, +# the format will be determined by the file ending: .spdx (tag-value), .json, .xml, .yaml. or .rdf (or .rdf.xml) +write_file(document, "my_spdx_document.spdx.json") From 3cf29da6f524dff52e97bef138dae0765d6f9606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 20 Apr 2023 08:23:53 +0200 Subject: [PATCH 064/354] make flake8 ignore all __init__.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .flake8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.flake8 b/.flake8 index 9402046ea..e2c6e5910 100644 --- a/.flake8 +++ b/.flake8 @@ -1,4 +1,4 @@ [flake8] max-line-length = 119 -exclude = src/spdx_tools/spdx/parser/tagvalue/parsetab.py, src/spdx_tools/spdx/model/__init__.py +exclude = src/spdx_tools/spdx/parser/tagvalue/parsetab.py, __init__.py extend-ignore = E203 From fdb908472bb26b05313035aa532c69b138d63955 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 24 Apr 2023 08:36:47 +0200 Subject: [PATCH 065/354] make example files valid Signed-off-by: Meret Behrens --- tests/spdx/data/SPDXXMLExample-v2.3.spdx.xml | 2 +- tests/spdx/data/SPDXYAMLExample-v2.3.spdx.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/spdx/data/SPDXXMLExample-v2.3.spdx.xml b/tests/spdx/data/SPDXXMLExample-v2.3.spdx.xml index e42b54e0f..ce25dbc09 100644 --- a/tests/spdx/data/SPDXXMLExample-v2.3.spdx.xml +++ b/tests/spdx/data/SPDXXMLExample-v2.3.spdx.xml @@ -267,7 +267,7 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. PACKAGE-MANAGER pkg:maven/org.apache.jena/apache-jena@3.12.0 - http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#purl + purl false http://www.openjena.org/ diff --git a/tests/spdx/data/SPDXYAMLExample-v2.3.spdx.yaml b/tests/spdx/data/SPDXYAMLExample-v2.3.spdx.yaml index e0190e38b..9770f71dd 100644 --- a/tests/spdx/data/SPDXYAMLExample-v2.3.spdx.yaml +++ b/tests/spdx/data/SPDXYAMLExample-v2.3.spdx.yaml @@ -232,7 +232,7 @@ packages: externalRefs: - referenceCategory: "PACKAGE-MANAGER" referenceLocator: "pkg:maven/org.apache.jena/apache-jena@3.12.0" - referenceType: "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#purl" + referenceType: "purl" filesAnalyzed: false homepage: "http://www.openjena.org/" name: "Jena" From fa2e9fe19e69c6f0e44564cd5b84d5e2bd0d9e17 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 24 Apr 2023 15:52:58 +0200 Subject: [PATCH 066/354] [issue-611] set list like fields to empty lists if tags are empty Signed-off-by: Meret Behrens --- src/spdx_tools/spdx/parser/xml/xml_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx/parser/xml/xml_parser.py b/src/spdx_tools/spdx/parser/xml/xml_parser.py index 52863f389..4dd8c3aa2 100644 --- a/src/spdx_tools/spdx/parser/xml/xml_parser.py +++ b/src/spdx_tools/spdx/parser/xml/xml_parser.py @@ -58,7 +58,7 @@ def _fix_list_like_fields(data: Any) -> Any: new_data = {} for key, value in data.items(): if key in LIST_LIKE_FIELDS and not isinstance(value, list): - new_data[key] = [_fix_list_like_fields(value)] + new_data[key] = [_fix_list_like_fields(value)] if value else [] else: new_data[key] = _fix_list_like_fields(value) return new_data From 0843139ae7a92c0a132b9915a2358a70c3723d3c Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 24 Apr 2023 15:53:54 +0200 Subject: [PATCH 067/354] [issue-611] use list helper methods for creators to raise an error if no creators provided Signed-off-by: Meret Behrens --- .../jsonlikedict/creation_info_parser.py | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py index dbad22d11..1e7015c50 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py @@ -9,11 +9,7 @@ from spdx_tools.spdx.parser.actor_parser import ActorParser from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.checksum_parser import ChecksumParser -from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import ( - append_parsed_field_or_log_error, - parse_field_or_log_error, - parse_field_or_no_assertion, -) +from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_log_error from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.parser.parsing_functions import ( construct_or_raise_parsing_error, @@ -45,7 +41,7 @@ def parse_creation_info(self, doc_dict: Dict) -> CreationInfo: raise SPDXParsingError([f"Error while parsing document {name}: {logger.get_messages()}"]) creators: List[Actor] = parse_field_or_log_error( - logger, creation_info_dict.get("creators"), self.parse_creators + logger, creation_info_dict.get("creators"), self.actor_parser.parse_actor, field_is_list=True ) created: Optional[datetime] = parse_field_or_log_error( @@ -83,17 +79,6 @@ def parse_creation_info(self, doc_dict: Dict) -> CreationInfo: return creation_info - def parse_creators(self, creators_list_from_dict: List[str]) -> List[Actor]: - logger = Logger() - creators = [] - for creator_str in creators_list_from_dict: - creators = append_parsed_field_or_log_error( - logger, creators, creator_str, lambda x: parse_field_or_no_assertion(x, self.actor_parser.parse_actor) - ) - - raise_parsing_error_if_logger_has_messages(logger) - return creators - @staticmethod def parse_version(version_str: str) -> Version: try: From f0f41bcda6dec3730f70925be7efe45eb024ce1e Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 24 Apr 2023 16:14:53 +0200 Subject: [PATCH 068/354] [issue-611] fix logging Signed-off-by: Meret Behrens --- .../spdx/parser/jsonlikedict/dict_parsing_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py b/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py index 6320b5bc0..c5076d2bf 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py @@ -45,7 +45,7 @@ def append_parsed_field_or_log_error( except SPDXParsingError as err: logger.extend(err.get_messages()) except (TypeError, ValueError) as err: - logger.extend(err.args[0]) + logger.append(err.args[0]) return list_to_append_to From 4a192bce2205fb4f473577cd48eb5766875c1143 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 25 Apr 2023 08:43:45 +0200 Subject: [PATCH 069/354] [issue-511] add license header Signed-off-by: Meret Behrens --- src/spdx_tools/spdx/model/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/spdx_tools/spdx/model/__init__.py b/src/spdx_tools/spdx/model/__init__.py index cec8cfe19..e27a116d0 100644 --- a/src/spdx_tools/spdx/model/__init__.py +++ b/src/spdx_tools/spdx/model/__init__.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx_tools.spdx.model.spdx_none import SpdxNone from spdx_tools.spdx.model.version import Version From 78c5f993659adef4dfb19e2f4b715628feb9fcf7 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 25 Apr 2023 09:31:05 +0200 Subject: [PATCH 070/354] [issue-615] raise SPDXParsingError when CreationInfo can't be parsed since the following code is based on a correct initialization of CreationInfo Signed-off-by: Meret Behrens --- src/spdx_tools/spdx/parser/rdf/rdf_parser.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/spdx_tools/spdx/parser/rdf/rdf_parser.py b/src/spdx_tools/spdx/parser/rdf/rdf_parser.py index 70236cd0d..d6406f3f0 100644 --- a/src/spdx_tools/spdx/parser/rdf/rdf_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/rdf_parser.py @@ -35,11 +35,7 @@ def parse_from_file(file_name: str) -> Document: def translate_graph_to_document(graph: Graph) -> Document: parsed_fields: Dict[str, Any] = dict() logger = Logger() - try: - creation_info, doc_node = parse_creation_info(graph) - except SPDXParsingError as err: - logger.extend(err.get_messages()) - creation_info = None + creation_info, doc_node = parse_creation_info(graph) parsed_fields["creation_info"] = creation_info From 693820cb2b4af3980e49ecc66efb1b46a2d1aa59 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 25 Apr 2023 09:31:30 +0200 Subject: [PATCH 071/354] [issue-615] log error when no creators provided Signed-off-by: Meret Behrens --- src/spdx_tools/spdx/parser/rdf/creation_info_parser.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py b/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py index c21276a53..36376b128 100644 --- a/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py @@ -61,6 +61,8 @@ def parse_creation_info(graph: Graph) -> Tuple[CreationInfo, URIRef]: logger, graph, creation_info_node, SPDX_NAMESPACE.creator ): creators.append(ActorParser.parse_actor(creator_literal.toPython())) + if not creators: + logger.append("No creators provided.") external_document_refs = [] for _, _, external_document_node in get_correctly_typed_triples( logger, graph, doc_node, SPDX_NAMESPACE.externalDocumentRef From 1957d0fcffd9de5e24bc784624b7c67dca804533 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 25 Apr 2023 10:53:57 +0200 Subject: [PATCH 072/354] [issue-615] add test Signed-off-by: Meret Behrens --- .../invalid_creation_info.rdf.xml | 18 +++++ ...invalid_creation_info_with_snippet.rdf.xml | 79 +++++++++++++++++++ .../parser/rdf/test_creation_info_parser.py | 19 +++++ 3 files changed, 116 insertions(+) create mode 100644 tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info.rdf.xml create mode 100644 tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info_with_snippet.rdf.xml diff --git a/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info.rdf.xml b/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info.rdf.xml new file mode 100644 index 000000000..60178b010 --- /dev/null +++ b/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info.rdf.xml @@ -0,0 +1,18 @@ + + + + documentComment + documentName + + + + 3.19 + + + + + diff --git a/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info_with_snippet.rdf.xml b/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info_with_snippet.rdf.xml new file mode 100644 index 000000000..4cccb26e8 --- /dev/null +++ b/tests/spdx/parser/rdf/data/invalid_documents/invalid_creation_info_with_snippet.rdf.xml @@ -0,0 +1,79 @@ + + + + SPDX-2.3 + + + https://see.also + extractedText + LicenseRef-1 + licenseComment + licenseName + + + documentComment + documentName + + + + creatorComment + 3.19 + + + + + + + + + + + 3 + + + + + + 4 + + + + + + + + + 1 + + + + + + + 2 + + + + + + + + + snippetAttributionText + snippetName + snippetLicenseComment + snippetComment + licenseCopyrightText + + + + + + + + diff --git a/tests/spdx/parser/rdf/test_creation_info_parser.py b/tests/spdx/parser/rdf/test_creation_info_parser.py index 606a2f126..d6fbcf81f 100644 --- a/tests/spdx/parser/rdf/test_creation_info_parser.py +++ b/tests/spdx/parser/rdf/test_creation_info_parser.py @@ -11,11 +11,13 @@ from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID from spdx_tools.spdx.model import Actor, ActorType, Checksum, ChecksumAlgorithm, Version +from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.rdf.creation_info_parser import ( parse_creation_info, parse_external_document_refs, parse_namespace_and_spdx_id, ) +from spdx_tools.spdx.parser.rdf.rdf_parser import parse_from_file from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE @@ -90,3 +92,20 @@ def test_parse_external_document_refs(): ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c" ) assert external_document_ref.document_uri == "https://namespace.com" + + +@pytest.mark.parametrize( + "file, error_message", + [ + ( + "invalid_creation_info.rdf.xml", + "Error while parsing CreationInfo: ['No creators provided.']", + ), + ("invalid_creation_info_with_snippet.rdf.xml", "Error while parsing CreationInfo: ['No creators provided.']"), + ], +) +def test_parse_invalid_creation_info(file, error_message): + with pytest.raises(SPDXParsingError) as err: + parse_from_file(os.path.join(os.path.dirname(__file__), f"data/invalid_documents/{file}")) + + assert err.value.get_messages() == [error_message] From 9e9ae0a92685dd1ef42992c2ae1b35a59555f413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 25 Apr 2023 11:54:35 +0200 Subject: [PATCH 073/354] make pytest not skip test_build folders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 7ec03780b..0772fe81c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,3 +62,6 @@ include = "(^/src/.*.py|^/tests/.*.py)" profile = "black" line_length = 119 skip = ["__init__.py"] + +[tool.pytest.ini_options] +norecursedirs = [] # overwrite the default to not skip tests/build folder which is needed in spdx3 From 3c50775bd6a5df3a1c3e4618ae8a91d9fc0bcee2 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 4 May 2023 15:44:58 +0200 Subject: [PATCH 074/354] fix link to migration guide Signed-off-by: Meret Behrens --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eeb17f368..e2a502530 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ We encourage you to use the new, refactored version (on the main branch) if you - want to use the RDF format of SPDX with all v2.3 features. If you are planning to migrate from v0.7.x of these tools, -please have a look at the [migration guide](https://github.com/spdx/tools-python/wiki/How-to-migrate-from-0.7-to-1.0). +please have a look at the [migration guide](https://github.com/spdx/tools-python/wiki/How-to-migrate-from-0.7-to-0.8). # Information From 435b0e8dff442234f05e5f98eba90b7711b52208 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 12 May 2023 11:31:54 +0200 Subject: [PATCH 075/354] [issue-649] log error if the build of a contains relationship fails due to a non-parseable preceding package Signed-off-by: Meret Behrens --- src/spdx_tools/spdx/parser/tagvalue/parser.py | 6 +++++ .../parser/tagvalue/test_tag_value_parser.py | 25 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/spdx_tools/spdx/parser/tagvalue/parser.py b/src/spdx_tools/spdx/parser/tagvalue/parser.py index e6ce74dc4..623226b8f 100644 --- a/src/spdx_tools/spdx/parser/tagvalue/parser.py +++ b/src/spdx_tools/spdx/parser/tagvalue/parser.py @@ -580,6 +580,12 @@ def check_for_preceding_package_and_build_contains_relationship(self): # information that follows any package information is assigned to the last parsed package by creating a # corresponding contains relationship. # (see https://spdx.github.io/spdx-spec/v2.3/composition-of-an-SPDX-document/#5.2.2) + if not self.elements_built["packages"]: + self.logger.append( + f"Error while building contains relationship for file {file_spdx_id}, " + f"preceding package was not parsed successfully." + ) + return package_spdx_id = self.elements_built["packages"][-1].spdx_id relationship = Relationship(package_spdx_id, RelationshipType.CONTAINS, file_spdx_id) if relationship not in self.elements_built.setdefault("relationships", []): diff --git a/tests/spdx/parser/tagvalue/test_tag_value_parser.py b/tests/spdx/parser/tagvalue/test_tag_value_parser.py index cb5381489..33defcb9d 100644 --- a/tests/spdx/parser/tagvalue/test_tag_value_parser.py +++ b/tests/spdx/parser/tagvalue/test_tag_value_parser.py @@ -54,6 +54,31 @@ def test_building_contains_relationship(): ] +def test_build_contains_relationship_with_error(): + parser = Parser() + file_spdx_ids = ["SPDXRef-File-in-Package", "SPDXRef-Second-File-in-Package"] + document_str = "\n".join( + [ + DOCUMENT_STR, + "PackageName: Package with two files", + "PackageDownloadLocation: https://download.com", + "FileName: File in package", + f"SPDXID: {file_spdx_ids[0]}", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + "FileName: Second file in package", + f"SPDXID: {file_spdx_ids[1]}", + "FileChecksum: SHA1: d6a770ba38583ed4bb4525bd96e50461655d2759", + ] + ) + with pytest.raises(SPDXParsingError) as err: + parser.parse(document_str) + for file_spdx_id in file_spdx_ids: + assert ( + f"Error while building contains relationship for file {file_spdx_id}, preceding package was not " + "parsed successfully." in err.value.get_messages() + ) + + def test_document_with_mixed_values(): parser = Parser() document_str = "\n".join( From 6a7e5002c380ccfc4da73868477538c57a78468d Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 12 May 2023 14:33:25 +0200 Subject: [PATCH 076/354] fix wrapper methods for parsing the rdf graph Signed-off-by: Meret Behrens --- src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py | 2 +- src/spdx_tools/spdx/parser/rdf/package_parser.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py b/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py index 8ed8faff0..ef1a505db 100644 --- a/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py +++ b/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py @@ -140,7 +140,7 @@ def get_value_from_graph( # this is a helper method to cast some rdf types from graph.value() to be compatible with the # code that follows value = graph.value(subject=subject, predicate=predicate, object=_object, default=default, any=_any) - if value and not isinstance(value, (URIRef, Literal, BNode)): + if value != default and value is not None and not isinstance(value, (URIRef, Literal, BNode)): logger.append( f"Warning: Node {value} should be of type BNode, Literal or URIRef, but is {type(value).__name__}. " f"This might lead to a failure." diff --git a/src/spdx_tools/spdx/parser/rdf/package_parser.py b/src/spdx_tools/spdx/parser/rdf/package_parser.py index a3de07749..1cb6a72e4 100644 --- a/src/spdx_tools/spdx/parser/rdf/package_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/package_parser.py @@ -108,7 +108,9 @@ def parse_package(package_node: URIRef, graph: Graph, doc_namespace: str) -> Pac ) homepage = parse_literal(logger, graph, package_node, DOAP.homepage) attribution_texts = [] - for _, _, attribution_text_literal in graph.triples((package_node, SPDX_NAMESPACE.attributionText, None)): + for _, _, attribution_text_literal in get_correctly_typed_triples( + logger, graph, package_node, SPDX_NAMESPACE.attributionText, None + ): attribution_texts.append(attribution_text_literal.toPython()) release_date = parse_literal( From acf56a07dfa4de6a790c7ad66de244d535a6c08c Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 12 May 2023 14:33:16 +0200 Subject: [PATCH 077/354] [issue-650] raise ParsingError if elements don't have an SPDXID Signed-off-by: Meret Behrens --- src/spdx_tools/spdx/parser/rdf/file_parser.py | 6 ++- .../parser/rdf/graph_parsing_functions.py | 4 +- .../spdx/parser/rdf/package_parser.py | 5 +- .../spdx/parser/rdf/snippet_parser.py | 4 +- .../file_without_spdx_ids.xml | 53 +++++++++++++++++++ tests/spdx/parser/rdf/test_file_parser.py | 19 ++++++- tests/spdx/parser/rdf/test_package_parser.py | 16 ++++++ tests/spdx/parser/rdf/test_snippet_parser.py | 16 ++++++ 8 files changed, 113 insertions(+), 10 deletions(-) create mode 100644 tests/spdx/parser/rdf/data/invalid_documents/file_without_spdx_ids.xml diff --git a/src/spdx_tools/spdx/parser/rdf/file_parser.py b/src/spdx_tools/spdx/parser/rdf/file_parser.py index 18512fe6c..83e61b4a5 100644 --- a/src/spdx_tools/spdx/parser/rdf/file_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/file_parser.py @@ -1,7 +1,9 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from rdflib import RDFS, Graph, URIRef +from typing import Union + +from rdflib import RDFS, BNode, Graph, URIRef from spdx_tools.spdx.model import File, FileType from spdx_tools.spdx.parser.logger import Logger @@ -23,7 +25,7 @@ from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE -def parse_file(file_node: URIRef, graph: Graph, doc_namespace: str) -> File: +def parse_file(file_node: Union[URIRef, BNode], graph: Graph, doc_namespace: str) -> File: logger = Logger() spdx_id = parse_spdx_id(file_node, doc_namespace, graph) name = parse_literal(logger, graph, file_node, SPDX_NAMESPACE.fileName) diff --git a/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py b/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py index ef1a505db..257367595 100644 --- a/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py +++ b/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py @@ -86,8 +86,8 @@ def parse_enum_value(enum_str: str, enum_class: Type[Enum], prefix: str) -> Enum raise SPDXParsingError([f"Invalid value for {enum_class}: {enum_str}"]) -def parse_spdx_id(resource: URIRef, doc_namespace: str, graph: Graph) -> Optional[str]: - if not resource: +def parse_spdx_id(resource: Union[URIRef, BNode], doc_namespace: str, graph: Graph) -> Optional[str]: + if not resource or isinstance(resource, BNode): return None if resource.startswith(f"{doc_namespace}#"): return resource.fragment diff --git a/src/spdx_tools/spdx/parser/rdf/package_parser.py b/src/spdx_tools/spdx/parser/rdf/package_parser.py index 1cb6a72e4..a0de0e904 100644 --- a/src/spdx_tools/spdx/parser/rdf/package_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/package_parser.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Optional +from typing import Optional, Union from rdflib import DOAP, RDFS, Graph, URIRef from rdflib.term import BNode @@ -34,7 +34,7 @@ from spdx_tools.spdx.rdfschema.namespace import REFERENCE_NAMESPACE, SPDX_NAMESPACE -def parse_package(package_node: URIRef, graph: Graph, doc_namespace: str) -> Package: +def parse_package(package_node: Union[URIRef, BNode], graph: Graph, doc_namespace: str) -> Package: logger = Logger() spdx_id = parse_spdx_id(package_node, doc_namespace, graph) name = parse_literal(logger, graph, package_node, SPDX_NAMESPACE.name) @@ -120,7 +120,6 @@ def parse_package(package_node: URIRef, graph: Graph, doc_namespace: str) -> Pac valid_until_date = parse_literal( logger, graph, package_node, SPDX_NAMESPACE.validUntilDate, parsing_method=datetime_from_str ) - raise_parsing_error_if_logger_has_messages(logger, "Package") package = construct_or_raise_parsing_error( Package, diff --git a/src/spdx_tools/spdx/parser/rdf/snippet_parser.py b/src/spdx_tools/spdx/parser/rdf/snippet_parser.py index b26d6cdfc..e59076654 100644 --- a/src/spdx_tools/spdx/parser/rdf/snippet_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/snippet_parser.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict, Optional, Tuple +from typing import Dict, Optional, Tuple, Union from rdflib import RDF, RDFS, Graph from rdflib.exceptions import UniquenessError @@ -27,7 +27,7 @@ from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE -def parse_snippet(snippet_node: URIRef, graph: Graph, doc_namespace: str) -> Snippet: +def parse_snippet(snippet_node: Union[URIRef, BNode], graph: Graph, doc_namespace: str) -> Snippet: logger = Logger() spdx_id = parse_spdx_id(snippet_node, doc_namespace, graph) file_spdx_id_uri = get_value_from_graph( diff --git a/tests/spdx/parser/rdf/data/invalid_documents/file_without_spdx_ids.xml b/tests/spdx/parser/rdf/data/invalid_documents/file_without_spdx_ids.xml new file mode 100644 index 000000000..23fe6c7de --- /dev/null +++ b/tests/spdx/parser/rdf/data/invalid_documents/file_without_spdx_ids.xml @@ -0,0 +1,53 @@ + + + + documentComment + documentName + + + + 3.19 + 2022-12-01T00:00:00Z + + + + + packageName + http://differentdownload.com + + + + + + 71c4025dd9897b364f3ebbb42c484ff43d00791c + + + ./fileName.py + + + + + + + 1 + + + + + + + 2 + + + + + + + + + diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py index fb24ed0da..3fe36c267 100644 --- a/tests/spdx/parser/rdf/test_file_parser.py +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -4,10 +4,12 @@ import os from unittest import TestCase +import pytest from license_expression import get_spdx_licensing -from rdflib import RDF, Graph, URIRef +from rdflib import RDF, BNode, Graph, URIRef from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, FileType, SpdxNoAssertion +from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.rdf.file_parser import parse_file from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE @@ -35,3 +37,18 @@ def test_parse_file(): assert file.license_comment == "licenseComment" assert file.notice == "fileNotice" assert file.attribution_texts == ["fileAttributionText"] + + +def test_parse_invalid_file(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/invalid_documents/file_without_spdx_ids.xml")) + file_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.File) + doc_namespace = "https://some.namespace" + + assert isinstance(file_node, BNode) + with pytest.raises(SPDXParsingError) as err: + parse_file(file_node, graph, doc_namespace) + + assert err.value.get_messages() == [ + "Error while constructing File: ['SetterError File: type of argument " + '"spdx_id" must be str; got NoneType instead: None\']' + ] diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index f6c968073..9d2bcfc1f 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -18,6 +18,7 @@ PackageVerificationCode, SpdxNoAssertion, ) +from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.rdf.package_parser import parse_external_package_ref, parse_package from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE @@ -95,3 +96,18 @@ def test_external_package_ref_parser(download_location, category, locator, type, assert external_package_ref.locator == locator assert external_package_ref.reference_type == type assert external_package_ref.comment == comment + + +def test_parse_invalid_package(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/invalid_documents/file_without_spdx_ids.xml")) + package_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Package) + doc_namespace = "https://some.namespace" + + assert isinstance(package_node, BNode) + with pytest.raises(SPDXParsingError) as err: + parse_package(package_node, graph, doc_namespace) + + assert err.value.get_messages() == [ + "Error while constructing Package: ['SetterError Package: type of argument " + '"spdx_id" must be str; got NoneType instead: None\']' + ] diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index 1b4022827..73970035b 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -159,3 +159,19 @@ def add_range_to_graph_helper(graph, predicate_value_class_member): graph.add((pointer_node, RDF.type, pointer_class)) graph.add((start_end_pointer, predicate, pointer_node)) graph.add((pointer_node, pointer_member, Literal(value))) + + +def test_parse_invalid_file(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/invalid_documents/file_without_spdx_ids.xml")) + snippet_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Snippet) + doc_namespace = "https://some.namespace" + + assert isinstance(snippet_node, BNode) + with pytest.raises(SPDXParsingError) as err: + parse_snippet(snippet_node, graph, doc_namespace) + + assert err.value.get_messages() == [ + "Error while constructing Snippet: ['SetterError Snippet: type of argument " + "\"spdx_id\" must be str; got NoneType instead: None', 'SetterError Snippet: " + 'type of argument "file_spdx_id" must be str; got NoneType instead: None\']' + ] From d8c5448d4621fdd982339ff47a94319687d83189 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 03:03:45 +0000 Subject: [PATCH 078/354] Bump typeguard from 2.13.3 to 4.0.0 Bumps [typeguard](https://github.com/agronholm/typeguard) from 2.13.3 to 4.0.0. - [Changelog](https://github.com/agronholm/typeguard/blob/master/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/typeguard/compare/2.13.3...4.0.0) --- updated-dependencies: - dependency-name: typeguard dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0772fe81c..52590bca7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ classifiers = [ ] urls = { Homepage = "https://github.com/spdx/tools-python" } requires-python = ">=3.7" -dependencies = ["click", "pyyaml", "xmltodict", "rdflib", "typeguard==2.13.3", "uritools", "license_expression", "ply"] +dependencies = ["click", "pyyaml", "xmltodict", "rdflib", "typeguard==4.0.0", "uritools", "license_expression", "ply"] dynamic = ["version"] [project.optional-dependencies] From 6b45bbda442464adc12f26135a8f953c743c30d2 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 15 May 2023 12:52:29 +0200 Subject: [PATCH 079/354] fix tests due to upgrade of typeguard - the error raised is a `TypeCheckError` - we need to enable the CollectionCheckStrategy.ALL_ITEMS to check each instance in a collection - instead of checking the generated error messages for each class we only check that an error is raised for every class and use only one invalid package as a proxy for all other tests to check the generated message Signed-off-by: Meret Behrens --- .../typing/dataclass_with_properties.py | 14 ++-- .../jsonlikedict/test_annotation_parser.py | 36 ++------- .../jsonlikedict/test_checksum_parser.py | 10 +-- .../jsonlikedict/test_creation_info_parser.py | 41 ++-------- .../parser/jsonlikedict/test_error_message.py | 31 ++++++++ .../test_extracted_licensing_info_parser.py | 13 +--- .../parser/jsonlikedict/test_file_parser.py | 29 +------ .../jsonlikedict/test_package_parser.py | 75 ++++--------------- .../jsonlikedict/test_relationship_parser.py | 11 +-- .../jsonlikedict/test_snippet_parser.py | 24 +----- tests/spdx/parser/rdf/test_file_parser.py | 7 +- tests/spdx/parser/rdf/test_package_parser.py | 7 +- tests/spdx/parser/rdf/test_snippet_parser.py | 8 +- 13 files changed, 73 insertions(+), 233 deletions(-) create mode 100644 tests/spdx/parser/jsonlikedict/test_error_message.py diff --git a/src/spdx_tools/common/typing/dataclass_with_properties.py b/src/spdx_tools/common/typing/dataclass_with_properties.py index 644a1269e..af8fa7179 100644 --- a/src/spdx_tools/common/typing/dataclass_with_properties.py +++ b/src/spdx_tools/common/typing/dataclass_with_properties.py @@ -1,6 +1,8 @@ from dataclasses import dataclass -from typeguard import typechecked +from typeguard import CollectionCheckStrategy, TypeCheckError, config, typechecked + +config.collection_check_strategy = CollectionCheckStrategy.ALL_ITEMS def dataclass_with_properties(cls): @@ -26,11 +28,11 @@ def set_field(self, value: field_type): def set_field_with_better_error_message(self, value: field_type): try: set_field(self, value) - except TypeError as err: - error_message: str = f"SetterError {self.__class__.__name__}: {err.args[0]}" + except TypeCheckError as err: + error_message: str = f"SetterError {self.__class__.__name__}: {err}" # As setters are created dynamically, their argument name is always "value". We replace it by the # actual name so the error message is more helpful. - raise TypeError(error_message.replace("value", field_name, 1) + f": {value}") + raise TypeError(error_message.replace("value", field_name, 1)) return set_field_with_better_error_message @@ -45,8 +47,8 @@ def get_field(self) -> field_type: def get_field_with_better_error_message(self) -> field_type: try: return get_field(self) - except TypeError as err: - error_message: str = f"GetterError {self.__class__.__name__}: {err.args[0]}" + except TypeCheckError as err: + error_message: str = f"GetterError {self.__class__.__name__}: {err}" # As getters are created dynamically, their argument name is always "the return value". # We replace it by the actual name so the error message is more helpful. raise TypeError( diff --git a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py index 0460598e7..ac814d6cd 100644 --- a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py @@ -119,40 +119,14 @@ def test_parse_all_annotations(): @pytest.mark.parametrize( - "incomplete_annotation_dict,expected_message", + "incomplete_annotation_dict", [ - ( - {"annotator": "Person: Jane Doe ()"}, - [ - "Error while constructing Annotation: ['SetterError Annotation: type of " - 'argument "spdx_id" must be str; got NoneType instead: None\', ' - '\'SetterError Annotation: type of argument "annotation_type" must be ' - "spdx_tools.spdx.model.annotation.AnnotationType; got NoneType instead: None', " - '\'SetterError Annotation: type of argument "annotation_date" must be ' - "datetime.datetime; got NoneType instead: None', 'SetterError Annotation: " - 'type of argument "annotation_comment" must be str; got NoneType instead: ' - "None']" - ], - ), - ( - {"annotationDate": "2010-01-29T18:30:22Z"}, - [ - "Error while constructing Annotation: ['SetterError Annotation: type of " - 'argument "spdx_id" must be str; got NoneType instead: None\', ' - '\'SetterError Annotation: type of argument "annotation_type" must be ' - "spdx_tools.spdx.model.annotation.AnnotationType; got NoneType instead: None', " - '\'SetterError Annotation: type of argument "annotator" must be ' - "spdx_tools.spdx.model.actor.Actor; got NoneType instead: None', 'SetterError Annotation: " - 'type of argument "annotation_comment" must be str; got NoneType instead: ' - "None']" - ], - ), + {"annotator": "Person: Jane Doe ()"}, + {"annotationDate": "2010-01-29T18:30:22Z"}, ], ) -def test_parse_incomplete_annotation(incomplete_annotation_dict, expected_message): +def test_parse_incomplete_annotation(incomplete_annotation_dict): annotation_parser = AnnotationParser() - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): annotation_parser.parse_annotation(incomplete_annotation_dict) - - TestCase().assertCountEqual(err.value.get_messages(), expected_message) diff --git a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py index aa2bbbe8a..24676cccf 100644 --- a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py @@ -36,13 +36,5 @@ def test_parse_incomplete_checksum(): checksum_parser = ChecksumParser() checksum_dict = {"algorithm": "SHA1"} - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): checksum_parser.parse_checksum(checksum_dict) - - TestCase().assertCountEqual( - err.value.get_messages(), - [ - 'Error while constructing Checksum: [\'SetterError Checksum: type of argument "value" must be str; ' - "got NoneType instead: None']" - ], - ) diff --git a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py index 86535d703..1a9851016 100644 --- a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py @@ -60,37 +60,18 @@ def test_parse_creation_info(): @pytest.mark.parametrize( - "incomplete_dict,expected_message", + "incomplete_dict", [ - ( - {"spdxVersion": "2.3", "SPDXID": DOCUMENT_SPDX_ID, "name": "Example Document"}, - ["Error while parsing document Example Document: ['CreationInfo does not exist.']"], - ), - ( - {"creationInfo": {"created": "2019-02-01T11:30:40Z"}}, - [ - "Error while constructing CreationInfo: ['SetterError CreationInfo: type of " - 'argument "spdx_version" must be str; got NoneType instead: None\', ' - '\'SetterError CreationInfo: type of argument "spdx_id" must be str; got ' - "NoneType instead: None', 'SetterError CreationInfo: type of argument " - "\"name\" must be str; got NoneType instead: None', 'SetterError " - 'CreationInfo: type of argument "document_namespace" must be str; got ' - "NoneType instead: None', 'SetterError CreationInfo: type of argument " - "\"creators\" must be a list; got NoneType instead: None', 'SetterError " - 'CreationInfo: type of argument "data_license" must be str; got NoneType ' - "instead: None']" - ], - ), + {"spdxVersion": "2.3", "SPDXID": DOCUMENT_SPDX_ID, "name": "Example Document"}, + {"creationInfo": {"created": "2019-02-01T11:30:40Z"}}, ], ) -def test_parse_incomplete_document_info(incomplete_dict, expected_message): +def test_parse_incomplete_document_info(incomplete_dict): creation_info_parser = CreationInfoParser() - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): creation_info_parser.parse_creation_info(incomplete_dict) - TestCase().assertCountEqual(err.value.get_messages(), expected_message) - def test_parse_invalid_creation_info(): creation_info_parser = CreationInfoParser() @@ -105,15 +86,5 @@ def test_parse_invalid_creation_info(): "dataLicense": None, } - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): creation_info_parser.parse_creation_info(doc_dict) - - TestCase().assertCountEqual( - err.value.get_messages(), - [ - "Error while constructing CreationInfo: ['SetterError CreationInfo: type of " - 'argument "document_namespace" must be str; got NoneType instead: None\', ' - '\'SetterError CreationInfo: type of argument "data_license" must be str; got ' - "NoneType instead: None']" - ], - ) diff --git a/tests/spdx/parser/jsonlikedict/test_error_message.py b/tests/spdx/parser/jsonlikedict/test_error_message.py new file mode 100644 index 000000000..768d68588 --- /dev/null +++ b/tests/spdx/parser/jsonlikedict/test_error_message.py @@ -0,0 +1,31 @@ +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.package_parser import PackageParser + + +# To avoid duplication we use this invalid package as a proxy for the exact comparison of the generated error message. +# For all other classes we only check that a TypeError is raised if an incorrect type is specified. +def test_error_message(): + package_parser = PackageParser() + package = {"SPDXID": "SPDXRef-Package", "downloadLocation": 5, "attributionTexts": ["text", 5, {"test": "data"}]} + + with pytest.raises(SPDXParsingError) as err: + package_parser.parse_package(package) + + TestCase().assertCountEqual( + err.value.get_messages(), + [ + 'Error while constructing Package: [\'SetterError Package: argument "name" ' + "(None) is not an instance of str', 'SetterError Package: argument " + '"download_location" (int) did not match any element in the union:\\n str: ' + "is not an instance of str\\n " + "spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion: is not an instance " + "of spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion\\n " + "spdx_tools.spdx.model.spdx_none.SpdxNone: is not an instance of " + "spdx_tools.spdx.model.spdx_none.SpdxNone', 'SetterError Package: item 1 of " + 'argument "attribution_texts" (list) is not an instance of str\']' + ], + ) diff --git a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py index 98bcc0c81..a2d4491c8 100644 --- a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py @@ -1,8 +1,6 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from unittest import TestCase - import pytest from spdx_tools.spdx.parser.error import SPDXParsingError @@ -51,14 +49,5 @@ def test_parse_invalid_extracted_licensing_info(): "seeAlsos": ["http://people.freebsd.org/~phk/"], } - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): extracted_licensing_info_parser.parse_extracted_licensing_info(extracted_licensing_infos_dict) - - TestCase().assertCountEqual( - err.value.get_messages(), - [ - "Error while constructing ExtractedLicensingInfo: ['SetterError " - 'ExtractedLicensingInfo: type of argument "comment" must be one of (str, ' - "NoneType); got int instead: 56']" - ], - ) diff --git a/tests/spdx/parser/jsonlikedict/test_file_parser.py b/tests/spdx/parser/jsonlikedict/test_file_parser.py index 53eec3f0e..e1c6b7a5e 100644 --- a/tests/spdx/parser/jsonlikedict/test_file_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_file_parser.py @@ -93,22 +93,6 @@ def test_parse_file(copyright_text, expected_copyright_text): assert file.attribution_texts == ["Some attribution text."] -def test_parse_incomplete_file(): - file_parser = FileParser() - file_dict = {"SPDXID": "SPDXRef-File", "fileName": "Incomplete File"} - - with pytest.raises(SPDXParsingError) as err: - file_parser.parse_file(file_dict) - - TestCase().assertCountEqual( - err.value.get_messages(), - [ - "Error while constructing File: ['SetterError File: type of argument " - '"checksums" must be a list; got NoneType instead: None\']' - ], - ) - - def test_parse_invalid_files(): file_parser = FileParser() files = [ @@ -129,20 +113,11 @@ def test_parse_invalid_files(): {"algorithm": "MD", "checksumValue": "624c1abb3664f4b35547e7c73864ad24"}, ], }, + {"SPDXID": "SPDXRef-File", "fileName": "Incomplete File"}, ] - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): parse_list_of_elements(files, file_parser.parse_file) - TestCase().assertCountEqual( - err.value.get_messages(), - [ - "Error while constructing File: ['SetterError File: type of argument " - '"checksums" must be a list; got NoneType instead: None\']', - 'Error while constructing File: [\'SetterError File: type of argument "name" ' - "must be str; got NoneType instead: None']", - "Error while parsing File: [\"Error while parsing Checksum: ['Invalid ChecksumAlgorithm: MD']\"]", - ], - ) def test_parse_file_types(): diff --git a/tests/spdx/parser/jsonlikedict/test_package_parser.py b/tests/spdx/parser/jsonlikedict/test_package_parser.py index 494f612b7..5b933df8b 100644 --- a/tests/spdx/parser/jsonlikedict/test_package_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_package_parser.py @@ -228,53 +228,24 @@ def test_parse_package( @pytest.mark.parametrize( - "incomplete_package_dict,expected_message", + "incomplete_package_dict", [ - ( - {"SPDXID": "SPDXRef-Package"}, - [ - "Error while constructing Package: ['SetterError Package: type of " - "argument \"name\" must be str; got NoneType instead: None', 'SetterError Package: type of argument " - '"download_location" must be one of (str, spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion, ' - "spdx_tools.spdx.model.spdx_none.SpdxNone); " - "got NoneType instead: None']" - ], - ), - ( - {"SPDXID": "SPDXRef-Package", "name": 5, "downloadLocation": "NONE"}, - [ - "Error while constructing Package: ['SetterError Package: type of argument " - '"name" must be str; got int instead: 5\']' - ], - ), + {"SPDXID": "SPDXRef-Package"}, + {"SPDXID": "SPDXRef-Package", "name": 5, "downloadLocation": "NONE"}, + { + "SPDXID": "SPDXRef-Package", + "name": "Example Package", + "downloadLocation": "NONE", + "checksums": [{"algorithm": "SHA", "value": "1234"}], + }, ], ) -def test_parse_incomplete_package(incomplete_package_dict, expected_message): +def test_parse_invalid_package(incomplete_package_dict): package_parser = PackageParser() - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): package_parser.parse_package(incomplete_package_dict) - TestCase().assertCountEqual(err.value.get_messages(), expected_message) - - -def test_parse_invalid_package(): - package_parser = PackageParser() - package_dict = { - "SPDXID": "SPDXRef-Package", - "name": "Example Package", - "downloadLocation": "NONE", - "checksums": [{"algorithm": "SHA", "value": "1234"}], - } - - with pytest.raises(SPDXParsingError) as err: - package_parser.parse_package(package_dict) - - TestCase().assertCountEqual( - err.value.get_messages(), - ["Error while parsing Package: [\"Error while parsing Checksum: ['Invalid ChecksumAlgorithm: SHA']\"]"], - ) - def test_parse_packages(): package_parser = PackageParser() @@ -289,37 +260,17 @@ def test_parse_packages(): {"SPDXID": "SPDXRef-Package", "name": "Example Package", "downloadLocation": "NONE"}, ] - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): parse_list_of_elements(packages_list, package_parser.parse_package) - TestCase().assertCountEqual( - err.value.get_messages(), - [ - 'Error while parsing Package: ["Error while parsing Checksum: ' "['Invalid ChecksumAlgorithm: SHA']\"]", - "Error while constructing Package: ['SetterError Package: type of argument " - '"name" must be str; got int instead: 5\']', - ], - ) - def test_parse_external_ref(): package_parser = PackageParser() external_ref = {"referenceType": "fix"} - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): package_parser.parse_external_ref(external_ref) - TestCase().assertCountEqual( - err.value.get_messages(), - [ - "Error while constructing ExternalPackageRef: ['SetterError " - 'ExternalPackageRef: type of argument "category" must be ' - "spdx_tools.spdx.model.package.ExternalPackageRefCategory; got NoneType instead: None', " - '\'SetterError ExternalPackageRef: type of argument "locator" must be str; ' - "got NoneType instead: None']" - ], - ) - def test_parse_invalid_external_package_ref_category(): package_parser = PackageParser() diff --git a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py index f5e65fe50..327a83f6c 100644 --- a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py @@ -37,18 +37,9 @@ def test_parse_incomplete_relationship(): "comment": "Comment.", } - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): relationship_parser.parse_relationship(relationship_dict) - TestCase().assertCountEqual( - err.value.get_messages(), - [ - "Error while constructing Relationship: ['SetterError Relationship: type of " - 'argument "relationship_type" must be ' - "spdx_tools.spdx.model.relationship.RelationshipType; got NoneType instead: None']" - ], - ) - def test_parse_relationship_type(): relationship_parser = RelationshipParser() diff --git a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py index 55397af24..257a00e3a 100644 --- a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py @@ -74,19 +74,9 @@ def test_parse_incomplete_snippet(): snippet_parser = SnippetParser() incomplete_snippet_dict = {"SPDXID": "SPDXRef-Snippet", "file_spdx_id": "SPDXRef-File"} - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): snippet_parser.parse_snippet(incomplete_snippet_dict) - TestCase().assertCountEqual( - err.value.get_messages(), - [ - "Error while constructing Snippet: ['SetterError Snippet: type of argument " - "\"file_spdx_id\" must be str; got NoneType instead: None', 'SetterError Snippet: type of argument " - '"byte_range" must be a tuple; got NoneType ' - "instead: None']" - ], - ) - def test_parse_snippet_with_invalid_snippet_range(): snippet_parser = SnippetParser() @@ -101,19 +91,9 @@ def test_parse_snippet_with_invalid_snippet_range(): ], } - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): snippet_parser.parse_snippet(snippet_with_invalid_ranges_list) - TestCase().assertCountEqual( - err.value.get_messages(), - [ - "Error while constructing Snippet: ['SetterError Snippet: type of argument " - "\"file_spdx_id\" must be str; got NoneType instead: None', 'SetterError " - 'Snippet: type of argument "byte_range"[0] must be int; got str instead: ' - "(\\'310s\\', 23)']" - ], - ) - def test_parse_invalid_snippet_range(): snippet_parser = SnippetParser() diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py index 3fe36c267..7facfce98 100644 --- a/tests/spdx/parser/rdf/test_file_parser.py +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -45,10 +45,5 @@ def test_parse_invalid_file(): doc_namespace = "https://some.namespace" assert isinstance(file_node, BNode) - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): parse_file(file_node, graph, doc_namespace) - - assert err.value.get_messages() == [ - "Error while constructing File: ['SetterError File: type of argument " - '"spdx_id" must be str; got NoneType instead: None\']' - ] diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index 9d2bcfc1f..814ceceee 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -104,10 +104,5 @@ def test_parse_invalid_package(): doc_namespace = "https://some.namespace" assert isinstance(package_node, BNode) - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): parse_package(package_node, graph, doc_namespace) - - assert err.value.get_messages() == [ - "Error while constructing Package: ['SetterError Package: type of argument " - '"spdx_id" must be str; got NoneType instead: None\']' - ] diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index 73970035b..da2267221 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -167,11 +167,5 @@ def test_parse_invalid_file(): doc_namespace = "https://some.namespace" assert isinstance(snippet_node, BNode) - with pytest.raises(SPDXParsingError) as err: + with pytest.raises(SPDXParsingError): parse_snippet(snippet_node, graph, doc_namespace) - - assert err.value.get_messages() == [ - "Error while constructing Snippet: ['SetterError Snippet: type of argument " - "\"spdx_id\" must be str; got NoneType instead: None', 'SetterError Snippet: " - 'type of argument "file_spdx_id" must be str; got NoneType instead: None\']' - ] From 000a9dbbec7a77a934471a11f6e53e59ab3bbd77 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 16 May 2023 08:59:46 +0200 Subject: [PATCH 080/354] implement review comments - simplify the error message for values with multiple possible types - add value to the error message Signed-off-by: Meret Behrens --- .../typing/dataclass_with_properties.py | 15 +++++++++++- .../parser/jsonlikedict/test_error_message.py | 23 +++++++++++-------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/spdx_tools/common/typing/dataclass_with_properties.py b/src/spdx_tools/common/typing/dataclass_with_properties.py index af8fa7179..d1777cefa 100644 --- a/src/spdx_tools/common/typing/dataclass_with_properties.py +++ b/src/spdx_tools/common/typing/dataclass_with_properties.py @@ -1,3 +1,4 @@ +import re from dataclasses import dataclass from typeguard import CollectionCheckStrategy, TypeCheckError, config, typechecked @@ -30,9 +31,21 @@ def set_field_with_better_error_message(self, value: field_type): set_field(self, value) except TypeCheckError as err: error_message: str = f"SetterError {self.__class__.__name__}: {err}" + if "did not match any element in the union" in error_message: + error_message = simplify_error_message_for_union(error_message) + # As setters are created dynamically, their argument name is always "value". We replace it by the # actual name so the error message is more helpful. - raise TypeError(error_message.replace("value", field_name, 1)) + raise TypeError(error_message.replace("value", field_name, 1) + f": {value}") + + def simplify_error_message_for_union(error_message: str) -> str: + # The error message from typeguard is more verbose than we need, so we simplify the message + # to provide the user with a compacter error message. + types_in_union = re.compile(r"\n\s*(.*?):", re.UNICODE) + list_of_types = re.findall(types_in_union, error_message) + text_to_replace = error_message.split("did not match any element in the union:")[-1] + error_message = error_message.replace(text_to_replace, " " + str(list_of_types)) + return error_message return set_field_with_better_error_message diff --git a/tests/spdx/parser/jsonlikedict/test_error_message.py b/tests/spdx/parser/jsonlikedict/test_error_message.py index 768d68588..d9249e980 100644 --- a/tests/spdx/parser/jsonlikedict/test_error_message.py +++ b/tests/spdx/parser/jsonlikedict/test_error_message.py @@ -10,7 +10,12 @@ # For all other classes we only check that a TypeError is raised if an incorrect type is specified. def test_error_message(): package_parser = PackageParser() - package = {"SPDXID": "SPDXRef-Package", "downloadLocation": 5, "attributionTexts": ["text", 5, {"test": "data"}]} + package = { + "SPDXID": "SPDXRef-Package", + "downloadLocation": 5, + "attributionTexts": ["text", 5, {"test": "data"}], + "packageFileName": 10, + } with pytest.raises(SPDXParsingError) as err: package_parser.parse_package(package) @@ -19,13 +24,13 @@ def test_error_message(): err.value.get_messages(), [ 'Error while constructing Package: [\'SetterError Package: argument "name" ' - "(None) is not an instance of str', 'SetterError Package: argument " - '"download_location" (int) did not match any element in the union:\\n str: ' - "is not an instance of str\\n " - "spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion: is not an instance " - "of spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion\\n " - "spdx_tools.spdx.model.spdx_none.SpdxNone: is not an instance of " - "spdx_tools.spdx.model.spdx_none.SpdxNone', 'SetterError Package: item 1 of " - 'argument "attribution_texts" (list) is not an instance of str\']' + "(None) is not an instance of str: None', 'SetterError Package: argument " + '"download_location" (int) did not match any element in the union: ' + "[\\'str\\', \\'spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion\\', " + "\\'spdx_tools.spdx.model.spdx_none.SpdxNone\\']: 5', 'SetterError Package: " + 'argument "file_name" (int) did not match any element in the union: ' + "[\\'str\\', \\'NoneType\\']: 10', 'SetterError Package: item 1 of argument " + "\"attribution_texts\" (list) is not an instance of str: [\\'text\\', 5, " + "{\\'test\\': \\'data\\'}]']" ], ) From cb680ccfb252e278ed9ffe23bde42487846c54d0 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 16 May 2023 09:29:36 +0200 Subject: [PATCH 081/354] implement review comments Signed-off-by: Meret Behrens --- src/spdx_tools/common/typing/dataclass_with_properties.py | 4 ++-- tests/spdx/parser/jsonlikedict/test_error_message.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/spdx_tools/common/typing/dataclass_with_properties.py b/src/spdx_tools/common/typing/dataclass_with_properties.py index d1777cefa..5f58c0b81 100644 --- a/src/spdx_tools/common/typing/dataclass_with_properties.py +++ b/src/spdx_tools/common/typing/dataclass_with_properties.py @@ -40,11 +40,11 @@ def set_field_with_better_error_message(self, value: field_type): def simplify_error_message_for_union(error_message: str) -> str: # The error message from typeguard is more verbose than we need, so we simplify the message - # to provide the user with a compacter error message. + # to provide the user with a more compact error message. types_in_union = re.compile(r"\n\s*(.*?):", re.UNICODE) list_of_types = re.findall(types_in_union, error_message) text_to_replace = error_message.split("did not match any element in the union:")[-1] - error_message = error_message.replace(text_to_replace, " " + str(list_of_types)) + error_message = error_message.replace(text_to_replace, " [" + ", ".join(list_of_types) + "]") return error_message return set_field_with_better_error_message diff --git a/tests/spdx/parser/jsonlikedict/test_error_message.py b/tests/spdx/parser/jsonlikedict/test_error_message.py index d9249e980..207623ad4 100644 --- a/tests/spdx/parser/jsonlikedict/test_error_message.py +++ b/tests/spdx/parser/jsonlikedict/test_error_message.py @@ -26,10 +26,10 @@ def test_error_message(): 'Error while constructing Package: [\'SetterError Package: argument "name" ' "(None) is not an instance of str: None', 'SetterError Package: argument " '"download_location" (int) did not match any element in the union: ' - "[\\'str\\', \\'spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion\\', " - "\\'spdx_tools.spdx.model.spdx_none.SpdxNone\\']: 5', 'SetterError Package: " + "[str, spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion, " + "spdx_tools.spdx.model.spdx_none.SpdxNone]: 5', 'SetterError Package: " 'argument "file_name" (int) did not match any element in the union: ' - "[\\'str\\', \\'NoneType\\']: 10', 'SetterError Package: item 1 of argument " + "[str, NoneType]: 10', 'SetterError Package: item 1 of argument " "\"attribution_texts\" (list) is not an instance of str: [\\'text\\', 5, " "{\\'test\\': \\'data\\'}]']" ], From 21c7e32a2223fc281adfacca21a266fae5bec0cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 31 May 2023 14:11:18 +0200 Subject: [PATCH 082/354] [issue-673] remove type checking due to performance issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../typing/dataclass_with_properties.py | 72 +--------- tests/spdx/jsonschema/test_converter.py | 4 +- tests/spdx/model/test_actor.py | 23 +-- tests/spdx/model/test_annotation.py | 32 ----- tests/spdx/model/test_checksum.py | 12 -- tests/spdx/model/test_creation_info.py | 75 ---------- tests/spdx/model/test_document.py | 43 ------ .../spdx/model/test_external_document_ref.py | 19 --- .../model/test_external_package_reference.py | 22 --- .../model/test_extracted_licensing_info.py | 27 ---- tests/spdx/model/test_file.py | 76 +--------- tests/spdx/model/test_package.py | 135 +----------------- .../model/test_package_verification_code.py | 12 -- tests/spdx/model/test_relationship.py | 22 --- tests/spdx/model/test_snippet.py | 57 -------- .../jsonlikedict/test_annotation_parser.py | 17 --- .../jsonlikedict/test_checksum_parser.py | 8 -- .../jsonlikedict/test_creation_info_parser.py | 34 ----- .../parser/jsonlikedict/test_error_message.py | 36 ----- .../test_extracted_licensing_info_parser.py | 19 --- .../jsonlikedict/test_package_parser.py | 28 ---- .../jsonlikedict/test_relationship_parser.py | 13 -- .../jsonlikedict/test_snippet_parser.py | 25 ---- tests/spdx/parser/rdf/test_file_parser.py | 14 +- tests/spdx/parser/rdf/test_package_parser.py | 11 -- tests/spdx/parser/rdf/test_snippet_parser.py | 10 -- 26 files changed, 12 insertions(+), 834 deletions(-) delete mode 100644 tests/spdx/parser/jsonlikedict/test_error_message.py diff --git a/src/spdx_tools/common/typing/dataclass_with_properties.py b/src/spdx_tools/common/typing/dataclass_with_properties.py index 5f58c0b81..3188fee44 100644 --- a/src/spdx_tools/common/typing/dataclass_with_properties.py +++ b/src/spdx_tools/common/typing/dataclass_with_properties.py @@ -1,71 +1,9 @@ -import re +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 from dataclasses import dataclass -from typeguard import CollectionCheckStrategy, TypeCheckError, config, typechecked - -config.collection_check_strategy = CollectionCheckStrategy.ALL_ITEMS - def dataclass_with_properties(cls): - """Decorator to generate a dataclass with properties out of the class' value:type list. - Their getters and setters will be subjected to the @typechecked decorator to ensure type conformity.""" - data_cls = dataclass(cls) - for field_name, field_type in data_cls.__annotations__.items(): - set_field = make_setter(field_name, field_type) - get_field = make_getter(field_name, field_type) - - setattr(data_cls, field_name, property(get_field, set_field)) - - return data_cls - - -def make_setter(field_name, field_type): - """helper method to avoid late binding when generating functions in a for loop""" - - @typechecked - def set_field(self, value: field_type): - setattr(self, f"_{field_name}", value) - - def set_field_with_better_error_message(self, value: field_type): - try: - set_field(self, value) - except TypeCheckError as err: - error_message: str = f"SetterError {self.__class__.__name__}: {err}" - if "did not match any element in the union" in error_message: - error_message = simplify_error_message_for_union(error_message) - - # As setters are created dynamically, their argument name is always "value". We replace it by the - # actual name so the error message is more helpful. - raise TypeError(error_message.replace("value", field_name, 1) + f": {value}") - - def simplify_error_message_for_union(error_message: str) -> str: - # The error message from typeguard is more verbose than we need, so we simplify the message - # to provide the user with a more compact error message. - types_in_union = re.compile(r"\n\s*(.*?):", re.UNICODE) - list_of_types = re.findall(types_in_union, error_message) - text_to_replace = error_message.split("did not match any element in the union:")[-1] - error_message = error_message.replace(text_to_replace, " [" + ", ".join(list_of_types) + "]") - return error_message - - return set_field_with_better_error_message - - -def make_getter(field_name, field_type): - """helper method to avoid late binding when generating functions in a for loop""" - - @typechecked - def get_field(self) -> field_type: - return getattr(self, f"_{field_name}") - - def get_field_with_better_error_message(self) -> field_type: - try: - return get_field(self) - except TypeCheckError as err: - error_message: str = f"GetterError {self.__class__.__name__}: {err}" - # As getters are created dynamically, their argument name is always "the return value". - # We replace it by the actual name so the error message is more helpful. - raise TypeError( - error_message.replace("the return value", field_name, 1) + f': {getattr(self, f"_{field_name}")}' - ) - - return get_field_with_better_error_message + # placeholder decorator until we figure out how to do run-time type checking more performant + return dataclass(cls) diff --git a/tests/spdx/jsonschema/test_converter.py b/tests/spdx/jsonschema/test_converter.py index 46558d904..0a94612bb 100644 --- a/tests/spdx/jsonschema/test_converter.py +++ b/tests/spdx/jsonschema/test_converter.py @@ -1,12 +1,12 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from dataclasses import dataclass from enum import auto from typing import Any, Type import pytest -from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.json_property import JsonProperty @@ -18,7 +18,7 @@ class TestPropertyType(JsonProperty): SECOND_NAME = auto() -@dataclass_with_properties +@dataclass class TestDataModelType: first_property: str second_property: int diff --git a/tests/spdx/model/test_actor.py b/tests/spdx/model/test_actor.py index e41e40b4e..90dba8ea6 100644 --- a/tests/spdx/model/test_actor.py +++ b/tests/spdx/model/test_actor.py @@ -15,33 +15,12 @@ def test_correct_initialization(): def test_correct_initialization_with_optional_as_none(): - actor = Actor(ActorType.TOOL, "tool_name", None) + actor = Actor(ActorType.TOOL, "tool_name") assert actor.actor_type == ActorType.TOOL assert actor.name == "tool_name" assert actor.email is None -def test_wrong_type_in_actor_type(): - with pytest.raises(TypeError): - Actor("PERSON", "name") - - -def test_wrong_type_in_name(): - with pytest.raises(TypeError): - Actor(ActorType.PERSON, 42) - - -def test_wrong_type_in_email(): - with pytest.raises(TypeError): - Actor(ActorType.PERSON, "name", []) - - -def test_wrong_type_in_email_after_initializing(): - with pytest.raises(TypeError): - actor = Actor(ActorType.PERSON, "name") - actor.email = [] - - @pytest.mark.parametrize( "actor,expected_string", [ diff --git a/tests/spdx/model/test_annotation.py b/tests/spdx/model/test_annotation.py index 5638b0b98..2ceb2dae0 100644 --- a/tests/spdx/model/test_annotation.py +++ b/tests/spdx/model/test_annotation.py @@ -5,8 +5,6 @@ from datetime import datetime from unittest import mock -import pytest - from spdx_tools.spdx.model import Annotation, AnnotationType @@ -18,33 +16,3 @@ def test_correct_initialization(actor): assert annotation.annotator == actor assert annotation.annotation_date == datetime(2022, 1, 1) assert annotation.annotation_comment == "comment" - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_spdx_id(actor): - with pytest.raises(TypeError): - Annotation(42, AnnotationType.OTHER, actor, datetime(2022, 1, 1), "comment") - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_annotation_type(actor): - with pytest.raises(TypeError): - Annotation("id", 42, actor, datetime(2022, 1, 1), "comment") - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_annotator(actor): - with pytest.raises(TypeError): - Annotation("id", AnnotationType.OTHER, 42, datetime(2022, 1, 1), "comment") - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_annotation_date(actor): - with pytest.raises(TypeError): - Annotation("id", AnnotationType.OTHER, actor, 42, "comment") - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_annotation_comment(actor): - with pytest.raises(TypeError): - Annotation("id", AnnotationType.OTHER, actor, datetime(2022, 1, 1), 42) diff --git a/tests/spdx/model/test_checksum.py b/tests/spdx/model/test_checksum.py index 308d95486..6f0a2c5f8 100644 --- a/tests/spdx/model/test_checksum.py +++ b/tests/spdx/model/test_checksum.py @@ -2,8 +2,6 @@ # # SPDX-License-Identifier: Apache-2.0 -import pytest - from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm @@ -11,13 +9,3 @@ def test_correct_initialization(): checksum = Checksum(ChecksumAlgorithm.BLAKE2B_256, "value") assert checksum.algorithm == ChecksumAlgorithm.BLAKE2B_256 assert checksum.value == "value" - - -def test_wrong_type_in_algorithm(): - with pytest.raises(TypeError): - Checksum(42, "value") - - -def test_wrong_type_in_value(): - with pytest.raises(TypeError): - Checksum(ChecksumAlgorithm.BLAKE2B_256, 42) diff --git a/tests/spdx/model/test_creation_info.py b/tests/spdx/model/test_creation_info.py index c0912005c..f204201ee 100644 --- a/tests/spdx/model/test_creation_info.py +++ b/tests/spdx/model/test_creation_info.py @@ -5,8 +5,6 @@ from datetime import datetime from unittest import mock -import pytest - from spdx_tools.spdx.model import CreationInfo, Version @@ -37,76 +35,3 @@ def test_correct_initialization(actor, ext_ref): assert creation_info.external_document_refs == [ext_ref, ext_ref] assert creation_info.license_list_version == Version(6, 3) assert creation_info.document_comment == "doc_comment" - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_spdx_version(actor): - with pytest.raises(TypeError): - CreationInfo(42, "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1)) - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_spdx_id(actor): - with pytest.raises(TypeError): - CreationInfo("version", 42, "name", "namespace", [actor, actor], datetime(2022, 1, 1)) - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_name(actor): - with pytest.raises(TypeError): - CreationInfo("version", "id", 42, "namespace", [actor, actor], datetime(2022, 1, 1)) - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_document_namespace(actor): - with pytest.raises(TypeError): - CreationInfo("version", "id", "name", 42, [actor, actor], datetime(2022, 1, 1)) - - -def test_wrong_type_in_creators(): - with pytest.raises(TypeError): - CreationInfo("version", "id", "name", "namespace", ["person"], datetime(2022, 1, 1)) - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_created(actor): - with pytest.raises(TypeError): - CreationInfo("version", "id", "name", "namespace", [actor, actor], "2022-01-01") - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_creator_comment(actor): - with pytest.raises(TypeError): - CreationInfo( - "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), creator_comment=["string"] - ) - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_data_license(actor): - with pytest.raises(TypeError): - CreationInfo("version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), data_license=42) - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_external_document_refs(actor): - with pytest.raises(TypeError): - CreationInfo( - "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), external_document_refs=() - ) - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_license_list_version(actor): - with pytest.raises(TypeError): - CreationInfo( - "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), license_list_version="6.4" - ) - - -@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) -def test_wrong_type_in_document_comment(actor): - with pytest.raises(TypeError): - CreationInfo( - "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), document_comment=["1"] - ) diff --git a/tests/spdx/model/test_document.py b/tests/spdx/model/test_document.py index 9d4079cb4..575032953 100644 --- a/tests/spdx/model/test_document.py +++ b/tests/spdx/model/test_document.py @@ -4,8 +4,6 @@ from unittest import mock -import pytest - from spdx_tools.spdx.model import Document @@ -45,44 +43,3 @@ def test_correct_initialization_with_default_values(creation_info): assert document.annotations == [] assert document.relationships == [] assert document.extracted_licensing_info == [] - - -def test_wrong_type_in_creation_info(): - with pytest.raises(TypeError): - Document("string") - - -@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) -def test_wrong_type_in_packages(creation_info): - with pytest.raises(TypeError): - Document(creation_info, packages=["string"]) - - -@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) -def test_wrong_type_in_files(creation_info): - with pytest.raises(TypeError): - Document(creation_info, files={}) - - -@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) -def test_wrong_type_in_snippets(creation_info): - with pytest.raises(TypeError): - Document(creation_info, snippets=()) - - -@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) -def test_wrong_type_in_annotations(creation_info): - with pytest.raises(TypeError): - Document(creation_info, annotations=["string"]) - - -@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) -def test_wrong_type_in_relationships(creation_info): - with pytest.raises(TypeError): - Document(creation_info, relationships="string") - - -@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) -def test_wrong_type_in_extracted_licensing_info(creation_info): - with pytest.raises(TypeError): - Document(creation_info, extracted_licensing_info=42) diff --git a/tests/spdx/model/test_external_document_ref.py b/tests/spdx/model/test_external_document_ref.py index 4b32d6bf3..ac1c8fc96 100644 --- a/tests/spdx/model/test_external_document_ref.py +++ b/tests/spdx/model/test_external_document_ref.py @@ -4,8 +4,6 @@ from unittest import mock -import pytest - from spdx_tools.spdx.model import ExternalDocumentRef @@ -15,20 +13,3 @@ def test_correct_initialization(checksum): assert external_document_ref.document_ref_id == "id" assert external_document_ref.document_uri == "uri" assert external_document_ref.checksum == checksum - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_spdx_id(checksum): - with pytest.raises(TypeError): - ExternalDocumentRef(42, "uri", checksum) - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_document_uri(checksum): - with pytest.raises(TypeError): - ExternalDocumentRef("id", 42, checksum) - - -def test_wrong_type_in_checksum(): - with pytest.raises(TypeError): - ExternalDocumentRef("id", "uri", 42) diff --git a/tests/spdx/model/test_external_package_reference.py b/tests/spdx/model/test_external_package_reference.py index d81bcc221..31610a554 100644 --- a/tests/spdx/model/test_external_package_reference.py +++ b/tests/spdx/model/test_external_package_reference.py @@ -2,8 +2,6 @@ # # SPDX-License-Identifier: Apache-2.0 -import pytest - from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory @@ -13,23 +11,3 @@ def test_correct_initialization(): assert external_package_reference.reference_type == "type" assert external_package_reference.locator == "locator" assert external_package_reference.comment == "comment" - - -def test_wrong_type_in_category(): - with pytest.raises(TypeError): - ExternalPackageRef([ExternalPackageRefCategory.OTHER], "type", "locator") - - -def test_wrong_type_in_reference_type(): - with pytest.raises(TypeError): - ExternalPackageRef(ExternalPackageRefCategory.OTHER, 42, "locator") - - -def test_wrong_type_in_locator(): - with pytest.raises(TypeError): - ExternalPackageRef(ExternalPackageRefCategory.OTHER, "type", 42) - - -def test_wrong_type_in_comment(): - with pytest.raises(TypeError): - ExternalPackageRef(ExternalPackageRefCategory.OTHER, "type", "locator", []) diff --git a/tests/spdx/model/test_extracted_licensing_info.py b/tests/spdx/model/test_extracted_licensing_info.py index 75dc79aab..be187544e 100644 --- a/tests/spdx/model/test_extracted_licensing_info.py +++ b/tests/spdx/model/test_extracted_licensing_info.py @@ -2,8 +2,6 @@ # # SPDX-License-Identifier: Apache-2.0 -import pytest - from spdx_tools.spdx.model import ExtractedLicensingInfo @@ -14,28 +12,3 @@ def test_correct_initialization(): assert extracted_licensing_info.license_name == "name" assert extracted_licensing_info.cross_references == ["reference"] assert extracted_licensing_info.comment == "comment" - - -def test_wrong_type_in_license_id(): - with pytest.raises(TypeError): - ExtractedLicensingInfo(license_id=42) - - -def test_wrong_type_in_extracted_text(): - with pytest.raises(TypeError): - ExtractedLicensingInfo(extracted_text=42) - - -def test_wrong_type_in_license_name(): - with pytest.raises(TypeError): - ExtractedLicensingInfo(license_name=42) - - -def test_wrong_type_in_cross_references(): - with pytest.raises(TypeError): - ExtractedLicensingInfo(cross_references=["ref", 42]) - - -def test_wrong_type_in_comment(): - with pytest.raises(TypeError): - ExtractedLicensingInfo(comment=42) diff --git a/tests/spdx/model/test_file.py b/tests/spdx/model/test_file.py index 592e8dc4f..2470e7379 100644 --- a/tests/spdx/model/test_file.py +++ b/tests/spdx/model/test_file.py @@ -4,9 +4,7 @@ from unittest import mock -import pytest - -from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, File, FileType, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.model import File, FileType, SpdxNoAssertion, SpdxNone @mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) @@ -54,75 +52,3 @@ def test_correct_initialization_with_default_values(checksum): assert file.notice is None assert file.contributors == [] assert file.attribution_texts == [] - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_name(checksum): - with pytest.raises(TypeError): - File(42, "id", [checksum]) - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_spdx_id(checksum): - with pytest.raises(TypeError): - File("name", 42, [checksum]) - - -def test_wrong_type_in_checksum(): - checksum = Checksum(ChecksumAlgorithm.BLAKE2B_256, "value") - with pytest.raises(TypeError): - File("name", "id", checksum) - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_file_type(checksum): - with pytest.raises(TypeError): - File("name", "id", [checksum], file_types=FileType.OTHER) - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_license_concluded(checksum): - with pytest.raises(TypeError): - File("name", "id", [checksum], license_concluded="NONE") - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_license_info_in_file(checksum): - with pytest.raises(TypeError): - File("name", "id", [checksum], license_info_in_file=[SpdxNone]) - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_license_comment(checksum): - with pytest.raises(TypeError): - File("name", "id", [checksum], license_comment=42) - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_copyright_text(checksum): - with pytest.raises(TypeError): - File("name", "id", [checksum], copyright_text=[SpdxNone()]) - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_comment(checksum): - with pytest.raises(TypeError): - File("name", "id", [checksum], comment=42) - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_notice(checksum): - with pytest.raises(TypeError): - File("name", "id", [checksum], notice=["notice"]) - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_contributors(checksum): - with pytest.raises(TypeError): - File("name", "id", [checksum], contributors="contributor") - - -@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) -def test_wrong_type_in_attribution_texts(checksum): - with pytest.raises(TypeError): - File("name", "id", [checksum], attribution_texts=["attribution", 42]) diff --git a/tests/spdx/model/test_package.py b/tests/spdx/model/test_package.py index c533b2812..833f664ff 100644 --- a/tests/spdx/model/test_package.py +++ b/tests/spdx/model/test_package.py @@ -5,10 +5,9 @@ from datetime import datetime from unittest import mock -import pytest -from license_expression import LicenseExpression, Licensing +from license_expression import Licensing -from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, Package, PackagePurpose, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.model import Package, PackagePurpose, SpdxNoAssertion, SpdxNone @mock.patch("spdx_tools.spdx.model.ExternalPackageRef", autospec=True) @@ -100,133 +99,3 @@ def test_correct_initialization_with_default_values(): assert package.release_date is None assert package.built_date is None assert package.valid_until_date is None - - -def test_wrong_type_in_spdx_id(): - with pytest.raises(TypeError): - Package(42, "name", "location") - - -def test_wrong_type_in_name(): - with pytest.raises(TypeError): - Package("id", 42, "location") - - -def test_wrong_type_in_download_location(): - with pytest.raises(TypeError): - Package("id", "name", 42) - - -def test_wrong_type_in_version(): - with pytest.raises(TypeError): - Package("id", "name", "location", version=42) - - -def test_wrong_type_in_file_name(): - with pytest.raises(TypeError): - Package("id", "name", "location", file_name=42) - - -def test_wrong_type_in_supplier(): - with pytest.raises(TypeError): - Package("id", "name", "location", supplier=SpdxNone()) - - -def test_wrong_type_in_originator(): - with pytest.raises(TypeError): - Package("id", "name", "location", originator=SpdxNone()) - - -def test_wrong_type_in_files_analyzed(): - with pytest.raises(TypeError): - Package("id", "name", "location", files_analyzed=None) - - -def test_wrong_type_in_verification_code(): - with pytest.raises(TypeError): - Package("id", "name", "location", verification_code=[]) - - -def test_wrong_type_in_checksums(): - with pytest.raises(TypeError): - Package("id", "name", "location", checksums=Checksum(ChecksumAlgorithm.MD2, "value")) - - -def test_wrong_type_in_homepage(): - with pytest.raises(TypeError): - Package("id", "name", "location", homepage=42) - - -def test_wrong_type_in_source_info(): - with pytest.raises(TypeError): - Package("id", "name", "location", source_info=42) - - -def test_wrong_type_in_license_concluded(): - with pytest.raises(TypeError): - Package("id", "name", "location", license_concluded=[]) - - -def test_wrong_type_in_license_info_from_files(): - with pytest.raises(TypeError): - Package("id", "name", "location", license_info_from_files=LicenseExpression("string")) - - -def test_wrong_type_in_license_declared(): - with pytest.raises(TypeError): - Package("id", "name", "location", license_declared=[]) - - -def test_wrong_type_in_license_comment(): - with pytest.raises(TypeError): - Package("id", "name", "location", license_comment=42) - - -def test_wrong_type_in_copyright_text(): - with pytest.raises(TypeError): - Package("id", "name", "location", copyright_text=42) - - -def test_wrong_type_in_summary(): - with pytest.raises(TypeError): - Package("id", "name", "location", summary=42) - - -def test_wrong_type_in_description(): - with pytest.raises(TypeError): - Package("id", "name", "location", description=42) - - -def test_wrong_type_in_comment(): - with pytest.raises(TypeError): - Package("id", "name", "location", comment=[]) - - -def test_wrong_type_in_external_references(): - with pytest.raises(TypeError): - Package("id", "name", "location", external_references=["external_ref"]) - - -def test_wrong_type_in_attribution_texts(): - with pytest.raises(TypeError): - Package("id", "name", "location", attribution_texts="text") - - -def test_wrong_type_in_primary_package_purpose(): - with pytest.raises(TypeError): - Package("id", "name", "location", primary_package_purpose=[]) - - -def test_wrong_type_in_release_date(): - with pytest.raises(TypeError): - Package("id", "name", "location", release_date=42) - - -def test_wrong_type_in_built_date(): - with pytest.raises(TypeError): - Package("id", "name", "location", built_date="2022-01-01") - - -def test_wrong_type_in_valid_until_date(): - with pytest.raises(TypeError): - Package("id", "name", "location", valid_until_date=SpdxNone()) diff --git a/tests/spdx/model/test_package_verification_code.py b/tests/spdx/model/test_package_verification_code.py index e1492a91d..46e8f221a 100644 --- a/tests/spdx/model/test_package_verification_code.py +++ b/tests/spdx/model/test_package_verification_code.py @@ -2,8 +2,6 @@ # # SPDX-License-Identifier: Apache-2.0 -import pytest - from spdx_tools.spdx.model import PackageVerificationCode @@ -11,13 +9,3 @@ def test_correct_initialization(): package_verification_code = PackageVerificationCode("value", ["file1", "file2"]) assert package_verification_code.value == "value" assert package_verification_code.excluded_files == ["file1", "file2"] - - -def test_wrong_type_in_value(): - with pytest.raises(TypeError): - PackageVerificationCode(42, ["file1", "file2"]) - - -def test_wrong_type_in_excluded_files(): - with pytest.raises(TypeError): - PackageVerificationCode("value", "file1") diff --git a/tests/spdx/model/test_relationship.py b/tests/spdx/model/test_relationship.py index 0ffb62482..7f9609f5b 100644 --- a/tests/spdx/model/test_relationship.py +++ b/tests/spdx/model/test_relationship.py @@ -2,8 +2,6 @@ # # SPDX-License-Identifier: Apache-2.0 -import pytest - from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion @@ -13,23 +11,3 @@ def test_correct_initialization(): assert relationship.relationship_type == RelationshipType.OTHER assert relationship.related_spdx_element_id == SpdxNoAssertion() assert relationship.comment == "comment" - - -def test_wrong_type_in_spdx_element_id(): - with pytest.raises(TypeError): - Relationship(SpdxNoAssertion(), RelationshipType.OTHER, "other_id") - - -def test_wrong_type_in_relationship_type(): - with pytest.raises(TypeError): - Relationship("id", 42, "other_id") - - -def test_wrong_type_in_related_spdx_element_id(): - with pytest.raises(TypeError): - Relationship("id", RelationshipType.OTHER, 42) - - -def test_wrong_type_in_comment(): - with pytest.raises(TypeError): - Relationship("id", RelationshipType.OTHER, "other_id", 42) diff --git a/tests/spdx/model/test_snippet.py b/tests/spdx/model/test_snippet.py index 7fcf21581..909e53bf7 100644 --- a/tests/spdx/model/test_snippet.py +++ b/tests/spdx/model/test_snippet.py @@ -2,8 +2,6 @@ # # SPDX-License-Identifier: Apache-2.0 -import pytest - from spdx_tools.spdx.model import Snippet, SpdxNoAssertion, SpdxNone @@ -47,58 +45,3 @@ def test_correct_initialization_with_default_values(): assert snippet.comment is None assert snippet.name is None assert snippet.attribution_texts == [] - - -def test_wrong_type_in_spdx_id(): - with pytest.raises(TypeError): - Snippet(42, "file_id", (200, 400)) - - -def test_wrong_type_in_file_spdx_id(): - with pytest.raises(TypeError): - Snippet("id", 42, (200, 400)) - - -def test_wrong_type_in_byte_range(): - with pytest.raises(TypeError): - Snippet("id", "file_id", (200, 300, 400)) - - -def test_wrong_type_in_line_range(): - with pytest.raises(TypeError): - Snippet("id", "file_id", (200, 400), line_range=(20, "40")) - - -def test_wrong_type_in_license_concluded(): - with pytest.raises(TypeError): - Snippet("id", "file_id", (200, 400), license_concluded="NONE") - - -def test_wrong_type_in_license_info_in_snippet(): - with pytest.raises(TypeError): - Snippet("id", "file_id", (200, 400), license_info_in_snippet=SpdxNoAssertion()) - - -def test_wrong_type_in_license_comment(): - with pytest.raises(TypeError): - Snippet("id", "file_id", (200, 400), license_comment=[]) - - -def test_wrong_type_in_copyright_text(): - with pytest.raises(TypeError): - Snippet("id", "file_id", (200, 400), copyright_text=["copyright"]) - - -def test_wrong_type_in_comment(): - with pytest.raises(TypeError): - Snippet("id", "file_id", (200, 400), comment=["comment"]) - - -def test_wrong_type_in_name(): - with pytest.raises(TypeError): - Snippet("id", "file_id", (200, 400), name=42) - - -def test_wrong_type_in_attribution_texts(): - with pytest.raises(TypeError): - Snippet("id", "file_id", (200, 400), attribution_texts="attribution") diff --git a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py index ac814d6cd..5511da8a6 100644 --- a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py @@ -4,11 +4,8 @@ import datetime from unittest import TestCase -import pytest - from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID from spdx_tools.spdx.model import Actor, ActorType, Annotation, AnnotationType -from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.annotation_parser import AnnotationParser @@ -116,17 +113,3 @@ def test_parse_all_annotations(): ), ], ) - - -@pytest.mark.parametrize( - "incomplete_annotation_dict", - [ - {"annotator": "Person: Jane Doe ()"}, - {"annotationDate": "2010-01-29T18:30:22Z"}, - ], -) -def test_parse_incomplete_annotation(incomplete_annotation_dict): - annotation_parser = AnnotationParser() - - with pytest.raises(SPDXParsingError): - annotation_parser.parse_annotation(incomplete_annotation_dict) diff --git a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py index 24676cccf..c01654062 100644 --- a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py @@ -30,11 +30,3 @@ def test_parse_invalid_checksum(): TestCase().assertCountEqual( err.value.get_messages(), ["Error while parsing Checksum: ['Invalid ChecksumAlgorithm: SHA']"] ) - - -def test_parse_incomplete_checksum(): - checksum_parser = ChecksumParser() - checksum_dict = {"algorithm": "SHA1"} - - with pytest.raises(SPDXParsingError): - checksum_parser.parse_checksum(checksum_dict) diff --git a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py index 1a9851016..85e2b3321 100644 --- a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py @@ -4,11 +4,8 @@ from datetime import datetime from unittest import TestCase -import pytest - from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID from spdx_tools.spdx.model import Actor, ActorType, Checksum, ChecksumAlgorithm, ExternalDocumentRef, Version -from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.creation_info_parser import CreationInfoParser @@ -57,34 +54,3 @@ def test_parse_creation_info(): document_uri="http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301", ) ] - - -@pytest.mark.parametrize( - "incomplete_dict", - [ - {"spdxVersion": "2.3", "SPDXID": DOCUMENT_SPDX_ID, "name": "Example Document"}, - {"creationInfo": {"created": "2019-02-01T11:30:40Z"}}, - ], -) -def test_parse_incomplete_document_info(incomplete_dict): - creation_info_parser = CreationInfoParser() - - with pytest.raises(SPDXParsingError): - creation_info_parser.parse_creation_info(incomplete_dict) - - -def test_parse_invalid_creation_info(): - creation_info_parser = CreationInfoParser() - doc_dict = { - "spdxVersion": "2.3", - "SPDXID": DOCUMENT_SPDX_ID, - "name": "Example Document", - "creationInfo": { - "created": "2010-01-29T18:30:22Z", - "creators": ["Tool: LicenseFind-1.0", "Organization: ExampleCodeInspect ()", "Person: Jane Doe ()"], - }, - "dataLicense": None, - } - - with pytest.raises(SPDXParsingError): - creation_info_parser.parse_creation_info(doc_dict) diff --git a/tests/spdx/parser/jsonlikedict/test_error_message.py b/tests/spdx/parser/jsonlikedict/test_error_message.py deleted file mode 100644 index 207623ad4..000000000 --- a/tests/spdx/parser/jsonlikedict/test_error_message.py +++ /dev/null @@ -1,36 +0,0 @@ -from unittest import TestCase - -import pytest - -from spdx_tools.spdx.parser.error import SPDXParsingError -from spdx_tools.spdx.parser.jsonlikedict.package_parser import PackageParser - - -# To avoid duplication we use this invalid package as a proxy for the exact comparison of the generated error message. -# For all other classes we only check that a TypeError is raised if an incorrect type is specified. -def test_error_message(): - package_parser = PackageParser() - package = { - "SPDXID": "SPDXRef-Package", - "downloadLocation": 5, - "attributionTexts": ["text", 5, {"test": "data"}], - "packageFileName": 10, - } - - with pytest.raises(SPDXParsingError) as err: - package_parser.parse_package(package) - - TestCase().assertCountEqual( - err.value.get_messages(), - [ - 'Error while constructing Package: [\'SetterError Package: argument "name" ' - "(None) is not an instance of str: None', 'SetterError Package: argument " - '"download_location" (int) did not match any element in the union: ' - "[str, spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion, " - "spdx_tools.spdx.model.spdx_none.SpdxNone]: 5', 'SetterError Package: " - 'argument "file_name" (int) did not match any element in the union: ' - "[str, NoneType]: 10', 'SetterError Package: item 1 of argument " - "\"attribution_texts\" (list) is not an instance of str: [\\'text\\', 5, " - "{\\'test\\': \\'data\\'}]']" - ], - ) diff --git a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py index a2d4491c8..4ac335649 100644 --- a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py @@ -1,9 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -import pytest -from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.extracted_licensing_info_parser import ExtractedLicensingInfoParser @@ -34,20 +32,3 @@ def test_parse_extracted_licensing_info(): ) assert extracted_licensing_info.license_name == "Beer-Ware License (Version 42)" assert extracted_licensing_info.cross_references == ["http://people.freebsd.org/~phk/"] - - -def test_parse_invalid_extracted_licensing_info(): - extracted_licensing_info_parser = ExtractedLicensingInfoParser() - - extracted_licensing_infos_dict = { - "licenseId": "LicenseRef-Beerware-4.2", - "comment": 56, - "extractedText": '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you ' - "retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and " - "you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", - "name": "Beer-Ware License (Version 42)", - "seeAlsos": ["http://people.freebsd.org/~phk/"], - } - - with pytest.raises(SPDXParsingError): - extracted_licensing_info_parser.parse_extracted_licensing_info(extracted_licensing_infos_dict) diff --git a/tests/spdx/parser/jsonlikedict/test_package_parser.py b/tests/spdx/parser/jsonlikedict/test_package_parser.py index 5b933df8b..83f6b8316 100644 --- a/tests/spdx/parser/jsonlikedict/test_package_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_package_parser.py @@ -227,26 +227,6 @@ def test_parse_package( assert package.valid_until_date == datetime(2014, 1, 29, 18, 30, 22) -@pytest.mark.parametrize( - "incomplete_package_dict", - [ - {"SPDXID": "SPDXRef-Package"}, - {"SPDXID": "SPDXRef-Package", "name": 5, "downloadLocation": "NONE"}, - { - "SPDXID": "SPDXRef-Package", - "name": "Example Package", - "downloadLocation": "NONE", - "checksums": [{"algorithm": "SHA", "value": "1234"}], - }, - ], -) -def test_parse_invalid_package(incomplete_package_dict): - package_parser = PackageParser() - - with pytest.raises(SPDXParsingError): - package_parser.parse_package(incomplete_package_dict) - - def test_parse_packages(): package_parser = PackageParser() packages_list = [ @@ -264,14 +244,6 @@ def test_parse_packages(): parse_list_of_elements(packages_list, package_parser.parse_package) -def test_parse_external_ref(): - package_parser = PackageParser() - external_ref = {"referenceType": "fix"} - - with pytest.raises(SPDXParsingError): - package_parser.parse_external_ref(external_ref) - - def test_parse_invalid_external_package_ref_category(): package_parser = PackageParser() external_package_ref_category = "TEST" diff --git a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py index 327a83f6c..8f887b3aa 100644 --- a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py @@ -7,7 +7,6 @@ from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion -from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.relationship_parser import RelationshipParser @@ -29,18 +28,6 @@ def test_parse_relationship(): assert relationship.comment == "Comment." -def test_parse_incomplete_relationship(): - relationship_parser = RelationshipParser() - relationship_dict = { - "spdxElementId": DOCUMENT_SPDX_ID, - "relatedSpdxElement": "SPDXRef-Package", - "comment": "Comment.", - } - - with pytest.raises(SPDXParsingError): - relationship_parser.parse_relationship(relationship_dict) - - def test_parse_relationship_type(): relationship_parser = RelationshipParser() relationship_type_str = "DEPENDENCY_OF" diff --git a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py index 257a00e3a..bb4cbc821 100644 --- a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py @@ -70,31 +70,6 @@ def test_parse_snippet(copyright_text, expected_copyright_text): assert snippet.attribution_texts == ["Some example attibution text."] -def test_parse_incomplete_snippet(): - snippet_parser = SnippetParser() - incomplete_snippet_dict = {"SPDXID": "SPDXRef-Snippet", "file_spdx_id": "SPDXRef-File"} - - with pytest.raises(SPDXParsingError): - snippet_parser.parse_snippet(incomplete_snippet_dict) - - -def test_parse_snippet_with_invalid_snippet_range(): - snippet_parser = SnippetParser() - snippet_with_invalid_ranges_list = { - "SPDXID": "SPDXRef-Snippet", - "file_spdx_id": "SPDXRef-File", - "ranges": [ - { - "endPointer": {"offset": 23, "reference": "SPDXRef-DoapSource"}, - "startPointer": {"offset": "310s", "reference": "SPDXRef-DoapSource"}, - } - ], - } - - with pytest.raises(SPDXParsingError): - snippet_parser.parse_snippet(snippet_with_invalid_ranges_list) - - def test_parse_invalid_snippet_range(): snippet_parser = SnippetParser() diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py index 7facfce98..fb24ed0da 100644 --- a/tests/spdx/parser/rdf/test_file_parser.py +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -4,12 +4,10 @@ import os from unittest import TestCase -import pytest from license_expression import get_spdx_licensing -from rdflib import RDF, BNode, Graph, URIRef +from rdflib import RDF, Graph, URIRef from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, FileType, SpdxNoAssertion -from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.rdf.file_parser import parse_file from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE @@ -37,13 +35,3 @@ def test_parse_file(): assert file.license_comment == "licenseComment" assert file.notice == "fileNotice" assert file.attribution_texts == ["fileAttributionText"] - - -def test_parse_invalid_file(): - graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/invalid_documents/file_without_spdx_ids.xml")) - file_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.File) - doc_namespace = "https://some.namespace" - - assert isinstance(file_node, BNode) - with pytest.raises(SPDXParsingError): - parse_file(file_node, graph, doc_namespace) diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index 814ceceee..f6c968073 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -18,7 +18,6 @@ PackageVerificationCode, SpdxNoAssertion, ) -from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.rdf.package_parser import parse_external_package_ref, parse_package from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE @@ -96,13 +95,3 @@ def test_external_package_ref_parser(download_location, category, locator, type, assert external_package_ref.locator == locator assert external_package_ref.reference_type == type assert external_package_ref.comment == comment - - -def test_parse_invalid_package(): - graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/invalid_documents/file_without_spdx_ids.xml")) - package_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Package) - doc_namespace = "https://some.namespace" - - assert isinstance(package_node, BNode) - with pytest.raises(SPDXParsingError): - parse_package(package_node, graph, doc_namespace) diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index da2267221..1b4022827 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -159,13 +159,3 @@ def add_range_to_graph_helper(graph, predicate_value_class_member): graph.add((pointer_node, RDF.type, pointer_class)) graph.add((start_end_pointer, predicate, pointer_node)) graph.add((pointer_node, pointer_member, Literal(value))) - - -def test_parse_invalid_file(): - graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/invalid_documents/file_without_spdx_ids.xml")) - snippet_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Snippet) - doc_namespace = "https://some.namespace" - - assert isinstance(snippet_node, BNode) - with pytest.raises(SPDXParsingError): - parse_snippet(snippet_node, graph, doc_namespace) From 6e09299493d2be827789d8daa151ab19b262a513 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Thu, 1 Jun 2023 10:17:55 +0200 Subject: [PATCH 083/354] Revert "[issue-673] remove type checking due to performance issues" This reverts commit 21c7e32a2223fc281adfacca21a266fae5bec0cc. Signed-off-by: Holger Frydrych --- .../typing/dataclass_with_properties.py | 72 +++++++++- tests/spdx/jsonschema/test_converter.py | 4 +- tests/spdx/model/test_actor.py | 23 ++- tests/spdx/model/test_annotation.py | 32 +++++ tests/spdx/model/test_checksum.py | 12 ++ tests/spdx/model/test_creation_info.py | 75 ++++++++++ tests/spdx/model/test_document.py | 43 ++++++ .../spdx/model/test_external_document_ref.py | 19 +++ .../model/test_external_package_reference.py | 22 +++ .../model/test_extracted_licensing_info.py | 27 ++++ tests/spdx/model/test_file.py | 76 +++++++++- tests/spdx/model/test_package.py | 135 +++++++++++++++++- .../model/test_package_verification_code.py | 12 ++ tests/spdx/model/test_relationship.py | 22 +++ tests/spdx/model/test_snippet.py | 57 ++++++++ .../jsonlikedict/test_annotation_parser.py | 17 +++ .../jsonlikedict/test_checksum_parser.py | 8 ++ .../jsonlikedict/test_creation_info_parser.py | 34 +++++ .../parser/jsonlikedict/test_error_message.py | 36 +++++ .../test_extracted_licensing_info_parser.py | 19 +++ .../jsonlikedict/test_package_parser.py | 28 ++++ .../jsonlikedict/test_relationship_parser.py | 13 ++ .../jsonlikedict/test_snippet_parser.py | 25 ++++ tests/spdx/parser/rdf/test_file_parser.py | 14 +- tests/spdx/parser/rdf/test_package_parser.py | 11 ++ tests/spdx/parser/rdf/test_snippet_parser.py | 10 ++ 26 files changed, 834 insertions(+), 12 deletions(-) create mode 100644 tests/spdx/parser/jsonlikedict/test_error_message.py diff --git a/src/spdx_tools/common/typing/dataclass_with_properties.py b/src/spdx_tools/common/typing/dataclass_with_properties.py index 3188fee44..5f58c0b81 100644 --- a/src/spdx_tools/common/typing/dataclass_with_properties.py +++ b/src/spdx_tools/common/typing/dataclass_with_properties.py @@ -1,9 +1,71 @@ -# SPDX-FileCopyrightText: 2022 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 +import re from dataclasses import dataclass +from typeguard import CollectionCheckStrategy, TypeCheckError, config, typechecked + +config.collection_check_strategy = CollectionCheckStrategy.ALL_ITEMS + def dataclass_with_properties(cls): - # placeholder decorator until we figure out how to do run-time type checking more performant - return dataclass(cls) + """Decorator to generate a dataclass with properties out of the class' value:type list. + Their getters and setters will be subjected to the @typechecked decorator to ensure type conformity.""" + data_cls = dataclass(cls) + for field_name, field_type in data_cls.__annotations__.items(): + set_field = make_setter(field_name, field_type) + get_field = make_getter(field_name, field_type) + + setattr(data_cls, field_name, property(get_field, set_field)) + + return data_cls + + +def make_setter(field_name, field_type): + """helper method to avoid late binding when generating functions in a for loop""" + + @typechecked + def set_field(self, value: field_type): + setattr(self, f"_{field_name}", value) + + def set_field_with_better_error_message(self, value: field_type): + try: + set_field(self, value) + except TypeCheckError as err: + error_message: str = f"SetterError {self.__class__.__name__}: {err}" + if "did not match any element in the union" in error_message: + error_message = simplify_error_message_for_union(error_message) + + # As setters are created dynamically, their argument name is always "value". We replace it by the + # actual name so the error message is more helpful. + raise TypeError(error_message.replace("value", field_name, 1) + f": {value}") + + def simplify_error_message_for_union(error_message: str) -> str: + # The error message from typeguard is more verbose than we need, so we simplify the message + # to provide the user with a more compact error message. + types_in_union = re.compile(r"\n\s*(.*?):", re.UNICODE) + list_of_types = re.findall(types_in_union, error_message) + text_to_replace = error_message.split("did not match any element in the union:")[-1] + error_message = error_message.replace(text_to_replace, " [" + ", ".join(list_of_types) + "]") + return error_message + + return set_field_with_better_error_message + + +def make_getter(field_name, field_type): + """helper method to avoid late binding when generating functions in a for loop""" + + @typechecked + def get_field(self) -> field_type: + return getattr(self, f"_{field_name}") + + def get_field_with_better_error_message(self) -> field_type: + try: + return get_field(self) + except TypeCheckError as err: + error_message: str = f"GetterError {self.__class__.__name__}: {err}" + # As getters are created dynamically, their argument name is always "the return value". + # We replace it by the actual name so the error message is more helpful. + raise TypeError( + error_message.replace("the return value", field_name, 1) + f': {getattr(self, f"_{field_name}")}' + ) + + return get_field_with_better_error_message diff --git a/tests/spdx/jsonschema/test_converter.py b/tests/spdx/jsonschema/test_converter.py index 0a94612bb..46558d904 100644 --- a/tests/spdx/jsonschema/test_converter.py +++ b/tests/spdx/jsonschema/test_converter.py @@ -1,12 +1,12 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from dataclasses import dataclass from enum import auto from typing import Any, Type import pytest +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.json_property import JsonProperty @@ -18,7 +18,7 @@ class TestPropertyType(JsonProperty): SECOND_NAME = auto() -@dataclass +@dataclass_with_properties class TestDataModelType: first_property: str second_property: int diff --git a/tests/spdx/model/test_actor.py b/tests/spdx/model/test_actor.py index 90dba8ea6..e41e40b4e 100644 --- a/tests/spdx/model/test_actor.py +++ b/tests/spdx/model/test_actor.py @@ -15,12 +15,33 @@ def test_correct_initialization(): def test_correct_initialization_with_optional_as_none(): - actor = Actor(ActorType.TOOL, "tool_name") + actor = Actor(ActorType.TOOL, "tool_name", None) assert actor.actor_type == ActorType.TOOL assert actor.name == "tool_name" assert actor.email is None +def test_wrong_type_in_actor_type(): + with pytest.raises(TypeError): + Actor("PERSON", "name") + + +def test_wrong_type_in_name(): + with pytest.raises(TypeError): + Actor(ActorType.PERSON, 42) + + +def test_wrong_type_in_email(): + with pytest.raises(TypeError): + Actor(ActorType.PERSON, "name", []) + + +def test_wrong_type_in_email_after_initializing(): + with pytest.raises(TypeError): + actor = Actor(ActorType.PERSON, "name") + actor.email = [] + + @pytest.mark.parametrize( "actor,expected_string", [ diff --git a/tests/spdx/model/test_annotation.py b/tests/spdx/model/test_annotation.py index 2ceb2dae0..5638b0b98 100644 --- a/tests/spdx/model/test_annotation.py +++ b/tests/spdx/model/test_annotation.py @@ -5,6 +5,8 @@ from datetime import datetime from unittest import mock +import pytest + from spdx_tools.spdx.model import Annotation, AnnotationType @@ -16,3 +18,33 @@ def test_correct_initialization(actor): assert annotation.annotator == actor assert annotation.annotation_date == datetime(2022, 1, 1) assert annotation.annotation_comment == "comment" + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_spdx_id(actor): + with pytest.raises(TypeError): + Annotation(42, AnnotationType.OTHER, actor, datetime(2022, 1, 1), "comment") + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_annotation_type(actor): + with pytest.raises(TypeError): + Annotation("id", 42, actor, datetime(2022, 1, 1), "comment") + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_annotator(actor): + with pytest.raises(TypeError): + Annotation("id", AnnotationType.OTHER, 42, datetime(2022, 1, 1), "comment") + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_annotation_date(actor): + with pytest.raises(TypeError): + Annotation("id", AnnotationType.OTHER, actor, 42, "comment") + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_annotation_comment(actor): + with pytest.raises(TypeError): + Annotation("id", AnnotationType.OTHER, actor, datetime(2022, 1, 1), 42) diff --git a/tests/spdx/model/test_checksum.py b/tests/spdx/model/test_checksum.py index 6f0a2c5f8..308d95486 100644 --- a/tests/spdx/model/test_checksum.py +++ b/tests/spdx/model/test_checksum.py @@ -2,6 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 +import pytest + from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm @@ -9,3 +11,13 @@ def test_correct_initialization(): checksum = Checksum(ChecksumAlgorithm.BLAKE2B_256, "value") assert checksum.algorithm == ChecksumAlgorithm.BLAKE2B_256 assert checksum.value == "value" + + +def test_wrong_type_in_algorithm(): + with pytest.raises(TypeError): + Checksum(42, "value") + + +def test_wrong_type_in_value(): + with pytest.raises(TypeError): + Checksum(ChecksumAlgorithm.BLAKE2B_256, 42) diff --git a/tests/spdx/model/test_creation_info.py b/tests/spdx/model/test_creation_info.py index f204201ee..c0912005c 100644 --- a/tests/spdx/model/test_creation_info.py +++ b/tests/spdx/model/test_creation_info.py @@ -5,6 +5,8 @@ from datetime import datetime from unittest import mock +import pytest + from spdx_tools.spdx.model import CreationInfo, Version @@ -35,3 +37,76 @@ def test_correct_initialization(actor, ext_ref): assert creation_info.external_document_refs == [ext_ref, ext_ref] assert creation_info.license_list_version == Version(6, 3) assert creation_info.document_comment == "doc_comment" + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_spdx_version(actor): + with pytest.raises(TypeError): + CreationInfo(42, "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1)) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_spdx_id(actor): + with pytest.raises(TypeError): + CreationInfo("version", 42, "name", "namespace", [actor, actor], datetime(2022, 1, 1)) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_name(actor): + with pytest.raises(TypeError): + CreationInfo("version", "id", 42, "namespace", [actor, actor], datetime(2022, 1, 1)) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_document_namespace(actor): + with pytest.raises(TypeError): + CreationInfo("version", "id", "name", 42, [actor, actor], datetime(2022, 1, 1)) + + +def test_wrong_type_in_creators(): + with pytest.raises(TypeError): + CreationInfo("version", "id", "name", "namespace", ["person"], datetime(2022, 1, 1)) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_created(actor): + with pytest.raises(TypeError): + CreationInfo("version", "id", "name", "namespace", [actor, actor], "2022-01-01") + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_creator_comment(actor): + with pytest.raises(TypeError): + CreationInfo( + "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), creator_comment=["string"] + ) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_data_license(actor): + with pytest.raises(TypeError): + CreationInfo("version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), data_license=42) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_external_document_refs(actor): + with pytest.raises(TypeError): + CreationInfo( + "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), external_document_refs=() + ) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_license_list_version(actor): + with pytest.raises(TypeError): + CreationInfo( + "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), license_list_version="6.4" + ) + + +@mock.patch("spdx_tools.spdx.model.Actor", autospec=True) +def test_wrong_type_in_document_comment(actor): + with pytest.raises(TypeError): + CreationInfo( + "version", "id", "name", "namespace", [actor, actor], datetime(2022, 1, 1), document_comment=["1"] + ) diff --git a/tests/spdx/model/test_document.py b/tests/spdx/model/test_document.py index 575032953..9d4079cb4 100644 --- a/tests/spdx/model/test_document.py +++ b/tests/spdx/model/test_document.py @@ -4,6 +4,8 @@ from unittest import mock +import pytest + from spdx_tools.spdx.model import Document @@ -43,3 +45,44 @@ def test_correct_initialization_with_default_values(creation_info): assert document.annotations == [] assert document.relationships == [] assert document.extracted_licensing_info == [] + + +def test_wrong_type_in_creation_info(): + with pytest.raises(TypeError): + Document("string") + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_wrong_type_in_packages(creation_info): + with pytest.raises(TypeError): + Document(creation_info, packages=["string"]) + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_wrong_type_in_files(creation_info): + with pytest.raises(TypeError): + Document(creation_info, files={}) + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_wrong_type_in_snippets(creation_info): + with pytest.raises(TypeError): + Document(creation_info, snippets=()) + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_wrong_type_in_annotations(creation_info): + with pytest.raises(TypeError): + Document(creation_info, annotations=["string"]) + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_wrong_type_in_relationships(creation_info): + with pytest.raises(TypeError): + Document(creation_info, relationships="string") + + +@mock.patch("spdx_tools.spdx.model.CreationInfo", autospec=True) +def test_wrong_type_in_extracted_licensing_info(creation_info): + with pytest.raises(TypeError): + Document(creation_info, extracted_licensing_info=42) diff --git a/tests/spdx/model/test_external_document_ref.py b/tests/spdx/model/test_external_document_ref.py index ac1c8fc96..4b32d6bf3 100644 --- a/tests/spdx/model/test_external_document_ref.py +++ b/tests/spdx/model/test_external_document_ref.py @@ -4,6 +4,8 @@ from unittest import mock +import pytest + from spdx_tools.spdx.model import ExternalDocumentRef @@ -13,3 +15,20 @@ def test_correct_initialization(checksum): assert external_document_ref.document_ref_id == "id" assert external_document_ref.document_uri == "uri" assert external_document_ref.checksum == checksum + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_spdx_id(checksum): + with pytest.raises(TypeError): + ExternalDocumentRef(42, "uri", checksum) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_document_uri(checksum): + with pytest.raises(TypeError): + ExternalDocumentRef("id", 42, checksum) + + +def test_wrong_type_in_checksum(): + with pytest.raises(TypeError): + ExternalDocumentRef("id", "uri", 42) diff --git a/tests/spdx/model/test_external_package_reference.py b/tests/spdx/model/test_external_package_reference.py index 31610a554..d81bcc221 100644 --- a/tests/spdx/model/test_external_package_reference.py +++ b/tests/spdx/model/test_external_package_reference.py @@ -2,6 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 +import pytest + from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory @@ -11,3 +13,23 @@ def test_correct_initialization(): assert external_package_reference.reference_type == "type" assert external_package_reference.locator == "locator" assert external_package_reference.comment == "comment" + + +def test_wrong_type_in_category(): + with pytest.raises(TypeError): + ExternalPackageRef([ExternalPackageRefCategory.OTHER], "type", "locator") + + +def test_wrong_type_in_reference_type(): + with pytest.raises(TypeError): + ExternalPackageRef(ExternalPackageRefCategory.OTHER, 42, "locator") + + +def test_wrong_type_in_locator(): + with pytest.raises(TypeError): + ExternalPackageRef(ExternalPackageRefCategory.OTHER, "type", 42) + + +def test_wrong_type_in_comment(): + with pytest.raises(TypeError): + ExternalPackageRef(ExternalPackageRefCategory.OTHER, "type", "locator", []) diff --git a/tests/spdx/model/test_extracted_licensing_info.py b/tests/spdx/model/test_extracted_licensing_info.py index be187544e..75dc79aab 100644 --- a/tests/spdx/model/test_extracted_licensing_info.py +++ b/tests/spdx/model/test_extracted_licensing_info.py @@ -2,6 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 +import pytest + from spdx_tools.spdx.model import ExtractedLicensingInfo @@ -12,3 +14,28 @@ def test_correct_initialization(): assert extracted_licensing_info.license_name == "name" assert extracted_licensing_info.cross_references == ["reference"] assert extracted_licensing_info.comment == "comment" + + +def test_wrong_type_in_license_id(): + with pytest.raises(TypeError): + ExtractedLicensingInfo(license_id=42) + + +def test_wrong_type_in_extracted_text(): + with pytest.raises(TypeError): + ExtractedLicensingInfo(extracted_text=42) + + +def test_wrong_type_in_license_name(): + with pytest.raises(TypeError): + ExtractedLicensingInfo(license_name=42) + + +def test_wrong_type_in_cross_references(): + with pytest.raises(TypeError): + ExtractedLicensingInfo(cross_references=["ref", 42]) + + +def test_wrong_type_in_comment(): + with pytest.raises(TypeError): + ExtractedLicensingInfo(comment=42) diff --git a/tests/spdx/model/test_file.py b/tests/spdx/model/test_file.py index 2470e7379..592e8dc4f 100644 --- a/tests/spdx/model/test_file.py +++ b/tests/spdx/model/test_file.py @@ -4,7 +4,9 @@ from unittest import mock -from spdx_tools.spdx.model import File, FileType, SpdxNoAssertion, SpdxNone +import pytest + +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, File, FileType, SpdxNoAssertion, SpdxNone @mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) @@ -52,3 +54,75 @@ def test_correct_initialization_with_default_values(checksum): assert file.notice is None assert file.contributors == [] assert file.attribution_texts == [] + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_name(checksum): + with pytest.raises(TypeError): + File(42, "id", [checksum]) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_spdx_id(checksum): + with pytest.raises(TypeError): + File("name", 42, [checksum]) + + +def test_wrong_type_in_checksum(): + checksum = Checksum(ChecksumAlgorithm.BLAKE2B_256, "value") + with pytest.raises(TypeError): + File("name", "id", checksum) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_file_type(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], file_types=FileType.OTHER) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_license_concluded(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], license_concluded="NONE") + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_license_info_in_file(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], license_info_in_file=[SpdxNone]) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_license_comment(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], license_comment=42) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_copyright_text(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], copyright_text=[SpdxNone()]) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_comment(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], comment=42) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_notice(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], notice=["notice"]) + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_contributors(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], contributors="contributor") + + +@mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) +def test_wrong_type_in_attribution_texts(checksum): + with pytest.raises(TypeError): + File("name", "id", [checksum], attribution_texts=["attribution", 42]) diff --git a/tests/spdx/model/test_package.py b/tests/spdx/model/test_package.py index 833f664ff..c533b2812 100644 --- a/tests/spdx/model/test_package.py +++ b/tests/spdx/model/test_package.py @@ -5,9 +5,10 @@ from datetime import datetime from unittest import mock -from license_expression import Licensing +import pytest +from license_expression import LicenseExpression, Licensing -from spdx_tools.spdx.model import Package, PackagePurpose, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, Package, PackagePurpose, SpdxNoAssertion, SpdxNone @mock.patch("spdx_tools.spdx.model.ExternalPackageRef", autospec=True) @@ -99,3 +100,133 @@ def test_correct_initialization_with_default_values(): assert package.release_date is None assert package.built_date is None assert package.valid_until_date is None + + +def test_wrong_type_in_spdx_id(): + with pytest.raises(TypeError): + Package(42, "name", "location") + + +def test_wrong_type_in_name(): + with pytest.raises(TypeError): + Package("id", 42, "location") + + +def test_wrong_type_in_download_location(): + with pytest.raises(TypeError): + Package("id", "name", 42) + + +def test_wrong_type_in_version(): + with pytest.raises(TypeError): + Package("id", "name", "location", version=42) + + +def test_wrong_type_in_file_name(): + with pytest.raises(TypeError): + Package("id", "name", "location", file_name=42) + + +def test_wrong_type_in_supplier(): + with pytest.raises(TypeError): + Package("id", "name", "location", supplier=SpdxNone()) + + +def test_wrong_type_in_originator(): + with pytest.raises(TypeError): + Package("id", "name", "location", originator=SpdxNone()) + + +def test_wrong_type_in_files_analyzed(): + with pytest.raises(TypeError): + Package("id", "name", "location", files_analyzed=None) + + +def test_wrong_type_in_verification_code(): + with pytest.raises(TypeError): + Package("id", "name", "location", verification_code=[]) + + +def test_wrong_type_in_checksums(): + with pytest.raises(TypeError): + Package("id", "name", "location", checksums=Checksum(ChecksumAlgorithm.MD2, "value")) + + +def test_wrong_type_in_homepage(): + with pytest.raises(TypeError): + Package("id", "name", "location", homepage=42) + + +def test_wrong_type_in_source_info(): + with pytest.raises(TypeError): + Package("id", "name", "location", source_info=42) + + +def test_wrong_type_in_license_concluded(): + with pytest.raises(TypeError): + Package("id", "name", "location", license_concluded=[]) + + +def test_wrong_type_in_license_info_from_files(): + with pytest.raises(TypeError): + Package("id", "name", "location", license_info_from_files=LicenseExpression("string")) + + +def test_wrong_type_in_license_declared(): + with pytest.raises(TypeError): + Package("id", "name", "location", license_declared=[]) + + +def test_wrong_type_in_license_comment(): + with pytest.raises(TypeError): + Package("id", "name", "location", license_comment=42) + + +def test_wrong_type_in_copyright_text(): + with pytest.raises(TypeError): + Package("id", "name", "location", copyright_text=42) + + +def test_wrong_type_in_summary(): + with pytest.raises(TypeError): + Package("id", "name", "location", summary=42) + + +def test_wrong_type_in_description(): + with pytest.raises(TypeError): + Package("id", "name", "location", description=42) + + +def test_wrong_type_in_comment(): + with pytest.raises(TypeError): + Package("id", "name", "location", comment=[]) + + +def test_wrong_type_in_external_references(): + with pytest.raises(TypeError): + Package("id", "name", "location", external_references=["external_ref"]) + + +def test_wrong_type_in_attribution_texts(): + with pytest.raises(TypeError): + Package("id", "name", "location", attribution_texts="text") + + +def test_wrong_type_in_primary_package_purpose(): + with pytest.raises(TypeError): + Package("id", "name", "location", primary_package_purpose=[]) + + +def test_wrong_type_in_release_date(): + with pytest.raises(TypeError): + Package("id", "name", "location", release_date=42) + + +def test_wrong_type_in_built_date(): + with pytest.raises(TypeError): + Package("id", "name", "location", built_date="2022-01-01") + + +def test_wrong_type_in_valid_until_date(): + with pytest.raises(TypeError): + Package("id", "name", "location", valid_until_date=SpdxNone()) diff --git a/tests/spdx/model/test_package_verification_code.py b/tests/spdx/model/test_package_verification_code.py index 46e8f221a..e1492a91d 100644 --- a/tests/spdx/model/test_package_verification_code.py +++ b/tests/spdx/model/test_package_verification_code.py @@ -2,6 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 +import pytest + from spdx_tools.spdx.model import PackageVerificationCode @@ -9,3 +11,13 @@ def test_correct_initialization(): package_verification_code = PackageVerificationCode("value", ["file1", "file2"]) assert package_verification_code.value == "value" assert package_verification_code.excluded_files == ["file1", "file2"] + + +def test_wrong_type_in_value(): + with pytest.raises(TypeError): + PackageVerificationCode(42, ["file1", "file2"]) + + +def test_wrong_type_in_excluded_files(): + with pytest.raises(TypeError): + PackageVerificationCode("value", "file1") diff --git a/tests/spdx/model/test_relationship.py b/tests/spdx/model/test_relationship.py index 7f9609f5b..0ffb62482 100644 --- a/tests/spdx/model/test_relationship.py +++ b/tests/spdx/model/test_relationship.py @@ -2,6 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 +import pytest + from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion @@ -11,3 +13,23 @@ def test_correct_initialization(): assert relationship.relationship_type == RelationshipType.OTHER assert relationship.related_spdx_element_id == SpdxNoAssertion() assert relationship.comment == "comment" + + +def test_wrong_type_in_spdx_element_id(): + with pytest.raises(TypeError): + Relationship(SpdxNoAssertion(), RelationshipType.OTHER, "other_id") + + +def test_wrong_type_in_relationship_type(): + with pytest.raises(TypeError): + Relationship("id", 42, "other_id") + + +def test_wrong_type_in_related_spdx_element_id(): + with pytest.raises(TypeError): + Relationship("id", RelationshipType.OTHER, 42) + + +def test_wrong_type_in_comment(): + with pytest.raises(TypeError): + Relationship("id", RelationshipType.OTHER, "other_id", 42) diff --git a/tests/spdx/model/test_snippet.py b/tests/spdx/model/test_snippet.py index 909e53bf7..7fcf21581 100644 --- a/tests/spdx/model/test_snippet.py +++ b/tests/spdx/model/test_snippet.py @@ -2,6 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 +import pytest + from spdx_tools.spdx.model import Snippet, SpdxNoAssertion, SpdxNone @@ -45,3 +47,58 @@ def test_correct_initialization_with_default_values(): assert snippet.comment is None assert snippet.name is None assert snippet.attribution_texts == [] + + +def test_wrong_type_in_spdx_id(): + with pytest.raises(TypeError): + Snippet(42, "file_id", (200, 400)) + + +def test_wrong_type_in_file_spdx_id(): + with pytest.raises(TypeError): + Snippet("id", 42, (200, 400)) + + +def test_wrong_type_in_byte_range(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 300, 400)) + + +def test_wrong_type_in_line_range(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), line_range=(20, "40")) + + +def test_wrong_type_in_license_concluded(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), license_concluded="NONE") + + +def test_wrong_type_in_license_info_in_snippet(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), license_info_in_snippet=SpdxNoAssertion()) + + +def test_wrong_type_in_license_comment(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), license_comment=[]) + + +def test_wrong_type_in_copyright_text(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), copyright_text=["copyright"]) + + +def test_wrong_type_in_comment(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), comment=["comment"]) + + +def test_wrong_type_in_name(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), name=42) + + +def test_wrong_type_in_attribution_texts(): + with pytest.raises(TypeError): + Snippet("id", "file_id", (200, 400), attribution_texts="attribution") diff --git a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py index 5511da8a6..ac814d6cd 100644 --- a/tests/spdx/parser/jsonlikedict/test_annotation_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_annotation_parser.py @@ -4,8 +4,11 @@ import datetime from unittest import TestCase +import pytest + from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID from spdx_tools.spdx.model import Actor, ActorType, Annotation, AnnotationType +from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.annotation_parser import AnnotationParser @@ -113,3 +116,17 @@ def test_parse_all_annotations(): ), ], ) + + +@pytest.mark.parametrize( + "incomplete_annotation_dict", + [ + {"annotator": "Person: Jane Doe ()"}, + {"annotationDate": "2010-01-29T18:30:22Z"}, + ], +) +def test_parse_incomplete_annotation(incomplete_annotation_dict): + annotation_parser = AnnotationParser() + + with pytest.raises(SPDXParsingError): + annotation_parser.parse_annotation(incomplete_annotation_dict) diff --git a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py index c01654062..24676cccf 100644 --- a/tests/spdx/parser/jsonlikedict/test_checksum_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_checksum_parser.py @@ -30,3 +30,11 @@ def test_parse_invalid_checksum(): TestCase().assertCountEqual( err.value.get_messages(), ["Error while parsing Checksum: ['Invalid ChecksumAlgorithm: SHA']"] ) + + +def test_parse_incomplete_checksum(): + checksum_parser = ChecksumParser() + checksum_dict = {"algorithm": "SHA1"} + + with pytest.raises(SPDXParsingError): + checksum_parser.parse_checksum(checksum_dict) diff --git a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py index 85e2b3321..1a9851016 100644 --- a/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_creation_info_parser.py @@ -4,8 +4,11 @@ from datetime import datetime from unittest import TestCase +import pytest + from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID from spdx_tools.spdx.model import Actor, ActorType, Checksum, ChecksumAlgorithm, ExternalDocumentRef, Version +from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.creation_info_parser import CreationInfoParser @@ -54,3 +57,34 @@ def test_parse_creation_info(): document_uri="http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301", ) ] + + +@pytest.mark.parametrize( + "incomplete_dict", + [ + {"spdxVersion": "2.3", "SPDXID": DOCUMENT_SPDX_ID, "name": "Example Document"}, + {"creationInfo": {"created": "2019-02-01T11:30:40Z"}}, + ], +) +def test_parse_incomplete_document_info(incomplete_dict): + creation_info_parser = CreationInfoParser() + + with pytest.raises(SPDXParsingError): + creation_info_parser.parse_creation_info(incomplete_dict) + + +def test_parse_invalid_creation_info(): + creation_info_parser = CreationInfoParser() + doc_dict = { + "spdxVersion": "2.3", + "SPDXID": DOCUMENT_SPDX_ID, + "name": "Example Document", + "creationInfo": { + "created": "2010-01-29T18:30:22Z", + "creators": ["Tool: LicenseFind-1.0", "Organization: ExampleCodeInspect ()", "Person: Jane Doe ()"], + }, + "dataLicense": None, + } + + with pytest.raises(SPDXParsingError): + creation_info_parser.parse_creation_info(doc_dict) diff --git a/tests/spdx/parser/jsonlikedict/test_error_message.py b/tests/spdx/parser/jsonlikedict/test_error_message.py new file mode 100644 index 000000000..207623ad4 --- /dev/null +++ b/tests/spdx/parser/jsonlikedict/test_error_message.py @@ -0,0 +1,36 @@ +from unittest import TestCase + +import pytest + +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.jsonlikedict.package_parser import PackageParser + + +# To avoid duplication we use this invalid package as a proxy for the exact comparison of the generated error message. +# For all other classes we only check that a TypeError is raised if an incorrect type is specified. +def test_error_message(): + package_parser = PackageParser() + package = { + "SPDXID": "SPDXRef-Package", + "downloadLocation": 5, + "attributionTexts": ["text", 5, {"test": "data"}], + "packageFileName": 10, + } + + with pytest.raises(SPDXParsingError) as err: + package_parser.parse_package(package) + + TestCase().assertCountEqual( + err.value.get_messages(), + [ + 'Error while constructing Package: [\'SetterError Package: argument "name" ' + "(None) is not an instance of str: None', 'SetterError Package: argument " + '"download_location" (int) did not match any element in the union: ' + "[str, spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion, " + "spdx_tools.spdx.model.spdx_none.SpdxNone]: 5', 'SetterError Package: " + 'argument "file_name" (int) did not match any element in the union: ' + "[str, NoneType]: 10', 'SetterError Package: item 1 of argument " + "\"attribution_texts\" (list) is not an instance of str: [\\'text\\', 5, " + "{\\'test\\': \\'data\\'}]']" + ], + ) diff --git a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py index 4ac335649..a2d4491c8 100644 --- a/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_extracted_licensing_info_parser.py @@ -1,7 +1,9 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +import pytest +from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.extracted_licensing_info_parser import ExtractedLicensingInfoParser @@ -32,3 +34,20 @@ def test_parse_extracted_licensing_info(): ) assert extracted_licensing_info.license_name == "Beer-Ware License (Version 42)" assert extracted_licensing_info.cross_references == ["http://people.freebsd.org/~phk/"] + + +def test_parse_invalid_extracted_licensing_info(): + extracted_licensing_info_parser = ExtractedLicensingInfoParser() + + extracted_licensing_infos_dict = { + "licenseId": "LicenseRef-Beerware-4.2", + "comment": 56, + "extractedText": '"THE BEER-WARE LICENSE" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you ' + "retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and " + "you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "name": "Beer-Ware License (Version 42)", + "seeAlsos": ["http://people.freebsd.org/~phk/"], + } + + with pytest.raises(SPDXParsingError): + extracted_licensing_info_parser.parse_extracted_licensing_info(extracted_licensing_infos_dict) diff --git a/tests/spdx/parser/jsonlikedict/test_package_parser.py b/tests/spdx/parser/jsonlikedict/test_package_parser.py index 83f6b8316..5b933df8b 100644 --- a/tests/spdx/parser/jsonlikedict/test_package_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_package_parser.py @@ -227,6 +227,26 @@ def test_parse_package( assert package.valid_until_date == datetime(2014, 1, 29, 18, 30, 22) +@pytest.mark.parametrize( + "incomplete_package_dict", + [ + {"SPDXID": "SPDXRef-Package"}, + {"SPDXID": "SPDXRef-Package", "name": 5, "downloadLocation": "NONE"}, + { + "SPDXID": "SPDXRef-Package", + "name": "Example Package", + "downloadLocation": "NONE", + "checksums": [{"algorithm": "SHA", "value": "1234"}], + }, + ], +) +def test_parse_invalid_package(incomplete_package_dict): + package_parser = PackageParser() + + with pytest.raises(SPDXParsingError): + package_parser.parse_package(incomplete_package_dict) + + def test_parse_packages(): package_parser = PackageParser() packages_list = [ @@ -244,6 +264,14 @@ def test_parse_packages(): parse_list_of_elements(packages_list, package_parser.parse_package) +def test_parse_external_ref(): + package_parser = PackageParser() + external_ref = {"referenceType": "fix"} + + with pytest.raises(SPDXParsingError): + package_parser.parse_external_ref(external_ref) + + def test_parse_invalid_external_package_ref_category(): package_parser = PackageParser() external_package_ref_category = "TEST" diff --git a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py index 8f887b3aa..327a83f6c 100644 --- a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py @@ -7,6 +7,7 @@ from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID from spdx_tools.spdx.model import Relationship, RelationshipType, SpdxNoAssertion +from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.relationship_parser import RelationshipParser @@ -28,6 +29,18 @@ def test_parse_relationship(): assert relationship.comment == "Comment." +def test_parse_incomplete_relationship(): + relationship_parser = RelationshipParser() + relationship_dict = { + "spdxElementId": DOCUMENT_SPDX_ID, + "relatedSpdxElement": "SPDXRef-Package", + "comment": "Comment.", + } + + with pytest.raises(SPDXParsingError): + relationship_parser.parse_relationship(relationship_dict) + + def test_parse_relationship_type(): relationship_parser = RelationshipParser() relationship_type_str = "DEPENDENCY_OF" diff --git a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py index bb4cbc821..257a00e3a 100644 --- a/tests/spdx/parser/jsonlikedict/test_snippet_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_snippet_parser.py @@ -70,6 +70,31 @@ def test_parse_snippet(copyright_text, expected_copyright_text): assert snippet.attribution_texts == ["Some example attibution text."] +def test_parse_incomplete_snippet(): + snippet_parser = SnippetParser() + incomplete_snippet_dict = {"SPDXID": "SPDXRef-Snippet", "file_spdx_id": "SPDXRef-File"} + + with pytest.raises(SPDXParsingError): + snippet_parser.parse_snippet(incomplete_snippet_dict) + + +def test_parse_snippet_with_invalid_snippet_range(): + snippet_parser = SnippetParser() + snippet_with_invalid_ranges_list = { + "SPDXID": "SPDXRef-Snippet", + "file_spdx_id": "SPDXRef-File", + "ranges": [ + { + "endPointer": {"offset": 23, "reference": "SPDXRef-DoapSource"}, + "startPointer": {"offset": "310s", "reference": "SPDXRef-DoapSource"}, + } + ], + } + + with pytest.raises(SPDXParsingError): + snippet_parser.parse_snippet(snippet_with_invalid_ranges_list) + + def test_parse_invalid_snippet_range(): snippet_parser = SnippetParser() diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py index fb24ed0da..7facfce98 100644 --- a/tests/spdx/parser/rdf/test_file_parser.py +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -4,10 +4,12 @@ import os from unittest import TestCase +import pytest from license_expression import get_spdx_licensing -from rdflib import RDF, Graph, URIRef +from rdflib import RDF, BNode, Graph, URIRef from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, FileType, SpdxNoAssertion +from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.rdf.file_parser import parse_file from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE @@ -35,3 +37,13 @@ def test_parse_file(): assert file.license_comment == "licenseComment" assert file.notice == "fileNotice" assert file.attribution_texts == ["fileAttributionText"] + + +def test_parse_invalid_file(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/invalid_documents/file_without_spdx_ids.xml")) + file_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.File) + doc_namespace = "https://some.namespace" + + assert isinstance(file_node, BNode) + with pytest.raises(SPDXParsingError): + parse_file(file_node, graph, doc_namespace) diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index f6c968073..814ceceee 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -18,6 +18,7 @@ PackageVerificationCode, SpdxNoAssertion, ) +from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.rdf.package_parser import parse_external_package_ref, parse_package from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE @@ -95,3 +96,13 @@ def test_external_package_ref_parser(download_location, category, locator, type, assert external_package_ref.locator == locator assert external_package_ref.reference_type == type assert external_package_ref.comment == comment + + +def test_parse_invalid_package(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/invalid_documents/file_without_spdx_ids.xml")) + package_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Package) + doc_namespace = "https://some.namespace" + + assert isinstance(package_node, BNode) + with pytest.raises(SPDXParsingError): + parse_package(package_node, graph, doc_namespace) diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index 1b4022827..da2267221 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -159,3 +159,13 @@ def add_range_to_graph_helper(graph, predicate_value_class_member): graph.add((pointer_node, RDF.type, pointer_class)) graph.add((start_end_pointer, predicate, pointer_node)) graph.add((pointer_node, pointer_member, Literal(value))) + + +def test_parse_invalid_file(): + graph = Graph().parse(os.path.join(os.path.dirname(__file__), "data/invalid_documents/file_without_spdx_ids.xml")) + snippet_node = graph.value(predicate=RDF.type, object=SPDX_NAMESPACE.Snippet) + doc_namespace = "https://some.namespace" + + assert isinstance(snippet_node, BNode) + with pytest.raises(SPDXParsingError): + parse_snippet(snippet_node, graph, doc_namespace) From e112dafd852febbaa37eb4881bf91d429256f895 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Thu, 1 Jun 2023 10:37:03 +0200 Subject: [PATCH 084/354] Replace typeguard type checking with beartype. typeguard was prohibitively slow on large inputs, beartype is significantly faster. However, beartype comes with a caveat in that it does not do deep nested type checks, but instead utilizes randomized sampled testing. As such, this still allows certain misuses of types to go undetected and may not be our final solution. However, in the meantime we deem it is much better to have beartype than not have any type checking taking place. Signed-off-by: Holger Frydrych --- pyproject.toml | 2 +- .../typing/dataclass_with_properties.py | 39 ++++--------------- 2 files changed, 8 insertions(+), 33 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 52590bca7..a77d1db8a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ classifiers = [ ] urls = { Homepage = "https://github.com/spdx/tools-python" } requires-python = ">=3.7" -dependencies = ["click", "pyyaml", "xmltodict", "rdflib", "typeguard==4.0.0", "uritools", "license_expression", "ply"] +dependencies = ["click", "pyyaml", "xmltodict", "rdflib", "beartype", "uritools", "license_expression", "ply"] dynamic = ["version"] [project.optional-dependencies] diff --git a/src/spdx_tools/common/typing/dataclass_with_properties.py b/src/spdx_tools/common/typing/dataclass_with_properties.py index 5f58c0b81..6e05ca343 100644 --- a/src/spdx_tools/common/typing/dataclass_with_properties.py +++ b/src/spdx_tools/common/typing/dataclass_with_properties.py @@ -1,9 +1,7 @@ -import re from dataclasses import dataclass -from typeguard import CollectionCheckStrategy, TypeCheckError, config, typechecked - -config.collection_check_strategy = CollectionCheckStrategy.ALL_ITEMS +from beartype import beartype +from beartype.roar import BeartypeCallHintException def dataclass_with_properties(cls): @@ -22,50 +20,27 @@ def dataclass_with_properties(cls): def make_setter(field_name, field_type): """helper method to avoid late binding when generating functions in a for loop""" - @typechecked + @beartype def set_field(self, value: field_type): setattr(self, f"_{field_name}", value) - def set_field_with_better_error_message(self, value: field_type): + def set_field_with_error_conversion(self, value: field_type): try: set_field(self, value) - except TypeCheckError as err: + except BeartypeCallHintException as err: error_message: str = f"SetterError {self.__class__.__name__}: {err}" - if "did not match any element in the union" in error_message: - error_message = simplify_error_message_for_union(error_message) # As setters are created dynamically, their argument name is always "value". We replace it by the # actual name so the error message is more helpful. raise TypeError(error_message.replace("value", field_name, 1) + f": {value}") - def simplify_error_message_for_union(error_message: str) -> str: - # The error message from typeguard is more verbose than we need, so we simplify the message - # to provide the user with a more compact error message. - types_in_union = re.compile(r"\n\s*(.*?):", re.UNICODE) - list_of_types = re.findall(types_in_union, error_message) - text_to_replace = error_message.split("did not match any element in the union:")[-1] - error_message = error_message.replace(text_to_replace, " [" + ", ".join(list_of_types) + "]") - return error_message - - return set_field_with_better_error_message + return set_field_with_error_conversion def make_getter(field_name, field_type): """helper method to avoid late binding when generating functions in a for loop""" - @typechecked def get_field(self) -> field_type: return getattr(self, f"_{field_name}") - def get_field_with_better_error_message(self) -> field_type: - try: - return get_field(self) - except TypeCheckError as err: - error_message: str = f"GetterError {self.__class__.__name__}: {err}" - # As getters are created dynamically, their argument name is always "the return value". - # We replace it by the actual name so the error message is more helpful. - raise TypeError( - error_message.replace("the return value", field_name, 1) + f': {getattr(self, f"_{field_name}")}' - ) - - return get_field_with_better_error_message + return get_field From c66f6fbc79177dff047fa3536cb8e5516787ff13 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Thu, 1 Jun 2023 10:46:08 +0200 Subject: [PATCH 085/354] Fix or remove tests that became flaky thanks to beartype Signed-off-by: Holger Frydrych --- .../model/test_extracted_licensing_info.py | 2 +- tests/spdx/model/test_file.py | 2 +- .../parser/jsonlikedict/test_error_message.py | 36 ------------------- 3 files changed, 2 insertions(+), 38 deletions(-) delete mode 100644 tests/spdx/parser/jsonlikedict/test_error_message.py diff --git a/tests/spdx/model/test_extracted_licensing_info.py b/tests/spdx/model/test_extracted_licensing_info.py index 75dc79aab..203d13df3 100644 --- a/tests/spdx/model/test_extracted_licensing_info.py +++ b/tests/spdx/model/test_extracted_licensing_info.py @@ -33,7 +33,7 @@ def test_wrong_type_in_license_name(): def test_wrong_type_in_cross_references(): with pytest.raises(TypeError): - ExtractedLicensingInfo(cross_references=["ref", 42]) + ExtractedLicensingInfo(cross_references=[41, 42]) def test_wrong_type_in_comment(): diff --git a/tests/spdx/model/test_file.py b/tests/spdx/model/test_file.py index 592e8dc4f..287c16635 100644 --- a/tests/spdx/model/test_file.py +++ b/tests/spdx/model/test_file.py @@ -125,4 +125,4 @@ def test_wrong_type_in_contributors(checksum): @mock.patch("spdx_tools.spdx.model.Checksum", autospec=True) def test_wrong_type_in_attribution_texts(checksum): with pytest.raises(TypeError): - File("name", "id", [checksum], attribution_texts=["attribution", 42]) + File("name", "id", [checksum], attribution_texts=[41, 42]) diff --git a/tests/spdx/parser/jsonlikedict/test_error_message.py b/tests/spdx/parser/jsonlikedict/test_error_message.py deleted file mode 100644 index 207623ad4..000000000 --- a/tests/spdx/parser/jsonlikedict/test_error_message.py +++ /dev/null @@ -1,36 +0,0 @@ -from unittest import TestCase - -import pytest - -from spdx_tools.spdx.parser.error import SPDXParsingError -from spdx_tools.spdx.parser.jsonlikedict.package_parser import PackageParser - - -# To avoid duplication we use this invalid package as a proxy for the exact comparison of the generated error message. -# For all other classes we only check that a TypeError is raised if an incorrect type is specified. -def test_error_message(): - package_parser = PackageParser() - package = { - "SPDXID": "SPDXRef-Package", - "downloadLocation": 5, - "attributionTexts": ["text", 5, {"test": "data"}], - "packageFileName": 10, - } - - with pytest.raises(SPDXParsingError) as err: - package_parser.parse_package(package) - - TestCase().assertCountEqual( - err.value.get_messages(), - [ - 'Error while constructing Package: [\'SetterError Package: argument "name" ' - "(None) is not an instance of str: None', 'SetterError Package: argument " - '"download_location" (int) did not match any element in the union: ' - "[str, spdx_tools.spdx.model.spdx_no_assertion.SpdxNoAssertion, " - "spdx_tools.spdx.model.spdx_none.SpdxNone]: 5', 'SetterError Package: " - 'argument "file_name" (int) did not match any element in the union: ' - "[str, NoneType]: 10', 'SetterError Package: item 1 of argument " - "\"attribution_texts\" (list) is not an instance of str: [\\'text\\', 5, " - "{\\'test\\': \\'data\\'}]']" - ], - ) From 548be63b828dcad6b57f32be7e4ea4e86b502f0a Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Thu, 1 Jun 2023 10:58:08 +0200 Subject: [PATCH 086/354] Change documentation references from typeguard to beartype Signed-off-by: Holger Frydrych --- README.md | 2 +- src/spdx_tools/common/typing/type_checks.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e2a502530..c4415c675 100644 --- a/README.md +++ b/README.md @@ -170,7 +170,7 @@ if not validation_messages: * rdflib: https://pypi.python.org/pypi/rdflib/ for handling RDF. * ply: https://pypi.org/project/ply/ for handling tag-value. * click: https://pypi.org/project/click/ for creating the CLI interface. -* typeguard: https://pypi.org/project/typeguard/ for type checking. +* beartype: https://pypi.org/project/beartype/ for type checking. * uritools: https://pypi.org/project/uritools/ for validation of URIs. * license-expression: https://pypi.org/project/license-expression/ for handling SPDX license expressions. diff --git a/src/spdx_tools/common/typing/type_checks.py b/src/spdx_tools/common/typing/type_checks.py index 09e3f5d49..9de96d629 100644 --- a/src/spdx_tools/common/typing/type_checks.py +++ b/src/spdx_tools/common/typing/type_checks.py @@ -7,7 +7,7 @@ def check_types_and_set_values(instance_under_construction: Any, local_variables """ Helper method to accumulate all type errors encountered during a constructor call and return them in a ConstructorTypeErrors instance. - Background: Our setters are enhanced with runtime typechecks using typeguard. However, this means that by + Background: Our setters are enhanced with runtime typechecks using beartype. However, this means that by default, a TypeError is raised on the first type violation that is encountered. We consider it more helpful to return all type violations in one go. As an aside, defining constructors "manually" using this utility method helps avoid a nasty PyCharm bug: From 5a6d4e316f6126d4f39b22b39e68aa429cb5666a Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Thu, 1 Jun 2023 14:06:01 +0200 Subject: [PATCH 087/354] Restore license header for dataclass_with_properties Signed-off-by: Holger Frydrych --- src/spdx_tools/common/typing/dataclass_with_properties.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/spdx_tools/common/typing/dataclass_with_properties.py b/src/spdx_tools/common/typing/dataclass_with_properties.py index 6e05ca343..3f13950d5 100644 --- a/src/spdx_tools/common/typing/dataclass_with_properties.py +++ b/src/spdx_tools/common/typing/dataclass_with_properties.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2022 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 from dataclasses import dataclass from beartype import beartype From 1d4ce2d4a253a53b51650c3225a4072a2e5c8dff Mon Sep 17 00:00:00 2001 From: Gaurav Mishra Date: Mon, 5 Jun 2023 11:55:50 +0530 Subject: [PATCH 088/354] fix(example): fix errors in example file Add the files to package and update the SPDX id describing relationship between document and package. Signed-off-by: Gaurav Mishra --- examples/spdx2_document_from_scratch.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/spdx2_document_from_scratch.py b/examples/spdx2_document_from_scratch.py index 24276d307..e74ccf3a1 100644 --- a/examples/spdx2_document_from_scratch.py +++ b/examples/spdx2_document_from_scratch.py @@ -88,7 +88,7 @@ document.packages = [package] # A DESCRIBES relationship asserts that the document indeed describes the package. -describes_relationship = Relationship("SPDXRef-Document", RelationshipType.DESCRIBES, "SPDXRef-Package") +describes_relationship = Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package") document.relationships = [describes_relationship] # Let's add two files. Have a look at the file class for all possible properties a file can have. @@ -120,6 +120,7 @@ # This library uses run-time type checks when assigning properties. # Because in-place alterations like .append() circumvent these checks, we don't use them here. document.relationships += [contains_relationship1, contains_relationship2] +document.files += [file1, file2] # We now have created a document with basic creation information, describing a package that contains two files. # You can also add Annotations, Snippets and ExtractedLicensingInfo to the document in an analogous manner to the above. From 93e90565dec1c5778f32954207ee4c02b54bf24f Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 10 Jan 2023 10:26:24 +0100 Subject: [PATCH 089/354] [spdx3.0] add basic implementation for file class Signed-off-by: Meret Behrens --- pyproject.toml | 2 +- src/spdx3/README.md | 2 + src/spdx3/model/__init__.py | 1 + src/spdx3/model/core/__init__.py | 0 src/spdx3/model/core/creation_information.py | 30 ++++++++++++ src/spdx3/model/core/element.py | 49 ++++++++++++++++++++ src/spdx3/model/core/profile_identifier.py | 17 +++++++ src/spdx3/model/software/__init__.py | 0 src/spdx3/model/software/file.py | 35 ++++++++++++++ src/spdx3/model/software/software_purpose.py | 33 +++++++++++++ 10 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 src/spdx3/README.md create mode 100644 src/spdx3/model/__init__.py create mode 100644 src/spdx3/model/core/__init__.py create mode 100644 src/spdx3/model/core/creation_information.py create mode 100644 src/spdx3/model/core/element.py create mode 100644 src/spdx3/model/core/profile_identifier.py create mode 100644 src/spdx3/model/software/__init__.py create mode 100644 src/spdx3/model/software/file.py create mode 100644 src/spdx3/model/software/software_purpose.py diff --git a/pyproject.toml b/pyproject.toml index a77d1db8a..d4380535c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ classifiers = [ ] urls = { Homepage = "https://github.com/spdx/tools-python" } requires-python = ">=3.7" -dependencies = ["click", "pyyaml", "xmltodict", "rdflib", "beartype", "uritools", "license_expression", "ply"] +dependencies = ["click", "pyyaml", "xmltodict", "rdflib", "beartype", "uritools", "license_expression", "ply", "semantic_version"] dynamic = ["version"] [project.optional-dependencies] diff --git a/src/spdx3/README.md b/src/spdx3/README.md new file mode 100644 index 000000000..0f1092d57 --- /dev/null +++ b/src/spdx3/README.md @@ -0,0 +1,2 @@ +This implementation is mainly based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 2612c160d861fae53a3b44009ca0e1aa0fd6857f). + diff --git a/src/spdx3/model/__init__.py b/src/spdx3/model/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/src/spdx3/model/__init__.py @@ -0,0 +1 @@ + diff --git a/src/spdx3/model/core/__init__.py b/src/spdx3/model/core/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx3/model/core/creation_information.py b/src/spdx3/model/core/creation_information.py new file mode 100644 index 000000000..7b63bee18 --- /dev/null +++ b/src/spdx3/model/core/creation_information.py @@ -0,0 +1,30 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from datetime import datetime +from typing import List +from semantic_version import Version + +from common.typing.type_checks import check_types_and_set_values + +from common.typing.dataclass_with_properties import dataclass_with_properties + +@dataclass_with_properties +class CreationInformation: + spec_version: Version + created: datetime + created_by: None # placeholder for Actor + profile: List[str] # or create an Enum for ProfileIdentifier? + data_license: str + + def __init__(self, spec_version: Version, created: datetime, created_by, profile: List[str], data_license: str = "CC0"): + check_types_and_set_values(self,locals()) + + diff --git a/src/spdx3/model/core/element.py b/src/spdx3/model/core/element.py new file mode 100644 index 000000000..d00e09dad --- /dev/null +++ b/src/spdx3/model/core/element.py @@ -0,0 +1,49 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional + +from common.typing.dataclass_with_properties import dataclass_with_properties +from spdx3.model.core.creation_information import CreationInformation + + +@dataclass_with_properties +class Element: + spdx_id: str # IRI + creation_info: CreationInformation + name: Optional[str] = None + summary: Optional[str] = None + description: Optional[str] = None + comment: Optional[str] = None + verified_using: None = None # placeholder for IntegrityMethod + external_references: None = None # placeholder for ExternalReference + external_identifier: None = None # placeholder for ExternalIdentifier + extension: None # placeholder for extension + + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, + summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, + verified_using: None = None, external_references: None = None, external_identifier: None = None, + extension: None = None): + check_types_and_set_values(self, locals()) + + +@dataclass_with_properties +class Artifact(Element): + originated_by: None # placeholder for Actor + + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, + summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, + verified_using: None = None, external_references: None = None, external_identifier: None = None, + extension: None = None, originated_by: None = None): + Element.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension) + check_types_and_set_values(self, locals()) + + diff --git a/src/spdx3/model/core/profile_identifier.py b/src/spdx3/model/core/profile_identifier.py new file mode 100644 index 000000000..69e7c12e8 --- /dev/null +++ b/src/spdx3/model/core/profile_identifier.py @@ -0,0 +1,17 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from enum import Enum, auto + + +class ProfileIdentifier(Enum): + CORE = auto() + SOFTWARE = auto() + LICENSING = auto() diff --git a/src/spdx3/model/software/__init__.py b/src/spdx3/model/software/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py new file mode 100644 index 000000000..d5a7a618d --- /dev/null +++ b/src/spdx3/model/software/file.py @@ -0,0 +1,35 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional + +from common.typing.type_checks import check_types_and_set_values + +from spdx3.model.creation_information import CreationInformation + +from common.typing.dataclass_with_properties import dataclass_with_properties +from spdx3.model.core.element import Artifact +from spdx3.model.software.software_purpose import SoftwarePurpose + + +@dataclass_with_properties +class File(Artifact): + content_identifier: Optional[str] = None # should be a valid URI + file_purpose: Optional[SoftwarePurpose] = None + content_type: Optional[str] = None # placeholder for MediaType + + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, + summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, + verified_using: None = None, external_references: None = None, external_identifier: None = None, + extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, + file_purpose: Optional[SoftwarePurpose] = None, content_type: Optional[str] = None): + Artifact.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by) + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/software_purpose.py b/src/spdx3/model/software/software_purpose.py new file mode 100644 index 000000000..d35e12036 --- /dev/null +++ b/src/spdx3/model/software/software_purpose.py @@ -0,0 +1,33 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from enum import Enum, auto + + +class SoftwarePurpose(Enum): + APPLICATION = auto() + ARCHIVE = auto() + BOM = auto() + CONFIGURATION = auto() + CONTAINER = auto() + DATA = auto() + DEVICE = auto() + DOCUMENTATION = auto() + EXECUTABLE = auto() + FILE = auto() + FIRMWARE = auto() + FRAMEWORK = auto() + INSTALL = auto() + LIBRARY = auto() + MODULE = auto() + OPERATING_SYSTEM = auto() + OTHER= auto() + PATCH = auto() + SOURCE = auto() From e0ec1c3f710483a0080c8b84f1731cf22de9f355 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 10 Jan 2023 13:08:39 +0100 Subject: [PATCH 090/354] [spdx3.0] add package class Signed-off-by: Meret Behrens --- src/spdx3/model/software/package.py | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/spdx3/model/software/package.py diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py new file mode 100644 index 000000000..b10289aaf --- /dev/null +++ b/src/spdx3/model/software/package.py @@ -0,0 +1,38 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional + +from spdx3.model.creation_information import CreationInformation + +from common.typing.type_checks import check_types_and_set_values + +from common.typing.dataclass_with_properties import dataclass_with_properties +from spdx3.model.core.element import Artifact +from spdx3.model.software.software_purpose import SoftwarePurpose + + +@dataclass_with_properties +class Package(Artifact): + content_identifier: Optional[str] = None # anyURI + package_purpose: Optional[SoftwarePurpose] = None + download_location: Optional[str] = None # anyURI + package_uri: Optional[str] = None # anyURI + homepage: Optional[str] = None # anyURI + + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, + summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, + verified_using: None = None, external_references: None = None, external_identifier: None = None, + extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, + package_purpose: Optional[SoftwarePurpose] = None, download_location: Optional[str] = None, + package_uri: Optional[str] = None, homepage: Optional[str] = None): + Artifact.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by) + check_types_and_set_values(self, locals()) From aab35601a4d693d5533774b3bd513847bd0d37e7 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 10 Jan 2023 16:44:39 +0100 Subject: [PATCH 091/354] [spdx3.0] move core class to model level Signed-off-by: Meret Behrens --- src/spdx3/__init__.py | 1 + src/spdx3/model/{core => }/creation_information.py | 0 src/spdx3/model/{core => }/element.py | 2 +- src/spdx3/model/{core => }/profile_identifier.py | 0 src/spdx3/model/software/file.py | 2 +- src/spdx3/model/software/package.py | 2 +- {src/spdx3/model/core => tests/spdx3/model}/__init__.py | 0 7 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 src/spdx3/__init__.py rename src/spdx3/model/{core => }/creation_information.py (100%) rename src/spdx3/model/{core => }/element.py (97%) rename src/spdx3/model/{core => }/profile_identifier.py (100%) rename {src/spdx3/model/core => tests/spdx3/model}/__init__.py (100%) diff --git a/src/spdx3/__init__.py b/src/spdx3/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/src/spdx3/__init__.py @@ -0,0 +1 @@ + diff --git a/src/spdx3/model/core/creation_information.py b/src/spdx3/model/creation_information.py similarity index 100% rename from src/spdx3/model/core/creation_information.py rename to src/spdx3/model/creation_information.py diff --git a/src/spdx3/model/core/element.py b/src/spdx3/model/element.py similarity index 97% rename from src/spdx3/model/core/element.py rename to src/spdx3/model/element.py index d00e09dad..98d872756 100644 --- a/src/spdx3/model/core/element.py +++ b/src/spdx3/model/element.py @@ -11,7 +11,7 @@ from typing import Optional from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.core.creation_information import CreationInformation +from spdx3.model.creation_information import CreationInformation @dataclass_with_properties diff --git a/src/spdx3/model/core/profile_identifier.py b/src/spdx3/model/profile_identifier.py similarity index 100% rename from src/spdx3/model/core/profile_identifier.py rename to src/spdx3/model/profile_identifier.py diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index d5a7a618d..9ad87c709 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -15,7 +15,7 @@ from spdx3.model.creation_information import CreationInformation from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.core.element import Artifact +from spdx3.model.element import Artifact from spdx3.model.software.software_purpose import SoftwarePurpose diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index b10289aaf..daa9997f3 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -15,7 +15,7 @@ from common.typing.type_checks import check_types_and_set_values from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.core.element import Artifact +from spdx3.model.element import Artifact from spdx3.model.software.software_purpose import SoftwarePurpose diff --git a/src/spdx3/model/core/__init__.py b/tests/spdx3/model/__init__.py similarity index 100% rename from src/spdx3/model/core/__init__.py rename to tests/spdx3/model/__init__.py From 9ae4b6b92ac544661d17e7d63efe3b1030b52c6f Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 10 Jan 2023 13:39:52 +0100 Subject: [PATCH 092/354] [spdx3.0] add snippet class Signed-off-by: Meret Behrens --- src/spdx3/model/software/snippet.py | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/spdx3/model/software/snippet.py diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py new file mode 100644 index 000000000..ad0bad5a4 --- /dev/null +++ b/src/spdx3/model/software/snippet.py @@ -0,0 +1,37 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional, Tuple + +from common.typing.type_checks import check_types_and_set_values + +from spdx3.model.creation_information import CreationInformation + +from common.typing.dataclass_with_properties import dataclass_with_properties +from spdx3.model.software.software_purpose import SoftwarePurpose +from spdx3.model.element import Artifact + + +@dataclass_with_properties +class Snippet(Artifact): + content_identifier: Optional[str] = None # anyURI + snippet_purpose: Optional[SoftwarePurpose] = None + byte_range: Optional[Tuple[int, int]] = None + line_range: Optional[Tuple[int, int]] = None + + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, + summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, + verified_using: None = None, external_references: None = None, external_identifier: None = None, + extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, + snippet_purpose: Optional[SoftwarePurpose] = None, byte_range: Optional[Tuple[int, int]] = None, + line_range: Optional[Tuple[int, int]] = None): + Artifact.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by) + check_types_and_set_values(self, locals()) From d8663b45c51cd69671d75211d5b54fcdbee96381 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 10 Jan 2023 16:39:51 +0100 Subject: [PATCH 093/354] [spdx3.0] add Collection, Bundle, Bom, Sbom, SpdxDocument, ExternalMap, NamespaceMap Signed-off-by: Meret Behrens --- src/spdx3/model/element.py | 49 ++++++++++++++++++++++++++++++-- src/spdx3/model/external_map.py | 23 +++++++++++++++ src/spdx3/model/namespace_map.py | 21 ++++++++++++++ src/spdx3/model/software/sbom.py | 30 +++++++++++++++++++ src/spdx3/model/spdx_document.py | 32 +++++++++++++++++++++ 5 files changed, 153 insertions(+), 2 deletions(-) create mode 100644 src/spdx3/model/external_map.py create mode 100644 src/spdx3/model/namespace_map.py create mode 100644 src/spdx3/model/software/sbom.py create mode 100644 src/spdx3/model/spdx_document.py diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index 98d872756..28a5e5f72 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -8,10 +8,14 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional - +from dataclasses import field +from typing import Optional, List +from common.typing.type_checks import check_types_and_set_values from common.typing.dataclass_with_properties import dataclass_with_properties + from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_map import ExternalMap +from spdx3.model.namespace_map import NamespaceMap @dataclass_with_properties @@ -47,3 +51,44 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio check_types_and_set_values(self, locals()) +@dataclass_with_properties +class Collection(Element): + namespace: Optional[NamespaceMap] = None + import_element: Optional[List[ExternalMap]] = field(default_factory=list) + + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, + summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, + verified_using: None = None, external_references: None = None, external_identifier: None = None, + extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, + import_element: Optional[List[ExternalMap]] = None): + import_element = [] if import_element is None else import_element + Element.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension) + check_types_and_set_values(self, locals()) + + +@dataclass_with_properties +class Bundle(Collection): + context: Optional[str] = None + + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, + summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, + verified_using: None = None, external_references: None = None, external_identifier: None = None, + extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, + import_element: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + Collection.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by, namespace, + import_element) + check_types_and_set_values(self, locals()) + + +@dataclass_with_properties +class Bom(Bundle): + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, + summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, + verified_using: None = None, external_references: None = None, external_identifier: None = None, + extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, + import_element: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + Bundle.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by, namespace, + import_element, context) diff --git a/src/spdx3/model/external_map.py b/src/spdx3/model/external_map.py new file mode 100644 index 000000000..445dcd069 --- /dev/null +++ b/src/spdx3/model/external_map.py @@ -0,0 +1,23 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from common.typing.type_checks import check_types_and_set_values + +from common.typing.dataclass_with_properties import dataclass_with_properties + + +@dataclass_with_properties +class ExternalMap: + external_id: str # anyURI + verified_using: None # placeholder for IntegrityMethod + location_hint: str # anyURI + + def __init__(self, external_id: str, verified_using : None, location_hint : str): + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/namespace_map.py b/src/spdx3/model/namespace_map.py new file mode 100644 index 000000000..4875d67f9 --- /dev/null +++ b/src/spdx3/model/namespace_map.py @@ -0,0 +1,21 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from common.typing.type_checks import check_types_and_set_values + +from common.typing.dataclass_with_properties import dataclass_with_properties + +@dataclass_with_properties +class NamespaceMap: + prefix: str + namespace: str # anyURI + + def __init__(self, prefix: str, namespace: str): + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py new file mode 100644 index 000000000..6c6f3130e --- /dev/null +++ b/src/spdx3/model/software/sbom.py @@ -0,0 +1,30 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional, List + +from spdx3.model.creation_information import CreationInformation + +from common.typing.dataclass_with_properties import dataclass_with_properties +from spdx3.model.element import Bom, Bundle +from spdx3.model.external_map import ExternalMap +from spdx3.model.namespace_map import NamespaceMap + + +@dataclass_with_properties +class Sbom(Bom): + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, + summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, + verified_using: None = None, external_references: None = None, external_identifier: None = None, + extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, + import_element: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + Bundle.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by, namespace, + import_element, context) diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py new file mode 100644 index 000000000..76dac8f16 --- /dev/null +++ b/src/spdx3/model/spdx_document.py @@ -0,0 +1,32 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional, List + +from spdx3.model.creation_information import CreationInformation + +from common.typing.dataclass_with_properties import dataclass_with_properties +from spdx3.model.element import Bundle +from spdx3.model.external_map import ExternalMap +from spdx3.model.namespace_map import NamespaceMap + + +@dataclass_with_properties +class SpdxDocument(Bundle): + # inherited field name is required for a SpdxDocument, no longer optional + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, + summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, + verified_using: None = None, external_references: None = None, external_identifier: None = None, + extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, + import_element: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + Bundle.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by, namespace, + import_element, context) + From 4a5918c8d2b184231b2c87e44e8c5ca517f9ba8e Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 11 Jan 2023 15:27:19 +0100 Subject: [PATCH 094/354] [spdx3.0] add tests for data model and fix initialization for inherited classes Signed-off-by: Meret Behrens --- src/spdx3/model/element.py | 77 ++++++++++--- src/spdx3/model/spdx_document.py | 17 ++- src/spdx_tools/common/typing/type_checks.py | 8 +- tests/spdx3/model/__init__.py | 1 + tests/spdx3/model/test_element.py | 121 ++++++++++++++++++++ tests/spdx3/model/test_spdx_document.py | 42 +++++++ 6 files changed, 243 insertions(+), 23 deletions(-) create mode 100644 tests/spdx3/model/test_element.py create mode 100644 tests/spdx3/model/test_spdx_document.py diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index 28a5e5f72..de3cdca24 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -10,6 +10,8 @@ # limitations under the License. from dataclasses import field from typing import Optional, List + +from common.typing.constructor_type_errors import ConstructorTypeErrors from common.typing.type_checks import check_types_and_set_values from common.typing.dataclass_with_properties import dataclass_with_properties @@ -26,30 +28,38 @@ class Element: summary: Optional[str] = None description: Optional[str] = None comment: Optional[str] = None - verified_using: None = None # placeholder for IntegrityMethod - external_references: None = None # placeholder for ExternalReference - external_identifier: None = None # placeholder for ExternalIdentifier - extension: None # placeholder for extension + verified_using: None = None # placeholder for IntegrityMethod + external_references: None = None # placeholder for ExternalReference + external_identifier: None = None # placeholder for ExternalIdentifier + extension: None = None # placeholder for extension def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None): - check_types_and_set_values(self, locals()) + check_types_and_set_values(self, locals(), origin_class=Element) @dataclass_with_properties class Artifact(Element): - originated_by: None # placeholder for Actor + originated_by: None = None # placeholder for Actor def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None): - Element.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension) - check_types_and_set_values(self, locals()) - + errors = [] + try: + super().__init__(spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + try: + check_types_and_set_values(self, locals(), origin_class=Artifact) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + if errors: + raise ConstructorTypeErrors(errors) @dataclass_with_properties class Collection(Element): @@ -62,9 +72,18 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, import_element: Optional[List[ExternalMap]] = None): import_element = [] if import_element is None else import_element - Element.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + errors = [] + try: + Element.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, external_references, external_identifier, extension) - check_types_and_set_values(self, locals()) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + try: + check_types_and_set_values(self, locals(), origin_class=Collection) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + if errors: + raise ConstructorTypeErrors(errors) @dataclass_with_properties @@ -76,10 +95,20 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, import_element: Optional[List[ExternalMap]] = None, context: Optional[str] = None): - Collection.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by, namespace, - import_element) - check_types_and_set_values(self, locals()) + errors = [] + try: + Collection.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by, namespace, + import_element) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + + try: + check_types_and_set_values(self, locals(), origin_class=Bundle) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + if errors: + raise ConstructorTypeErrors(errors) @dataclass_with_properties @@ -89,6 +118,16 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, import_element: Optional[List[ExternalMap]] = None, context: Optional[str] = None): - Bundle.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by, namespace, - import_element, context) + errors = [] + try: + Bundle.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by, namespace, + import_element, context) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + try: + check_types_and_set_values(self, locals(), origin_class=Bom) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + if errors: + raise ConstructorTypeErrors(errors) diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index 76dac8f16..6423b48cd 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -10,6 +10,10 @@ # limitations under the License. from typing import Optional, List +from common.typing.type_checks import check_types_and_set_values + +from common.typing.constructor_type_errors import ConstructorTypeErrors + from spdx3.model.creation_information import CreationInformation from common.typing.dataclass_with_properties import dataclass_with_properties @@ -26,7 +30,16 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, import_element: Optional[List[ExternalMap]] = None, context: Optional[str] = None): - Bundle.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + errors = [] + try: + super().__init__(spdx_id, creation_info, name, summary, description, comment, verified_using, external_references, external_identifier, extension, originated_by, namespace, import_element, context) - + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + try: + check_types_and_set_values(self, locals(), origin_class=SpdxDocument) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + if errors: + raise ConstructorTypeErrors(errors) diff --git a/src/spdx_tools/common/typing/type_checks.py b/src/spdx_tools/common/typing/type_checks.py index 9de96d629..5acd836ba 100644 --- a/src/spdx_tools/common/typing/type_checks.py +++ b/src/spdx_tools/common/typing/type_checks.py @@ -3,7 +3,7 @@ from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors -def check_types_and_set_values(instance_under_construction: Any, local_variables: Dict) -> None: +def check_types_and_set_values(instance_under_construction: Any, local_variables: Dict, origin_class: Any = None) -> None: """ Helper method to accumulate all type errors encountered during a constructor call and return them in a ConstructorTypeErrors instance. @@ -12,9 +12,13 @@ def check_types_and_set_values(instance_under_construction: Any, local_variables return all type violations in one go. As an aside, defining constructors "manually" using this utility method helps avoid a nasty PyCharm bug: https://youtrack.jetbrains.com/issue/PY-34569 + With the additional parameter origin_class we ensure that the attributes from the class that calls this method + are set. If we use inheritance the instance_under_construction object might be a child object. """ + if not origin_class: + origin_class = instance_under_construction errors = [] - for key, value_type in instance_under_construction.__annotations__.items(): + for key, value_type in origin_class.__annotations__.items(): value = local_variables.get(key) try: setattr(instance_under_construction, key, value) diff --git a/tests/spdx3/model/__init__.py b/tests/spdx3/model/__init__.py index e69de29bb..8b1378917 100644 --- a/tests/spdx3/model/__init__.py +++ b/tests/spdx3/model/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/spdx3/model/test_element.py b/tests/spdx3/model/test_element.py new file mode 100644 index 000000000..fb00bd5d2 --- /dev/null +++ b/tests/spdx3/model/test_element.py @@ -0,0 +1,121 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from spdx3.model.element import Element, Artifact, Collection, Bundle, Bom + + +@mock.patch("spdx3.model.creation_information.CreationInformation") +def test_correct_initialization_element(creation_info): + element = Element("SPDXRef-Element", creation_info) + + assert element.spdx_id == "SPDXRef-Element" + assert element.creation_info == creation_info + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_invalid_initialization_element(creation_info): + with pytest.raises(TypeError) as err: + Element(54, creation_info, name=76) + + assert err.value.args[0] == ['SetterError Element: type of argument "spdx_id" must be str; got int ' + 'instead: 54', + 'SetterError Element: type of argument "name" must be one of (str, NoneType); ' + 'got int instead: 76'] + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization_artifact(creation_info): + artifact = Artifact("SPDXRef-Artifact", creation_info, originated_by=None) + + assert artifact.spdx_id == "SPDXRef-Artifact" + assert artifact.creation_info == creation_info + assert artifact.originated_by is None + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_invalid_initialization_artifact(creation_info): + with pytest.raises(TypeError) as err: + Artifact(65, creation_info, originated_by=54) + + assert err.value.args[0] == ['SetterError Artifact: type of argument "spdx_id" must be str; got int ' + 'instead: 65', + 'SetterError Artifact: type of argument "originated_by" must be NoneType; got ' + 'int instead: 54'] + + +@mock.patch("spdx3.model.external_map.ExternalMap", autospec=True) +@mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization_collection(creation_information, namespace_map, external_map): + collection = Collection("SPDXRef-Collection", creation_information, namespace=namespace_map, + import_element=[external_map]) + + assert collection.spdx_id == "SPDXRef-Collection" + assert collection.creation_info == creation_information + assert collection.namespace == namespace_map + assert collection.import_element == [external_map] + + +@mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_invalid_initialization_collection(creation_information, namespace_map): + with pytest.raises(TypeError) as err: + Collection("SPDXRef-Collection", creation_information, namespace=namespace_map, + import_element=["ExternalMap"]) + + assert err.value.args[0] == ['SetterError Collection: type of argument "import_element" must be one of ' + '(List[spdx3.model.external_map.ExternalMap], NoneType); got list instead: ' + "['ExternalMap']"] + + +@mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization_bundle(creation_information, namespace): + bundle = Bundle("SPDXRef-Bundle", creation_information, namespace=namespace, context="context") + + assert bundle.spdx_id == "SPDXRef-Bundle" + assert bundle.creation_info == creation_information + assert bundle.context == "context" + assert bundle.namespace == namespace + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_invalid_initialization_bundle(creation_information): + with pytest.raises(TypeError) as err: + Bundle(4, creation_information, namespace=True, context=["yes"]) + + assert err.value.args[0] == ['SetterError Bundle: type of argument "spdx_id" must be str; got int instead: ' + '4', + 'SetterError Bundle: type of argument "namespace" must be one of ' + '(spdx3.model.namespace_map.NamespaceMap, NoneType); got bool instead: True', + 'SetterError Bundle: type of argument "context" must be one of (str, ' + "NoneType); got list instead: ['yes']"] + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization_bom(creation_information): + bom = Bom("SPDXRef-Bom", creation_information) + + assert bom.spdx_id == "SPDXRef-Bom" + assert bom.creation_info == creation_information + + +def test_invalid_initialization_bom(): + with pytest.raises(TypeError) as err: + Bom(1, "Creation Information") + + assert err.value.args[0] == ['SetterError Bom: type of argument "spdx_id" must be str; got int instead: 1', + 'SetterError Bom: type of argument "creation_info" must be ' + 'spdx3.model.creation_information.CreationInformation; got str instead: ' + 'Creation Information'] diff --git a/tests/spdx3/model/test_spdx_document.py b/tests/spdx3/model/test_spdx_document.py new file mode 100644 index 000000000..e19c0d6b5 --- /dev/null +++ b/tests/spdx3/model/test_spdx_document.py @@ -0,0 +1,42 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from spdx3.model.spdx_document import SpdxDocument + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization(creation_information): + spdx_document = SpdxDocument("SPDXRef-DOCUMENT", creation_information, "Test document") + + assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" + assert spdx_document.creation_info == creation_information + assert spdx_document.name == "Test document" + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + SpdxDocument(1, {"info": 5}, "document name") + + assert err.value.args[0] == ['SetterError SpdxDocument: type of argument "spdx_id" must be str; got int ' + 'instead: 1', + 'SetterError SpdxDocument: type of argument "creation_info" must be ' + 'spdx3.model.creation_information.CreationInformation; got dict instead: ' + "{'info': 5}"] + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_incomplete_initialization(creation_information): + with pytest.raises(TypeError) as err: + SpdxDocument("SPDXRef-Docuement", creation_information) + + assert err.value.args[0] == "SpdxDocument.__init__() missing 1 required positional argument: 'name'" From 6438f628debc6345b89172284bd8ff2e03205393 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 11 Jan 2023 15:27:40 +0100 Subject: [PATCH 095/354] [reformat] creation_information.py Signed-off-by: Meret Behrens --- src/spdx3/model/creation_information.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/spdx3/model/creation_information.py b/src/spdx3/model/creation_information.py index 7b63bee18..9044d4b02 100644 --- a/src/spdx3/model/creation_information.py +++ b/src/spdx3/model/creation_information.py @@ -16,15 +16,15 @@ from common.typing.dataclass_with_properties import dataclass_with_properties + @dataclass_with_properties class CreationInformation: spec_version: Version created: datetime - created_by: None # placeholder for Actor - profile: List[str] # or create an Enum for ProfileIdentifier? + created_by: None # placeholder for Actor + profile: List[str] # or create an Enum for ProfileIdentifier? data_license: str - def __init__(self, spec_version: Version, created: datetime, created_by, profile: List[str], data_license: str = "CC0"): - check_types_and_set_values(self,locals()) - - + def __init__(self, spec_version: Version, created: datetime, created_by, profile: List[str], + data_license: str = "CC0"): + check_types_and_set_values(self, locals()) From ad05ba70e885a6e9cc3778b3beed39f3e1cc4f03 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 11 Jan 2023 16:09:11 +0100 Subject: [PATCH 096/354] [spdx3.0] add tests for classes in software module and fix initialization for inherited classes Signed-off-by: Meret Behrens --- src/spdx3/model/software/file.py | 22 +++++++-- src/spdx3/model/software/package.py | 25 +++++++--- src/spdx3/model/software/sbom.py | 22 +++++++-- src/spdx3/model/software/snippet.py | 24 +++++++--- tests/spdx3/model/software/__init__.py | 1 + tests/spdx3/model/software/test_file.py | 47 +++++++++++++++++++ tests/spdx3/model/software/test_package.py | 53 ++++++++++++++++++++++ tests/spdx3/model/software/test_sbom.py | 33 ++++++++++++++ tests/spdx3/model/software/test_snippet.py | 43 ++++++++++++++++++ 9 files changed, 249 insertions(+), 21 deletions(-) create mode 100644 tests/spdx3/model/software/__init__.py create mode 100644 tests/spdx3/model/software/test_file.py create mode 100644 tests/spdx3/model/software/test_package.py create mode 100644 tests/spdx3/model/software/test_sbom.py create mode 100644 tests/spdx3/model/software/test_snippet.py diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index 9ad87c709..602754c1f 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -8,8 +8,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional +from typing import Optional, List +from common.typing.constructor_type_errors import ConstructorTypeErrors from common.typing.type_checks import check_types_and_set_values from spdx3.model.creation_information import CreationInformation @@ -22,7 +23,7 @@ @dataclass_with_properties class File(Artifact): content_identifier: Optional[str] = None # should be a valid URI - file_purpose: Optional[SoftwarePurpose] = None + file_purpose: Optional[List[SoftwarePurpose]] = None content_type: Optional[str] = None # placeholder for MediaType def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, @@ -30,6 +31,17 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, file_purpose: Optional[SoftwarePurpose] = None, content_type: Optional[str] = None): - Artifact.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by) - check_types_and_set_values(self, locals()) + file_purpose = [] if file_purpose is None else file_purpose + errors = [] + try: + Artifact.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + try: + check_types_and_set_values(self, locals()) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + + if errors: + raise ConstructorTypeErrors(errors) diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index daa9997f3..15ab14ef5 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -8,7 +8,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional +from typing import Optional, List + +from common.typing.constructor_type_errors import ConstructorTypeErrors from spdx3.model.creation_information import CreationInformation @@ -22,7 +24,7 @@ @dataclass_with_properties class Package(Artifact): content_identifier: Optional[str] = None # anyURI - package_purpose: Optional[SoftwarePurpose] = None + package_purpose: Optional[List[SoftwarePurpose]] = None download_location: Optional[str] = None # anyURI package_uri: Optional[str] = None # anyURI homepage: Optional[str] = None # anyURI @@ -31,8 +33,19 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, - package_purpose: Optional[SoftwarePurpose] = None, download_location: Optional[str] = None, + package_purpose: Optional[List[SoftwarePurpose]] = None, download_location: Optional[str] = None, package_uri: Optional[str] = None, homepage: Optional[str] = None): - Artifact.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by) - check_types_and_set_values(self, locals()) + package_purpose = [] if package_purpose is None else package_purpose + errors = [] + try: + Artifact.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + try: + check_types_and_set_values(self, locals()) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + + if errors: + raise ConstructorTypeErrors(errors) diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index 6c6f3130e..f8d2ba907 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -10,10 +10,14 @@ # limitations under the License. from typing import Optional, List +from common.typing.type_checks import check_types_and_set_values + +from common.typing.constructor_type_errors import ConstructorTypeErrors + from spdx3.model.creation_information import CreationInformation from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.element import Bom, Bundle +from spdx3.model.element import Bom from spdx3.model.external_map import ExternalMap from spdx3.model.namespace_map import NamespaceMap @@ -25,6 +29,16 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, import_element: Optional[List[ExternalMap]] = None, context: Optional[str] = None): - Bundle.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by, namespace, - import_element, context) + errors = [] + try: + Bom.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by, namespace, + import_element, context) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + try: + check_types_and_set_values(self, locals()) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + if errors: + raise ConstructorTypeErrors(errors) diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index ad0bad5a4..0cc0689ca 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -8,8 +8,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, Tuple +from typing import Optional, Tuple, List +from common.typing.constructor_type_errors import ConstructorTypeErrors from common.typing.type_checks import check_types_and_set_values from spdx3.model.creation_information import CreationInformation @@ -22,7 +23,7 @@ @dataclass_with_properties class Snippet(Artifact): content_identifier: Optional[str] = None # anyURI - snippet_purpose: Optional[SoftwarePurpose] = None + snippet_purpose: Optional[List[SoftwarePurpose]] = None byte_range: Optional[Tuple[int, int]] = None line_range: Optional[Tuple[int, int]] = None @@ -30,8 +31,19 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, - snippet_purpose: Optional[SoftwarePurpose] = None, byte_range: Optional[Tuple[int, int]] = None, + snippet_purpose: Optional[List[SoftwarePurpose]] = None, byte_range: Optional[Tuple[int, int]] = None, line_range: Optional[Tuple[int, int]] = None): - Artifact.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by) - check_types_and_set_values(self, locals()) + snippet_purpose = [] if snippet_purpose is None else snippet_purpose + errors = [] + try: + Artifact.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, originated_by) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + try: + check_types_and_set_values(self, locals()) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + + if errors: + raise ConstructorTypeErrors(errors) diff --git a/tests/spdx3/model/software/__init__.py b/tests/spdx3/model/software/__init__.py new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/tests/spdx3/model/software/__init__.py @@ -0,0 +1 @@ + diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py new file mode 100644 index 000000000..35dd77aea --- /dev/null +++ b/tests/spdx3/model/software/test_file.py @@ -0,0 +1,47 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from spdx3.model.software.software_purpose import SoftwarePurpose + +from spdx3.model.software.file import File + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization_file(creation_information): + file = File("SPDXRef-File", creation_information, content_identifier="https://any.uri", + file_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE], content_type="MediaType") + + assert file.spdx_id == "SPDXRef-File" + assert file.creation_info == creation_information + assert file.content_identifier == "https://any.uri" + assert file.file_purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE] + assert file.content_type == "MediaType" + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_invalid_initialization_file(creation_information): + with pytest.raises(TypeError) as err: + File(1, creation_information, content_identifier=3, file_purpose=SoftwarePurpose.FILE, + content_type=SoftwarePurpose.ARCHIVE) + + assert err.value.args[0] == ['SetterError File: type of argument "spdx_id" must be str; got int instead: 1', + 'SetterError File: type of argument "content_identifier" must be one of (str, ' + 'NoneType); got int instead: 3', + 'SetterError File: type of argument "file_purpose" must be one of ' + '(List[spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got ' + 'spdx3.model.software.software_purpose.SoftwarePurpose instead: ' + 'SoftwarePurpose.FILE', + 'SetterError File: type of argument "content_type" must be one of (str, ' + 'NoneType); got spdx3.model.software.software_purpose.SoftwarePurpose ' + 'instead: SoftwarePurpose.ARCHIVE'] diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py new file mode 100644 index 000000000..fc9b702db --- /dev/null +++ b/tests/spdx3/model/software/test_package.py @@ -0,0 +1,53 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from spdx3.model.software.software_purpose import SoftwarePurpose + +from spdx3.model.software.package import Package + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization_package(creation_information): + package = Package("SPDXRef-Package", creation_information, content_identifier="https://any.uri", + package_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH], + download_location="https://downloadlocation", package_uri="https://package.uri", + homepage="https://homepage") + + assert package.spdx_id == "SPDXRef-Package" + assert package.creation_info == creation_information + assert package.content_identifier == "https://any.uri" + assert package.package_purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH] + assert package.download_location == "https://downloadlocation" + assert package.package_uri == "https://package.uri" + assert package.homepage == "https://homepage" + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_invalid_initialization_package(creation_information): + with pytest.raises(TypeError) as err: + Package("SPDXRef-Package", creation_information, content_identifier=3, package_purpose=SoftwarePurpose.FILE, + download_location=4, package_uri=["uris"], homepage=True) + + assert err.value.args[0] == ['SetterError Package: type of argument "content_identifier" must be one of ' + '(str, NoneType); got int instead: 3', + 'SetterError Package: type of argument "package_purpose" must be one of ' + '(List[spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got ' + 'spdx3.model.software.software_purpose.SoftwarePurpose instead: ' + 'SoftwarePurpose.FILE', + 'SetterError Package: type of argument "download_location" must be one of ' + '(str, NoneType); got int instead: 4', + 'SetterError Package: type of argument "package_uri" must be one of (str, ' + "NoneType); got list instead: ['uris']", + 'SetterError Package: type of argument "homepage" must be one of (str, ' + 'NoneType); got bool instead: True'] diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py new file mode 100644 index 000000000..992005cb8 --- /dev/null +++ b/tests/spdx3/model/software/test_sbom.py @@ -0,0 +1,33 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from spdx3.model.software.sbom import Sbom + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization_sbom(creation_information): + sbom = Sbom("SPDXRef-Sbom", creation_information) + + assert sbom.spdx_id == "SPDXRef-Sbom" + assert sbom.creation_info == creation_information + + +def test_invalid_initialization_sbom(): + with pytest.raises(TypeError) as err: + Sbom(2, {"creation_info": [3, 4, 5]}) + + assert err.value.args[0] == ['SetterError Sbom: type of argument "spdx_id" must be str; got int instead: 2', + 'SetterError Sbom: type of argument "creation_info" must be ' + 'spdx3.model.creation_information.CreationInformation; got dict instead: ' + "{'creation_info': [3, 4, 5]}"] diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py new file mode 100644 index 000000000..8b6ae3b9d --- /dev/null +++ b/tests/spdx3/model/software/test_snippet.py @@ -0,0 +1,43 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from spdx3.model.software.software_purpose import SoftwarePurpose + +from spdx3.model.software.snippet import Snippet + + +@mock.patch("spdx3.model.software.snippet.Snippet", autospec=True) +def test_correct_initialization_snippet(creation_information): + snippet = Snippet("SPDXRef-Snippet", creation_information, content_identifier="https://content.identifier", + snippet_purpose=[SoftwarePurpose.SOURCE], byte_range=(3, 4), line_range=(346, 456)) + + assert snippet.spdx_id == "SPDXRef-Snippet" + assert snippet.creation_info == creation_information + assert snippet.content_identifier == "https://content.identifier" + assert snippet.snippet_purpose == [SoftwarePurpose.SOURCE] + assert snippet.byte_range == (3, 4) + assert snippet.line_range == (346, 456) + + +@mock.patch("spdx3.model.software.snippet.Snippet", autospec=True) +def test_invalid_initialization_snippet(creation_information): + with pytest.raises(TypeError) as err: + Snippet(2, creation_information, originated_by=34, byte_range="34:45") + + assert err.value.args[0] == ['SetterError Snippet: type of argument "spdx_id" must be str; got int ' + 'instead: 2', + 'SetterError Snippet: type of argument "originated_by" must be NoneType; got ' + 'int instead: 34', + 'SetterError Snippet: type of argument "byte_range" must be one of ' + '(Tuple[int, int], NoneType); got str instead: 34:45'] From 3c63ee09494d2ced253882627005809be51f8838 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 11 Jan 2023 16:41:30 +0100 Subject: [PATCH 097/354] [spdx3.0] add tests for CreationInformation, NamespaceMap and ExternalMap Signed-off-by: Meret Behrens --- src/spdx3/model/external_map.py | 9 ++-- src/spdx3/model/namespace_map.py | 7 +-- .../spdx3/model/test_creation_information.py | 50 +++++++++++++++++++ tests/spdx3/model/test_external_map.py | 31 ++++++++++++ tests/spdx3/model/test_namespace_map.py | 30 +++++++++++ 5 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 tests/spdx3/model/test_creation_information.py create mode 100644 tests/spdx3/model/test_external_map.py create mode 100644 tests/spdx3/model/test_namespace_map.py diff --git a/src/spdx3/model/external_map.py b/src/spdx3/model/external_map.py index 445dcd069..885b46e6d 100644 --- a/src/spdx3/model/external_map.py +++ b/src/spdx3/model/external_map.py @@ -8,6 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from typing import Optional from common.typing.type_checks import check_types_and_set_values from common.typing.dataclass_with_properties import dataclass_with_properties @@ -15,9 +16,9 @@ @dataclass_with_properties class ExternalMap: - external_id: str # anyURI - verified_using: None # placeholder for IntegrityMethod - location_hint: str # anyURI + external_id: str # anyURI + verified_using: None # placeholder for IntegrityMethod + location_hint: Optional[str] = None # anyURI - def __init__(self, external_id: str, verified_using : None, location_hint : str): + def __init__(self, external_id: str, verified_using: None, location_hint: Optional[str] = None): check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/namespace_map.py b/src/spdx3/model/namespace_map.py index 4875d67f9..eb06f28a6 100644 --- a/src/spdx3/model/namespace_map.py +++ b/src/spdx3/model/namespace_map.py @@ -8,14 +8,15 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from typing import Optional from common.typing.type_checks import check_types_and_set_values from common.typing.dataclass_with_properties import dataclass_with_properties @dataclass_with_properties class NamespaceMap: - prefix: str - namespace: str # anyURI + prefix: Optional[str] = None + namespace: Optional[str] = None # anyURI - def __init__(self, prefix: str, namespace: str): + def __init__(self, prefix: Optional[str] = None, namespace: Optional[str] = None): check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py new file mode 100644 index 000000000..d1bc6db53 --- /dev/null +++ b/tests/spdx3/model/test_creation_information.py @@ -0,0 +1,50 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from datetime import datetime +from unittest import mock + +import pytest + +from spdx3.model.creation_information import CreationInformation + + +@mock.patch("semantic_version.Version", autospec=True) +def test_correct_initialization(version): + creation_information = CreationInformation(version, datetime(2023, 1, 11, 16, 21), None, ["core", "software"], + "CC0") + + assert creation_information.spec_version == version + assert creation_information.created == datetime(2023, 1, 11, 16, 21) + assert creation_information.created_by is None + assert creation_information.profile == ["core", "software"] + assert creation_information.data_license == "CC0" + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + CreationInformation("2.3", "2012-01-01", None, "core", 3) + + assert err.value.args[0] == ['SetterError CreationInformation: type of argument "spec_version" must be ' + 'semantic_version.base.Version; got str instead: 2.3', + 'SetterError CreationInformation: type of argument "created" must be ' + 'datetime.datetime; got str instead: 2012-01-01', + 'SetterError CreationInformation: type of argument "profile" must be a list; ' + 'got str instead: core', + 'SetterError CreationInformation: type of argument "data_license" must be ' + 'str; got int instead: 3'] + + +def test_incomplete_initialization(): + with pytest.raises(TypeError) as err: + CreationInformation("2.3") + + assert err.value.args[0] == ('CreationInformation.__init__() missing 3 required positional arguments: ' + "'created', 'created_by', and 'profile'") diff --git a/tests/spdx3/model/test_external_map.py b/tests/spdx3/model/test_external_map.py new file mode 100644 index 000000000..95257de0e --- /dev/null +++ b/tests/spdx3/model/test_external_map.py @@ -0,0 +1,31 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import pytest + +from spdx3.model.external_map import ExternalMap + + +def test_correct_initialization(): + external_map = ExternalMap("https://external.id", None, "https://location.hint") + + assert external_map.external_id == "https://external.id" + assert external_map.verified_using is None + assert external_map.location_hint == "https://location.hint" + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + ExternalMap(234, None, ["location hints"]) + + assert err.value.args[0] == ['SetterError ExternalMap: type of argument "external_id" must be str; got int ' + 'instead: 234', + 'SetterError ExternalMap: type of argument "location_hint" must be one of ' + "(str, NoneType); got list instead: ['location hints']"] diff --git a/tests/spdx3/model/test_namespace_map.py b/tests/spdx3/model/test_namespace_map.py new file mode 100644 index 000000000..e856be009 --- /dev/null +++ b/tests/spdx3/model/test_namespace_map.py @@ -0,0 +1,30 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import pytest + +from spdx3.model.namespace_map import NamespaceMap + + +def test_correct_initialization(): + namespace_map = NamespaceMap("some prefix", "https://namespace") + + assert namespace_map.prefix == "some prefix" + assert namespace_map.namespace == "https://namespace" + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + NamespaceMap(34, ["list of namespaces"]) + + assert err.value.args[0] == ['SetterError NamespaceMap: type of argument "prefix" must be one of (str, ' + 'NoneType); got int instead: 34', + 'SetterError NamespaceMap: type of argument "namespace" must be one of (str, ' + "NoneType); got list instead: ['list of namespaces']"] From 45f1fa4387fd3ad183ad22041419460ebe491149 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 12 Jan 2023 11:55:24 +0100 Subject: [PATCH 098/354] [spdx3.0] rename spdx.element.Collection.import_element to imports Signed-off-by: Meret Behrens --- src/spdx3/model/element.py | 14 +++++++------- src/spdx3/model/software/sbom.py | 4 ++-- src/spdx3/model/spdx_document.py | 4 ++-- tests/spdx3/model/test_element.py | 8 ++++---- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index de3cdca24..005f109b2 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -64,14 +64,14 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio @dataclass_with_properties class Collection(Element): namespace: Optional[NamespaceMap] = None - import_element: Optional[List[ExternalMap]] = field(default_factory=list) + imports: Optional[List[ExternalMap]] = field(default_factory=list) def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, - import_element: Optional[List[ExternalMap]] = None): - import_element = [] if import_element is None else import_element + imports: Optional[List[ExternalMap]] = None): + imports = [] if imports is None else imports errors = [] try: Element.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, @@ -94,12 +94,12 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, - import_element: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): errors = [] try: Collection.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, external_references, external_identifier, extension, originated_by, namespace, - import_element) + imports) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) @@ -117,12 +117,12 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, - import_element: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): errors = [] try: Bundle.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, external_references, external_identifier, extension, originated_by, namespace, - import_element, context) + imports, context) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) try: diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index f8d2ba907..e021b6981 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -28,12 +28,12 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, - import_element: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): errors = [] try: Bom.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, external_references, external_identifier, extension, originated_by, namespace, - import_element, context) + imports, context) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) try: diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index 6423b48cd..21450ba0f 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -29,12 +29,12 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, - import_element: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): errors = [] try: super().__init__(spdx_id, creation_info, name, summary, description, comment, verified_using, external_references, external_identifier, extension, originated_by, namespace, - import_element, context) + imports, context) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) try: diff --git a/tests/spdx3/model/test_element.py b/tests/spdx3/model/test_element.py index fb00bd5d2..1cdcb3711 100644 --- a/tests/spdx3/model/test_element.py +++ b/tests/spdx3/model/test_element.py @@ -59,12 +59,12 @@ def test_invalid_initialization_artifact(creation_info): @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization_collection(creation_information, namespace_map, external_map): collection = Collection("SPDXRef-Collection", creation_information, namespace=namespace_map, - import_element=[external_map]) + imports=[external_map]) assert collection.spdx_id == "SPDXRef-Collection" assert collection.creation_info == creation_information assert collection.namespace == namespace_map - assert collection.import_element == [external_map] + assert collection.imports == [external_map] @mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) @@ -72,9 +72,9 @@ def test_correct_initialization_collection(creation_information, namespace_map, def test_invalid_initialization_collection(creation_information, namespace_map): with pytest.raises(TypeError) as err: Collection("SPDXRef-Collection", creation_information, namespace=namespace_map, - import_element=["ExternalMap"]) + imports=["ExternalMap"]) - assert err.value.args[0] == ['SetterError Collection: type of argument "import_element" must be one of ' + assert err.value.args[0] == ['SetterError Collection: type of argument "imports" must be one of ' '(List[spdx3.model.external_map.ExternalMap], NoneType); got list instead: ' "['ExternalMap']"] From f3ceec64e47deff0e03409f7518c5d05620b9aa9 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 12 Jan 2023 15:09:07 +0100 Subject: [PATCH 099/354] [spdx3.0] fix: add elements and root_elements to Collection and change name according to md-file Signed-off-by: Meret Behrens --- src/spdx3/model/element.py | 41 +++++++++++++--------- src/spdx3/model/software/sbom.py | 11 +++--- src/spdx3/model/spdx_document.py | 16 ++++----- tests/spdx3/model/test_element.py | 46 +++++++++++++++---------- tests/spdx3/model/test_spdx_document.py | 18 +++++++--- 5 files changed, 81 insertions(+), 51 deletions(-) diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index 005f109b2..0276d0f5c 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -61,25 +61,31 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio if errors: raise ConstructorTypeErrors(errors) + @dataclass_with_properties -class Collection(Element): - namespace: Optional[NamespaceMap] = None +class SpdxCollection(Element): + elements: List[Element] = field(default_factory=list) + root_elements: List[Element] = field(default_factory=list) + namespaces: Optional[List[NamespaceMap]] = field(default_factory=list) imports: Optional[List[ExternalMap]] = field(default_factory=list) def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, - imports: Optional[List[ExternalMap]] = None): + extension: None = None, elements: List[Element] = None, root_elements: List[Element] = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None): + elements = [] if elements is None else elements + root_elements = [] if root_elements is None else root_elements + namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports errors = [] try: - Element.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension) + super().__init__(spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) try: - check_types_and_set_values(self, locals(), origin_class=Collection) + check_types_and_set_values(self, locals(), origin_class=SpdxCollection) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) if errors: @@ -87,19 +93,21 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio @dataclass_with_properties -class Bundle(Collection): +class Bundle(SpdxCollection): context: Optional[str] = None def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, - imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + extension: None = None, elements: List[Element] = None, root_elements: List[Element] = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, + context: Optional[str] = None): errors = [] try: - Collection.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by, namespace, - imports) + SpdxCollection.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, elements, root_elements, + namespaces, + imports) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) @@ -116,12 +124,13 @@ class Bom(Bundle): def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, - imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + extension: None = None, elements: List[Element] = None, root_elements: List[Element] = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, + context: Optional[str] = None): errors = [] try: Bundle.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by, namespace, + external_references, external_identifier, extension, elements, root_elements, namespaces, imports, context) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index e021b6981..8196030b4 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -17,7 +17,7 @@ from spdx3.model.creation_information import CreationInformation from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.element import Bom +from spdx3.model.element import Bom, Element from spdx3.model.external_map import ExternalMap from spdx3.model.namespace_map import NamespaceMap @@ -27,13 +27,14 @@ class Sbom(Bom): def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, - imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + extension: None = None, elements: List[Element] = None, root_elements: List[Element] = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, + context: Optional[str] = None): errors = [] try: Bom.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by, namespace, - imports, context) + external_references, external_identifier, extension, elements, root_elements, namespaces, + imports, context) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) try: diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index 21450ba0f..8c3800bd0 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -17,7 +17,7 @@ from spdx3.model.creation_information import CreationInformation from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.element import Bundle +from spdx3.model.element import Bundle, Element from spdx3.model.external_map import ExternalMap from spdx3.model.namespace_map import NamespaceMap @@ -25,16 +25,16 @@ @dataclass_with_properties class SpdxDocument(Bundle): # inherited field name is required for a SpdxDocument, no longer optional - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, originated_by: None = None, namespace: Optional[NamespaceMap] = None, + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, elements: List[Element], + root_elements: List[Element], summary: Optional[str] = None, description: Optional[str] = None, + comment: Optional[str] = None, verified_using: None = None, external_references: None = None, + external_identifier: None = None, extension: None = None, namespace: Optional[NamespaceMap] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): errors = [] try: - super().__init__(spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by, namespace, - imports, context) + super().__init__(spdx_id, creation_info, elements, root_elements, name, summary, description, comment, + verified_using, external_references, external_identifier, extension, namespace, imports, + context) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) try: diff --git a/tests/spdx3/model/test_element.py b/tests/spdx3/model/test_element.py index 1cdcb3711..62360744a 100644 --- a/tests/spdx3/model/test_element.py +++ b/tests/spdx3/model/test_element.py @@ -12,7 +12,7 @@ import pytest -from spdx3.model.element import Element, Artifact, Collection, Bundle, Bom +from spdx3.model.element import Element, Artifact, SpdxCollection, Bundle, Bom @mock.patch("spdx3.model.creation_information.CreationInformation") @@ -57,24 +57,34 @@ def test_invalid_initialization_artifact(creation_info): @mock.patch("spdx3.model.external_map.ExternalMap", autospec=True) @mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_collection(creation_information, namespace_map, external_map): - collection = Collection("SPDXRef-Collection", creation_information, namespace=namespace_map, - imports=[external_map]) +def test_correct_initialization_spdx_collection(creation_information, namespace_map, external_map): + element = Element("SPDXRef-Element", + creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class + spdx_collection = SpdxCollection("SPDXRef-Collection", creation_information, elements=[element], + root_elements=[element], + namespaces=[namespace_map], imports=[external_map]) - assert collection.spdx_id == "SPDXRef-Collection" - assert collection.creation_info == creation_information - assert collection.namespace == namespace_map - assert collection.imports == [external_map] + assert spdx_collection.spdx_id == "SPDXRef-Collection" + assert spdx_collection.creation_info == creation_information + assert spdx_collection.elements == [element] + assert spdx_collection.root_elements == [element] + assert spdx_collection.namespaces == [namespace_map] + assert spdx_collection.imports == [external_map] @mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization_collection(creation_information, namespace_map): +def test_invalid_initialization_spdx_collection(creation_information, namespace_map): with pytest.raises(TypeError) as err: - Collection("SPDXRef-Collection", creation_information, namespace=namespace_map, - imports=["ExternalMap"]) - - assert err.value.args[0] == ['SetterError Collection: type of argument "imports" must be one of ' + SpdxCollection("SPDXRef-Collection", creation_information, elements=[None], root_elements=3, + namespaces=namespace_map, + imports=["ExternalMap"]) + + assert err.value.args[0] == ['SetterError SpdxCollection: type of argument "elements"[0] must be ' + 'spdx3.model.element.Element; got NoneType instead: [None]', + 'SetterError SpdxCollection: type of argument "root_elements" must be a list; ' + 'got int instead: 3', + 'SetterError SpdxCollection: type of argument "imports" must be one of ' '(List[spdx3.model.external_map.ExternalMap], NoneType); got list instead: ' "['ExternalMap']"] @@ -82,23 +92,23 @@ def test_invalid_initialization_collection(creation_information, namespace_map): @mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization_bundle(creation_information, namespace): - bundle = Bundle("SPDXRef-Bundle", creation_information, namespace=namespace, context="context") + bundle = Bundle("SPDXRef-Bundle", creation_information, namespaces=[namespace], context="context") assert bundle.spdx_id == "SPDXRef-Bundle" assert bundle.creation_info == creation_information assert bundle.context == "context" - assert bundle.namespace == namespace + assert bundle.namespaces == [namespace] @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_invalid_initialization_bundle(creation_information): with pytest.raises(TypeError) as err: - Bundle(4, creation_information, namespace=True, context=["yes"]) + Bundle(4, creation_information, namespaces=True, context=["yes"]) assert err.value.args[0] == ['SetterError Bundle: type of argument "spdx_id" must be str; got int instead: ' '4', - 'SetterError Bundle: type of argument "namespace" must be one of ' - '(spdx3.model.namespace_map.NamespaceMap, NoneType); got bool instead: True', + 'SetterError Bundle: type of argument "namespaces" must be one of ' + '(List[spdx3.model.namespace_map.NamespaceMap], NoneType); got bool instead: True', 'SetterError Bundle: type of argument "context" must be one of (str, ' "NoneType); got list instead: ['yes']"] diff --git a/tests/spdx3/model/test_spdx_document.py b/tests/spdx3/model/test_spdx_document.py index e19c0d6b5..cba442911 100644 --- a/tests/spdx3/model/test_spdx_document.py +++ b/tests/spdx3/model/test_spdx_document.py @@ -11,32 +11,42 @@ from unittest import mock import pytest +from spdx3.model.element import Element from spdx3.model.spdx_document import SpdxDocument @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): - spdx_document = SpdxDocument("SPDXRef-DOCUMENT", creation_information, "Test document") + element = Element("SPDXRef-Element", + creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class + spdx_document = SpdxDocument("SPDXRef-DOCUMENT", creation_information, "Test document", elements=[element], + root_elements=[element]) assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" assert spdx_document.creation_info == creation_information assert spdx_document.name == "Test document" + assert spdx_document.elements == [element] + assert spdx_document.root_elements == [element] def test_invalid_initialization(): with pytest.raises(TypeError) as err: - SpdxDocument(1, {"info": 5}, "document name") + SpdxDocument(1, {"info": 5}, "document name", elements=[8], root_elements=[]) assert err.value.args[0] == ['SetterError SpdxDocument: type of argument "spdx_id" must be str; got int ' 'instead: 1', 'SetterError SpdxDocument: type of argument "creation_info" must be ' 'spdx3.model.creation_information.CreationInformation; got dict instead: ' - "{'info': 5}"] + "{'info': 5}", + 'SetterError SpdxDocument: type of argument "elements"[0] must be ' + 'spdx3.model.element.Element; got int instead: [8]'] + @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_incomplete_initialization(creation_information): with pytest.raises(TypeError) as err: SpdxDocument("SPDXRef-Docuement", creation_information) - assert err.value.args[0] == "SpdxDocument.__init__() missing 1 required positional argument: 'name'" + assert err.value.args[ + 0] == "SpdxDocument.__init__() missing 3 required positional arguments: 'name', 'elements', and 'root_elements'" From 9fd2afffedd650531f73782e635dc475b0a4e8a8 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 17 Jan 2023 14:31:17 +0100 Subject: [PATCH 100/354] [spdx3.0] make elements and root_elements required for collections and all inherited classes Signed-off-by: Meret Behrens --- src/spdx3/model/element.py | 39 ++++++++++++------------- src/spdx3/model/software/sbom.py | 14 ++++----- tests/spdx3/model/software/test_sbom.py | 11 +++++-- tests/spdx3/model/test_element.py | 26 ++++++++++++----- 4 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index 0276d0f5c..4bf7f4e45 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -64,18 +64,17 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio @dataclass_with_properties class SpdxCollection(Element): + # due to the inheritance we need to make all fields non-default in the __annotation__, the __init__ method still raises an error if required fields are not set elements: List[Element] = field(default_factory=list) root_elements: List[Element] = field(default_factory=list) namespaces: Optional[List[NamespaceMap]] = field(default_factory=list) imports: Optional[List[ExternalMap]] = field(default_factory=list) - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, elements: List[Element] = None, root_elements: List[Element] = None, + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], + root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, + external_references: None = None, external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None): - elements = [] if elements is None else elements - root_elements = [] if root_elements is None else root_elements namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports errors = [] @@ -96,17 +95,15 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio class Bundle(SpdxCollection): context: Optional[str] = None - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, elements: List[Element] = None, root_elements: List[Element] = None, - namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, - context: Optional[str] = None): + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], + root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, + external_references: None = None, external_identifier: None = None, extension: None = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): errors = [] try: - SpdxCollection.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, elements, root_elements, - namespaces, + SpdxCollection.__init__(self, spdx_id, creation_info, elements, root_elements, name, summary, description, + comment, verified_using, external_references, external_identifier, extension, namespaces, imports) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) @@ -121,16 +118,16 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio @dataclass_with_properties class Bom(Bundle): - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, elements: List[Element] = None, root_elements: List[Element] = None, + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], + root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, + external_references: None = None, external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): errors = [] try: - Bundle.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, elements, root_elements, namespaces, + Bundle.__init__(self, spdx_id, creation_info, elements, root_elements, name, summary, description, comment, verified_using, + external_references, external_identifier, extension, namespaces, imports, context) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index 8196030b4..b303da671 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -24,17 +24,17 @@ @dataclass_with_properties class Sbom(Bom): - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, elements: List[Element] = None, root_elements: List[Element] = None, + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], + root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, + external_references: None = None, external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): errors = [] try: - Bom.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, elements, root_elements, namespaces, - imports, context) + Bom.__init__(self, spdx_id, creation_info, elements, root_elements, name, summary, description, comment, + verified_using, external_references, external_identifier, extension, namespaces, imports, + context) except ConstructorTypeErrors as err: errors.extend(err.get_messages()) try: diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index 992005cb8..c10cec91f 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -11,21 +11,26 @@ from unittest import mock import pytest +from spdx3.model.element import Element from spdx3.model.software.sbom import Sbom @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization_sbom(creation_information): - sbom = Sbom("SPDXRef-Sbom", creation_information) + element = Element("SPDXRef-Element", + creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class + + sbom = Sbom("SPDXRef-Sbom", creation_information, elements=[element, element], root_elements=[element]) assert sbom.spdx_id == "SPDXRef-Sbom" assert sbom.creation_info == creation_information - + assert sbom.elements == [element, element] + assert sbom.root_elements == [element] def test_invalid_initialization_sbom(): with pytest.raises(TypeError) as err: - Sbom(2, {"creation_info": [3, 4, 5]}) + Sbom(2, {"creation_info": [3, 4, 5]}, elements=[], root_elements=[]) assert err.value.args[0] == ['SetterError Sbom: type of argument "spdx_id" must be str; got int instead: 2', 'SetterError Sbom: type of argument "creation_info" must be ' diff --git a/tests/spdx3/model/test_element.py b/tests/spdx3/model/test_element.py index 62360744a..49d01c15a 100644 --- a/tests/spdx3/model/test_element.py +++ b/tests/spdx3/model/test_element.py @@ -61,8 +61,7 @@ def test_correct_initialization_spdx_collection(creation_information, namespace_ element = Element("SPDXRef-Element", creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class spdx_collection = SpdxCollection("SPDXRef-Collection", creation_information, elements=[element], - root_elements=[element], - namespaces=[namespace_map], imports=[external_map]) + root_elements=[element], namespaces=[namespace_map], imports=[external_map]) assert spdx_collection.spdx_id == "SPDXRef-Collection" assert spdx_collection.creation_info == creation_information @@ -92,18 +91,25 @@ def test_invalid_initialization_spdx_collection(creation_information, namespace_ @mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization_bundle(creation_information, namespace): - bundle = Bundle("SPDXRef-Bundle", creation_information, namespaces=[namespace], context="context") + element = Element("SPDXRef-Element", + creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class + bundle = Bundle("SPDXRef-Bundle", creation_information, elements=[element], root_elements=[element], + namespaces=[namespace], context="context") assert bundle.spdx_id == "SPDXRef-Bundle" assert bundle.creation_info == creation_information + assert bundle.elements == [element] + assert bundle.root_elements == [element] assert bundle.context == "context" assert bundle.namespaces == [namespace] @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_invalid_initialization_bundle(creation_information): + element = Element("SPDXRef-Element", + creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class with pytest.raises(TypeError) as err: - Bundle(4, creation_information, namespaces=True, context=["yes"]) + Bundle(4, creation_information, elements=[element], root_elements=[element], namespaces=True, context=["yes"]) assert err.value.args[0] == ['SetterError Bundle: type of argument "spdx_id" must be str; got int instead: ' '4', @@ -115,17 +121,23 @@ def test_invalid_initialization_bundle(creation_information): @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization_bom(creation_information): - bom = Bom("SPDXRef-Bom", creation_information) + element = Element("SPDXRef-Element", + creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class + bom = Bom("SPDXRef-Bom", creation_information, elements=[element], root_elements=[element]) assert bom.spdx_id == "SPDXRef-Bom" assert bom.creation_info == creation_information + assert bom.elements == [element] + assert bom.root_elements == [element] def test_invalid_initialization_bom(): with pytest.raises(TypeError) as err: - Bom(1, "Creation Information") + Bom(1, "Creation Information", elements=[5], root_elements=[]) assert err.value.args[0] == ['SetterError Bom: type of argument "spdx_id" must be str; got int instead: 1', 'SetterError Bom: type of argument "creation_info" must be ' 'spdx3.model.creation_information.CreationInformation; got str instead: ' - 'Creation Information'] + 'Creation Information', + 'SetterError Bom: type of argument "elements"[0] must be ' + 'spdx3.model.element.Element; got int instead: [5]'] From be1f1f6a767849bd41245b535a30eaa011c9f117 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 13 Jan 2023 12:31:09 +0100 Subject: [PATCH 101/354] [spdx3.0] add relationship Signed-off-by: Meret Behrens --- src/spdx3/model/relationship.py | 97 ++++++++++++++++++++++++++ tests/spdx3/model/test_relationship.py | 49 +++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 src/spdx3/model/relationship.py create mode 100644 tests/spdx3/model/test_relationship.py diff --git a/src/spdx3/model/relationship.py b/src/spdx3/model/relationship.py new file mode 100644 index 000000000..9c8e3d439 --- /dev/null +++ b/src/spdx3/model/relationship.py @@ -0,0 +1,97 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from enum import Enum, auto +from typing import List, Optional + +from common.typing.type_checks import check_types_and_set_values +from common.typing.constructor_type_errors import ConstructorTypeErrors + +from spdx3.model.creation_information import CreationInformation + +from spdx3.model.element import Element + +from common.typing.dataclass_with_properties import dataclass_with_properties + + +class RelationshipType(Enum): + AMENDS = auto() + ANCESTOR = auto() + BUILD_DEPENDENCY = auto() + BUILD_TOOL = auto() + CONTAINS = auto() + COPY = auto() + DATA_FILE = auto() + DEPENDENCY_MANIFEST = auto() + DEPENDS_ON = auto() + DESCENDANT = auto() + DESCRIBES = auto() + DEV_DEPENDENCY = auto() + DEV_TOOL = auto() + DISTRIBUTION_ARTIFACT = auto() + DOCUMENTATION = auto() + DYNAMIC_LINK = auto() + EXAMPLE = auto() + EXPANDED_FROM_ARCHIVE = auto() + FILE_ADDED = auto() + FILE_DELETED = auto() + FILE_MODIFIED = auto() + GENERATES = auto() + METAFILE = auto() + OPTIONAL_COMPONENT = auto() + OPTIONAL_DEPENDENCY = auto() + OTHER = auto() + PACKAGES = auto() + PATCH = auto() + PREREQUISITE = auto() + PROVIDED_DEPENDENCY = auto() + REQUIREMENT_FOR = auto() + RUNTIME_DEPENDENCY = auto() + SPECIFICATION_FOR = auto() + STATIC_LINK = auto() + SUPPLIED_BY = auto() + TEST = auto() + TEST_CASE = auto() + TEST_DEPENDENCY = auto() + TEST_TOOL = auto() + VARIANT = auto() + + +class RelationshipCompleteness(Enum): + INCOMPLETE = auto() + KNOWN = auto() + UNKNOWN = auto() + + +@dataclass_with_properties +class Relationship(Element): + # due to the inheritance we need to make all fields non-default in the __annotation__, the __init__ method still raises an error if required fields are not set + from_element: Element = None + to: List[Element] = None + relationship_type: RelationshipType = None + completeness: Optional[RelationshipCompleteness] = None + + def __init__(self, spdx_id: str, creation_info: CreationInformation, from_element: Element, to: List[Element], + relationship_type: RelationshipType, name: Optional[str] = None, + summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, + verified_using: None = None, external_references: None = None, external_identifier: None = None, + extension: None = None, completeness: Optional[RelationshipCompleteness] = None): + errors = [] + try: + super().__init__(spdx_id, creation_info, name, summary, description, comment, verified_using, + external_references, external_identifier, extension) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + try: + check_types_and_set_values(self, locals()) + except ConstructorTypeErrors as err: + errors.extend(err.get_messages()) + if errors: + raise ConstructorTypeErrors(errors) diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py new file mode 100644 index 000000000..f501d9349 --- /dev/null +++ b/tests/spdx3/model/test_relationship.py @@ -0,0 +1,49 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from spdx3.model.element import Element + +from spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness + + +@mock.patch("spdx3.model.creation_information.CreationInformation") +def test_correct_initialization(creation_information): + element = Element("SPDXRef-Element", + creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class + + relationship = Relationship("SPDXRef-Relationship", creation_information, element, [element, element], + RelationshipType.DESCRIBES, completeness=RelationshipCompleteness.UNKNOWN) + + assert relationship.spdx_id == "SPDXRef-Relationship" + assert relationship.creation_info == creation_information + assert relationship.from_element == element + assert relationship.to == [element, element] + assert relationship.relationship_type == RelationshipType.DESCRIBES + assert relationship.completeness == RelationshipCompleteness.UNKNOWN + + +@mock.patch("spdx3.model.creation_information.CreationInformation") +def test_invalid_initialization(creation_information): + with pytest.raises(TypeError) as err: + Relationship("SPDXRef-Relationship", creation_information, "Element", 5, "Relationshiptype", completeness=True) + + assert err.value.args[0] == ['SetterError Relationship: type of argument "from_element" must be ' + 'spdx3.model.element.Element; got str instead: Element', + 'SetterError Relationship: type of argument "to" must be a list; got int ' + 'instead: 5', + 'SetterError Relationship: type of argument "relationship_type" must be ' + 'spdx3.model.relationship.RelationshipType; got str instead: Relationshiptype', + 'SetterError Relationship: type of argument "completeness" must be one of ' + '(spdx3.model.relationship.RelationshipCompleteness, NoneType); got bool ' + 'instead: True'] From 2b62b4b0b4d36806ddc3a15538dcb6483ba00e73 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 16 Jan 2023 14:05:40 +0100 Subject: [PATCH 102/354] [spdx3.0] use __dataclass_fields__ to also set inherited fields in check_types_and_set_values Signed-off-by: Meret Behrens --- src/spdx3/model/element.py | 77 ++++++--------------- src/spdx3/model/relationship.py | 16 +---- src/spdx3/model/software/file.py | 17 +---- src/spdx3/model/software/package.py | 18 +---- src/spdx3/model/software/sbom.py | 18 +---- src/spdx3/model/software/snippet.py | 17 +---- src/spdx3/model/spdx_document.py | 21 ++---- src/spdx_tools/common/typing/type_checks.py | 6 +- 8 files changed, 38 insertions(+), 152 deletions(-) diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index 4bf7f4e45..0754d7ef7 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -11,7 +11,6 @@ from dataclasses import field from typing import Optional, List -from common.typing.constructor_type_errors import ConstructorTypeErrors from common.typing.type_checks import check_types_and_set_values from common.typing.dataclass_with_properties import dataclass_with_properties @@ -22,6 +21,8 @@ @dataclass_with_properties class Element: + # This should be an abstract class and should not be instantiated directly. + # We need to investigate if we can combine dataclasses with abstract base classes (https://github.com/spdx/tools-python/issues/431) spdx_id: str # IRI creation_info: CreationInformation name: Optional[str] = None @@ -37,29 +38,21 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None): - check_types_and_set_values(self, locals(), origin_class=Element) + check_types_and_set_values(self, locals()) @dataclass_with_properties class Artifact(Element): originated_by: None = None # placeholder for Actor - + """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent + class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super + class but as we have taken care of all fields this warning can be ignored.""" def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None): - errors = [] - try: - super().__init__(spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - try: - check_types_and_set_values(self, locals(), origin_class=Artifact) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - if errors: - raise ConstructorTypeErrors(errors) + check_types_and_set_values(self, locals()) + @dataclass_with_properties @@ -69,7 +62,9 @@ class SpdxCollection(Element): root_elements: List[Element] = field(default_factory=list) namespaces: Optional[List[NamespaceMap]] = field(default_factory=list) imports: Optional[List[ExternalMap]] = field(default_factory=list) - + """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent + class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super + class but as we have taken care of all fields this warning can be ignored.""" def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, @@ -77,63 +72,31 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: L namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None): namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports - errors = [] - try: - super().__init__(spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - try: - check_types_and_set_values(self, locals(), origin_class=SpdxCollection) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - if errors: - raise ConstructorTypeErrors(errors) - + check_types_and_set_values(self, locals()) @dataclass_with_properties class Bundle(SpdxCollection): context: Optional[str] = None - + """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent + class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super + class but as we have taken care of all fields this warning can be ignored.""" def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): - errors = [] - try: - SpdxCollection.__init__(self, spdx_id, creation_info, elements, root_elements, name, summary, description, - comment, verified_using, external_references, external_identifier, extension, namespaces, - imports) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - - try: - check_types_and_set_values(self, locals(), origin_class=Bundle) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - if errors: - raise ConstructorTypeErrors(errors) + check_types_and_set_values(self, locals()) @dataclass_with_properties class Bom(Bundle): + """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent + class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super + class but as we have taken care of all fields this warning can be ignored.""" def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): - errors = [] - try: - Bundle.__init__(self, spdx_id, creation_info, elements, root_elements, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, namespaces, - imports, context) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - try: - check_types_and_set_values(self, locals(), origin_class=Bom) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - if errors: - raise ConstructorTypeErrors(errors) + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/relationship.py b/src/spdx3/model/relationship.py index 9c8e3d439..f46b73568 100644 --- a/src/spdx3/model/relationship.py +++ b/src/spdx3/model/relationship.py @@ -12,7 +12,6 @@ from typing import List, Optional from common.typing.type_checks import check_types_and_set_values -from common.typing.constructor_type_errors import ConstructorTypeErrors from spdx3.model.creation_information import CreationInformation @@ -77,21 +76,10 @@ class Relationship(Element): to: List[Element] = None relationship_type: RelationshipType = None completeness: Optional[RelationshipCompleteness] = None - + # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, from_element: Element, to: List[Element], relationship_type: RelationshipType, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, completeness: Optional[RelationshipCompleteness] = None): - errors = [] - try: - super().__init__(spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - try: - check_types_and_set_values(self, locals()) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - if errors: - raise ConstructorTypeErrors(errors) + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index 602754c1f..8612412ba 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -10,7 +10,6 @@ # limitations under the License. from typing import Optional, List -from common.typing.constructor_type_errors import ConstructorTypeErrors from common.typing.type_checks import check_types_and_set_values from spdx3.model.creation_information import CreationInformation @@ -25,23 +24,11 @@ class File(Artifact): content_identifier: Optional[str] = None # should be a valid URI file_purpose: Optional[List[SoftwarePurpose]] = None content_type: Optional[str] = None # placeholder for MediaType - + # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, file_purpose: Optional[SoftwarePurpose] = None, content_type: Optional[str] = None): file_purpose = [] if file_purpose is None else file_purpose - errors = [] - try: - Artifact.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - try: - check_types_and_set_values(self, locals()) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - - if errors: - raise ConstructorTypeErrors(errors) + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 15ab14ef5..7a96e8c45 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -10,8 +10,6 @@ # limitations under the License. from typing import Optional, List -from common.typing.constructor_type_errors import ConstructorTypeErrors - from spdx3.model.creation_information import CreationInformation from common.typing.type_checks import check_types_and_set_values @@ -28,7 +26,7 @@ class Package(Artifact): download_location: Optional[str] = None # anyURI package_uri: Optional[str] = None # anyURI homepage: Optional[str] = None # anyURI - + # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, @@ -36,16 +34,4 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio package_purpose: Optional[List[SoftwarePurpose]] = None, download_location: Optional[str] = None, package_uri: Optional[str] = None, homepage: Optional[str] = None): package_purpose = [] if package_purpose is None else package_purpose - errors = [] - try: - Artifact.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - try: - check_types_and_set_values(self, locals()) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - - if errors: - raise ConstructorTypeErrors(errors) + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index b303da671..0365cb9b6 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -12,8 +12,6 @@ from common.typing.type_checks import check_types_and_set_values -from common.typing.constructor_type_errors import ConstructorTypeErrors - from spdx3.model.creation_information import CreationInformation from common.typing.dataclass_with_properties import dataclass_with_properties @@ -24,22 +22,12 @@ @dataclass_with_properties class Sbom(Bom): + # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): - errors = [] - try: - Bom.__init__(self, spdx_id, creation_info, elements, root_elements, name, summary, description, comment, - verified_using, external_references, external_identifier, extension, namespaces, imports, - context) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - try: - check_types_and_set_values(self, locals()) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - if errors: - raise ConstructorTypeErrors(errors) + check_types_and_set_values(self, locals()) + diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index 0cc0689ca..a558fbc8c 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -10,7 +10,6 @@ # limitations under the License. from typing import Optional, Tuple, List -from common.typing.constructor_type_errors import ConstructorTypeErrors from common.typing.type_checks import check_types_and_set_values from spdx3.model.creation_information import CreationInformation @@ -26,7 +25,7 @@ class Snippet(Artifact): snippet_purpose: Optional[List[SoftwarePurpose]] = None byte_range: Optional[Tuple[int, int]] = None line_range: Optional[Tuple[int, int]] = None - + # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, @@ -34,16 +33,4 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio snippet_purpose: Optional[List[SoftwarePurpose]] = None, byte_range: Optional[Tuple[int, int]] = None, line_range: Optional[Tuple[int, int]] = None): snippet_purpose = [] if snippet_purpose is None else snippet_purpose - errors = [] - try: - Artifact.__init__(self, spdx_id, creation_info, name, summary, description, comment, verified_using, - external_references, external_identifier, extension, originated_by) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - try: - check_types_and_set_values(self, locals()) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - - if errors: - raise ConstructorTypeErrors(errors) + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index 8c3800bd0..f80422438 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -12,8 +12,6 @@ from common.typing.type_checks import check_types_and_set_values -from common.typing.constructor_type_errors import ConstructorTypeErrors - from spdx3.model.creation_information import CreationInformation from common.typing.dataclass_with_properties import dataclass_with_properties @@ -24,22 +22,13 @@ @dataclass_with_properties class SpdxDocument(Bundle): - # inherited field name is required for a SpdxDocument, no longer optional + # The inherited field "name" is required for a SpdxDocument, no longer optional. + # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, elements: List[Element], root_elements: List[Element], summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, extension: None = None, namespace: Optional[NamespaceMap] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): - errors = [] - try: - super().__init__(spdx_id, creation_info, elements, root_elements, name, summary, description, comment, - verified_using, external_references, external_identifier, extension, namespace, imports, - context) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - try: - check_types_and_set_values(self, locals(), origin_class=SpdxDocument) - except ConstructorTypeErrors as err: - errors.extend(err.get_messages()) - if errors: - raise ConstructorTypeErrors(errors) + + check_types_and_set_values(self, locals()) + diff --git a/src/spdx_tools/common/typing/type_checks.py b/src/spdx_tools/common/typing/type_checks.py index 5acd836ba..f4fbe1933 100644 --- a/src/spdx_tools/common/typing/type_checks.py +++ b/src/spdx_tools/common/typing/type_checks.py @@ -3,7 +3,7 @@ from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors -def check_types_and_set_values(instance_under_construction: Any, local_variables: Dict, origin_class: Any = None) -> None: +def check_types_and_set_values(instance_under_construction: Any, local_variables: Dict) -> None: """ Helper method to accumulate all type errors encountered during a constructor call and return them in a ConstructorTypeErrors instance. @@ -15,10 +15,8 @@ def check_types_and_set_values(instance_under_construction: Any, local_variables With the additional parameter origin_class we ensure that the attributes from the class that calls this method are set. If we use inheritance the instance_under_construction object might be a child object. """ - if not origin_class: - origin_class = instance_under_construction errors = [] - for key, value_type in origin_class.__annotations__.items(): + for key in instance_under_construction.__dataclass_fields__.keys(): value = local_variables.get(key) try: setattr(instance_under_construction, key, value) From 81599947bcfa9969ed88e83d652e34dedeb749e6 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 17 Jan 2023 08:47:45 +0100 Subject: [PATCH 103/354] [spdx3.0] refactor: use method instead of private variable to iterate through the fields of a dataclass and add license header Signed-off-by: Meret Behrens --- src/spdx_tools/common/typing/type_checks.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/spdx_tools/common/typing/type_checks.py b/src/spdx_tools/common/typing/type_checks.py index f4fbe1933..38734de35 100644 --- a/src/spdx_tools/common/typing/type_checks.py +++ b/src/spdx_tools/common/typing/type_checks.py @@ -1,3 +1,14 @@ +# Copyright (c) 2022 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from dataclasses import fields from typing import Any, Dict from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors @@ -12,11 +23,10 @@ def check_types_and_set_values(instance_under_construction: Any, local_variables return all type violations in one go. As an aside, defining constructors "manually" using this utility method helps avoid a nasty PyCharm bug: https://youtrack.jetbrains.com/issue/PY-34569 - With the additional parameter origin_class we ensure that the attributes from the class that calls this method - are set. If we use inheritance the instance_under_construction object might be a child object. """ errors = [] - for key in instance_under_construction.__dataclass_fields__.keys(): + for field in fields(instance_under_construction): + key = field.name value = local_variables.get(key) try: setattr(instance_under_construction, key, value) From 772182fbfa2f52020c2c17e66b6013359c5bfaee Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 16 Jan 2023 17:10:09 +0100 Subject: [PATCH 104/354] [spdx3.0] use mocks for element in test as check_types_and_set_values no longer uses them Signed-off-by: Meret Behrens --- tests/spdx3/model/software/test_sbom.py | 7 ++----- tests/spdx3/model/test_element.py | 20 ++++++++------------ tests/spdx3/model/test_relationship.py | 12 ++++-------- tests/spdx3/model/test_spdx_document.py | 6 ++---- 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index c10cec91f..dfb1b9062 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -11,16 +11,13 @@ from unittest import mock import pytest -from spdx3.model.element import Element from spdx3.model.software.sbom import Sbom +@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_sbom(creation_information): - element = Element("SPDXRef-Element", - creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class - +def test_correct_initialization_sbom(creation_information, element): sbom = Sbom("SPDXRef-Sbom", creation_information, elements=[element, element], root_elements=[element]) assert sbom.spdx_id == "SPDXRef-Sbom" diff --git a/tests/spdx3/model/test_element.py b/tests/spdx3/model/test_element.py index 49d01c15a..161feafc0 100644 --- a/tests/spdx3/model/test_element.py +++ b/tests/spdx3/model/test_element.py @@ -56,10 +56,9 @@ def test_invalid_initialization_artifact(creation_info): @mock.patch("spdx3.model.external_map.ExternalMap", autospec=True) @mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) +@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_spdx_collection(creation_information, namespace_map, external_map): - element = Element("SPDXRef-Element", - creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class +def test_correct_initialization_spdx_collection(creation_information, element, namespace_map, external_map): spdx_collection = SpdxCollection("SPDXRef-Collection", creation_information, elements=[element], root_elements=[element], namespaces=[namespace_map], imports=[external_map]) @@ -89,10 +88,9 @@ def test_invalid_initialization_spdx_collection(creation_information, namespace_ @mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) +@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_bundle(creation_information, namespace): - element = Element("SPDXRef-Element", - creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class +def test_correct_initialization_bundle(creation_information, element, namespace): bundle = Bundle("SPDXRef-Bundle", creation_information, elements=[element], root_elements=[element], namespaces=[namespace], context="context") @@ -104,10 +102,9 @@ def test_correct_initialization_bundle(creation_information, namespace): assert bundle.namespaces == [namespace] +@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization_bundle(creation_information): - element = Element("SPDXRef-Element", - creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class +def test_invalid_initialization_bundle(creation_information, element): with pytest.raises(TypeError) as err: Bundle(4, creation_information, elements=[element], root_elements=[element], namespaces=True, context=["yes"]) @@ -119,10 +116,9 @@ def test_invalid_initialization_bundle(creation_information): "NoneType); got list instead: ['yes']"] +@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_bom(creation_information): - element = Element("SPDXRef-Element", - creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class +def test_correct_initialization_bom(creation_information, element): bom = Bom("SPDXRef-Bom", creation_information, elements=[element], root_elements=[element]) assert bom.spdx_id == "SPDXRef-Bom" diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py index f501d9349..d35555468 100644 --- a/tests/spdx3/model/test_relationship.py +++ b/tests/spdx3/model/test_relationship.py @@ -12,16 +12,12 @@ import pytest -from spdx3.model.element import Element - from spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness -@mock.patch("spdx3.model.creation_information.CreationInformation") -def test_correct_initialization(creation_information): - element = Element("SPDXRef-Element", - creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class - +@mock.patch("spdx3.model.element.Element", autospec=True) +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization(creation_information, element): relationship = Relationship("SPDXRef-Relationship", creation_information, element, [element, element], RelationshipType.DESCRIBES, completeness=RelationshipCompleteness.UNKNOWN) @@ -33,7 +29,7 @@ def test_correct_initialization(creation_information): assert relationship.completeness == RelationshipCompleteness.UNKNOWN -@mock.patch("spdx3.model.creation_information.CreationInformation") +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Relationship("SPDXRef-Relationship", creation_information, "Element", 5, "Relationshiptype", completeness=True) diff --git a/tests/spdx3/model/test_spdx_document.py b/tests/spdx3/model/test_spdx_document.py index cba442911..02e2fdf7f 100644 --- a/tests/spdx3/model/test_spdx_document.py +++ b/tests/spdx3/model/test_spdx_document.py @@ -11,15 +11,13 @@ from unittest import mock import pytest -from spdx3.model.element import Element from spdx3.model.spdx_document import SpdxDocument +@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): - element = Element("SPDXRef-Element", - creation_info=creation_information) # using a mock here leads to failure as check_types_and_set_values accesses the element class +def test_correct_initialization(creation_information, element): spdx_document = SpdxDocument("SPDXRef-DOCUMENT", creation_information, "Test document", elements=[element], root_elements=[element]) From 2614304d289ed6c75f5f5b650c9deb88c4850fa6 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 16 Jan 2023 17:11:46 +0100 Subject: [PATCH 105/354] [spdx3.0] add IntegrityMethod Signed-off-by: Meret Behrens --- src/spdx3/model/element.py | 36 ++++++++----- src/spdx3/model/external_map.py | 9 ++-- src/spdx3/model/integrity_method.py | 60 ++++++++++++++++++++++ tests/spdx3/model/test_external_map.py | 9 ++-- tests/spdx3/model/test_integrity_method.py | 44 ++++++++++++++++ 5 files changed, 138 insertions(+), 20 deletions(-) create mode 100644 src/spdx3/model/integrity_method.py create mode 100644 tests/spdx3/model/test_integrity_method.py diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index 0754d7ef7..c42d5f5e4 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -16,6 +16,7 @@ from spdx3.model.creation_information import CreationInformation from spdx3.model.external_map import ExternalMap +from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.namespace_map import NamespaceMap @@ -29,15 +30,16 @@ class Element: summary: Optional[str] = None description: Optional[str] = None comment: Optional[str] = None - verified_using: None = None # placeholder for IntegrityMethod + verified_using: Optional[List[IntegrityMethod]] = field(default_factory=list) external_references: None = None # placeholder for ExternalReference external_identifier: None = None # placeholder for ExternalIdentifier extension: None = None # placeholder for extension def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None): + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None): + verified_using = [] if verified_using is None else verified_using check_types_and_set_values(self, locals()) @@ -47,14 +49,14 @@ class Artifact(Element): """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super class but as we have taken care of all fields this warning can be ignored.""" + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, originated_by: None = None): + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, originated_by: None = None): check_types_and_set_values(self, locals()) - @dataclass_with_properties class SpdxCollection(Element): # due to the inheritance we need to make all fields non-default in the __annotation__, the __init__ method still raises an error if required fields are not set @@ -65,26 +67,32 @@ class SpdxCollection(Element): """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super class but as we have taken care of all fields this warning can be ignored.""" + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, - external_references: None = None, external_identifier: None = None, extension: None = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None): namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports check_types_and_set_values(self, locals()) + @dataclass_with_properties class Bundle(SpdxCollection): context: Optional[str] = None """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super class but as we have taken care of all fields this warning can be ignored.""" + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, - external_references: None = None, external_identifier: None = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, + context: Optional[str] = None): check_types_and_set_values(self, locals()) @@ -93,10 +101,12 @@ class Bom(Bundle): """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super class but as we have taken care of all fields this warning can be ignored.""" + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, - external_references: None = None, external_identifier: None = None, extension: None = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/external_map.py b/src/spdx3/model/external_map.py index 885b46e6d..128df5aa2 100644 --- a/src/spdx3/model/external_map.py +++ b/src/spdx3/model/external_map.py @@ -8,17 +8,20 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional +from dataclasses import field +from typing import Optional, List from common.typing.type_checks import check_types_and_set_values from common.typing.dataclass_with_properties import dataclass_with_properties +from spdx3.model.integrity_method import IntegrityMethod @dataclass_with_properties class ExternalMap: external_id: str # anyURI - verified_using: None # placeholder for IntegrityMethod + verified_using: Optional[List[IntegrityMethod]] = field(default_factory=list) location_hint: Optional[str] = None # anyURI - def __init__(self, external_id: str, verified_using: None, location_hint: Optional[str] = None): + def __init__(self, external_id: str, verified_using: Optional[List[IntegrityMethod]]= None, location_hint: Optional[str] = None): + verified_using = [] if verified_using is None else verified_using check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/integrity_method.py b/src/spdx3/model/integrity_method.py new file mode 100644 index 000000000..964ec7397 --- /dev/null +++ b/src/spdx3/model/integrity_method.py @@ -0,0 +1,60 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from enum import Enum, auto +from typing import Optional + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values + + +@dataclass_with_properties +class IntegrityMethod: + # This should be an abstract class and should not be instantiated directly. + # We need to investigate if we can combine dataclasses with abstract base classes (https://github.com/spdx/tools-python/issues/431) + comment: Optional[str] = None + + def __init__(self, comment: Optional[str] = None): + check_types_and_set_values(self, locals()) + + +class HashAlgorithm(Enum): + BLAKE2B256 = auto() + BLAKE2B384 = auto() + BLAKE2B512 = auto() + BLAKE3 = auto() + MD2 = auto() + MD4 = auto() + MD5 = auto() + MD6 = auto() + OTHER = auto() + SHA1 = auto() + SHA224 = auto() + SHA256 = auto() + SHA3_224 = auto() + SHA3_256 = auto() + SHA3_384 = auto() + SHA3_512 = auto() + SHA384 = auto() + SHA512 = auto() + SPDXPVCSHA1 = auto() + SPDXPVCSHA256 = auto() + + +@dataclass_with_properties +class Hash(IntegrityMethod): + algorithm: HashAlgorithm = None + hash_value: str = None + """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent + class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super + class but as we have taken care of all fields this warning can be ignored.""" + + def __init__(self, algorithm: HashAlgorithm, hash_value: str, comment: Optional[str] = None): + check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/model/test_external_map.py b/tests/spdx3/model/test_external_map.py index 95257de0e..34ef6be66 100644 --- a/tests/spdx3/model/test_external_map.py +++ b/tests/spdx3/model/test_external_map.py @@ -8,16 +8,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from unittest import mock import pytest from spdx3.model.external_map import ExternalMap - -def test_correct_initialization(): - external_map = ExternalMap("https://external.id", None, "https://location.hint") +@mock.patch("spdx3.model.integrity_method.IntegrityMethod", autospec=True) +def test_correct_initialization(integrity_method): + external_map = ExternalMap("https://external.id", [integrity_method], "https://location.hint") assert external_map.external_id == "https://external.id" - assert external_map.verified_using is None + assert external_map.verified_using == [integrity_method] assert external_map.location_hint == "https://location.hint" diff --git a/tests/spdx3/model/test_integrity_method.py b/tests/spdx3/model/test_integrity_method.py new file mode 100644 index 000000000..70c379aec --- /dev/null +++ b/tests/spdx3/model/test_integrity_method.py @@ -0,0 +1,44 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import pytest + +from spdx3.model.integrity_method import IntegrityMethod, Hash, HashAlgorithm + + +def test_correct_initialization_integrity_method(): + integrity_method = IntegrityMethod(comment="This is a comment.") + + assert integrity_method.comment == "This is a comment." + + +def test_invalid_initialization_integrity_method(): + with pytest.raises(TypeError) as err: + IntegrityMethod(["some comments", "and some more comments"]) + + assert err.value.args[0] == ['SetterError IntegrityMethod: type of argument "comment" must be one of (str, ' + "NoneType); got list instead: ['some comments', 'and some more comments']"] + + +def test_correct_initialization_hash(): + hash = Hash(algorithm=HashAlgorithm.SHA1, hash_value="value") + + assert hash.algorithm == HashAlgorithm.SHA1 + assert hash.hash_value == "value" + + +def test_invalid_initialization_hash(): + with pytest.raises(TypeError) as err: + Hash("SHA1", 345) + + assert err.value.args[0] == ['SetterError Hash: type of argument "algorithm" must be ' + 'spdx3.model.integrity_method.HashAlgorithm; got str instead: SHA1', + 'SetterError Hash: type of argument "hash_value" must be str; got int ' + 'instead: 345'] From 8c24a3089560b39b81133516bd87624b7fe3ac7f Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 17 Jan 2023 14:15:00 +0100 Subject: [PATCH 106/354] [refactor] move each class in a separate file Signed-off-by: Meret Behrens --- src/spdx3/model/artifact.py | 31 ++++++ src/spdx3/model/bom.py | 36 +++++++ src/spdx3/model/bundle.py | 37 +++++++ src/spdx3/model/element.py | 71 -------------- src/spdx3/model/hash.py | 49 ++++++++++ src/spdx3/model/integrity_method.py | 36 ------- src/spdx3/model/software/file.py | 2 +- src/spdx3/model/software/package.py | 2 +- src/spdx3/model/software/sbom.py | 3 +- src/spdx3/model/software/snippet.py | 2 +- src/spdx3/model/spdx_collection.py | 42 ++++++++ src/spdx3/model/spdx_document.py | 3 +- tests/spdx3/model/test_artifact.py | 35 +++++++ tests/spdx3/model/test_bom.py | 39 ++++++++ tests/spdx3/model/test_bundle.py | 44 +++++++++ tests/spdx3/model/test_element.py | 107 +-------------------- tests/spdx3/model/test_hash.py | 30 ++++++ tests/spdx3/model/test_integrity_method.py | 19 +--- tests/spdx3/model/test_spdx_collection.py | 48 +++++++++ 19 files changed, 400 insertions(+), 236 deletions(-) create mode 100644 src/spdx3/model/artifact.py create mode 100644 src/spdx3/model/bom.py create mode 100644 src/spdx3/model/bundle.py create mode 100644 src/spdx3/model/hash.py create mode 100644 src/spdx3/model/spdx_collection.py create mode 100644 tests/spdx3/model/test_artifact.py create mode 100644 tests/spdx3/model/test_bom.py create mode 100644 tests/spdx3/model/test_bundle.py create mode 100644 tests/spdx3/model/test_hash.py create mode 100644 tests/spdx3/model/test_spdx_collection.py diff --git a/src/spdx3/model/artifact.py b/src/spdx3/model/artifact.py new file mode 100644 index 000000000..2162bac5e --- /dev/null +++ b/src/spdx3/model/artifact.py @@ -0,0 +1,31 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional, List + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values +from spdx3.model.creation_information import CreationInformation +from spdx3.model.element import Element +from spdx3.model.integrity_method import IntegrityMethod + + +@dataclass_with_properties +class Artifact(Element): + originated_by: None = None # placeholder for Actor + """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent + class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super + class but as we have taken care of all fields this warning can be ignored.""" + + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, + summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, originated_by: None = None): + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/bom.py b/src/spdx3/model/bom.py new file mode 100644 index 000000000..5483a13ef --- /dev/null +++ b/src/spdx3/model/bom.py @@ -0,0 +1,36 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import List, Optional + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values +from spdx3.model.creation_information import CreationInformation +from spdx3.model.element import Element +from spdx3.model.bundle import Bundle +from spdx3.model.external_map import ExternalMap +from spdx3.model.integrity_method import IntegrityMethod +from spdx3.model.namespace_map import NamespaceMap + + +@dataclass_with_properties +class Bom(Bundle): + """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent + class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super + class but as we have taken care of all fields this warning can be ignored.""" + + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], + root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, + context: Optional[str] = None): + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/bundle.py b/src/spdx3/model/bundle.py new file mode 100644 index 000000000..96bddf84a --- /dev/null +++ b/src/spdx3/model/bundle.py @@ -0,0 +1,37 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional, List + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values +from spdx3.model.creation_information import CreationInformation +from spdx3.model.element import Element +from spdx3.model.spdx_collection import SpdxCollection +from spdx3.model.external_map import ExternalMap +from spdx3.model.integrity_method import IntegrityMethod +from spdx3.model.namespace_map import NamespaceMap + + +@dataclass_with_properties +class Bundle(SpdxCollection): + context: Optional[str] = None + """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent + class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super + class but as we have taken care of all fields this warning can be ignored.""" + + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], + root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, + context: Optional[str] = None): + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index c42d5f5e4..33192349c 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -15,9 +15,7 @@ from common.typing.dataclass_with_properties import dataclass_with_properties from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_map import ExternalMap from spdx3.model.integrity_method import IntegrityMethod -from spdx3.model.namespace_map import NamespaceMap @dataclass_with_properties @@ -41,72 +39,3 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio external_identifier: None = None, extension: None = None): verified_using = [] if verified_using is None else verified_using check_types_and_set_values(self, locals()) - - -@dataclass_with_properties -class Artifact(Element): - originated_by: None = None # placeholder for Actor - """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent - class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super - class but as we have taken care of all fields this warning can be ignored.""" - - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, originated_by: None = None): - check_types_and_set_values(self, locals()) - - -@dataclass_with_properties -class SpdxCollection(Element): - # due to the inheritance we need to make all fields non-default in the __annotation__, the __init__ method still raises an error if required fields are not set - elements: List[Element] = field(default_factory=list) - root_elements: List[Element] = field(default_factory=list) - namespaces: Optional[List[NamespaceMap]] = field(default_factory=list) - imports: Optional[List[ExternalMap]] = field(default_factory=list) - """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent - class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super - class but as we have taken care of all fields this warning can be ignored.""" - - def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], - root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None): - namespaces = [] if namespaces is None else namespaces - imports = [] if imports is None else imports - check_types_and_set_values(self, locals()) - - -@dataclass_with_properties -class Bundle(SpdxCollection): - context: Optional[str] = None - """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent - class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super - class but as we have taken care of all fields this warning can be ignored.""" - - def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], - root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, - context: Optional[str] = None): - check_types_and_set_values(self, locals()) - - -@dataclass_with_properties -class Bom(Bundle): - """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent - class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super - class but as we have taken care of all fields this warning can be ignored.""" - - def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], - root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, - context: Optional[str] = None): - check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/hash.py b/src/spdx3/model/hash.py new file mode 100644 index 000000000..90d56b8b3 --- /dev/null +++ b/src/spdx3/model/hash.py @@ -0,0 +1,49 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from enum import Enum, auto +from typing import Optional + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values +from spdx3.model.integrity_method import IntegrityMethod + +class HashAlgorithm(Enum): + BLAKE2B256 = auto() + BLAKE2B384 = auto() + BLAKE2B512 = auto() + BLAKE3 = auto() + MD2 = auto() + MD4 = auto() + MD5 = auto() + MD6 = auto() + OTHER = auto() + SHA1 = auto() + SHA224 = auto() + SHA256 = auto() + SHA3_224 = auto() + SHA3_256 = auto() + SHA3_384 = auto() + SHA3_512 = auto() + SHA384 = auto() + SHA512 = auto() + SPDXPVCSHA1 = auto() + SPDXPVCSHA256 = auto() + + +@dataclass_with_properties +class Hash(IntegrityMethod): + algorithm: HashAlgorithm = None + hash_value: str = None + # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). + + def __init__(self, algorithm: HashAlgorithm, hash_value: str, comment: Optional[str] = None): + check_types_and_set_values(self, locals()) + diff --git a/src/spdx3/model/integrity_method.py b/src/spdx3/model/integrity_method.py index 964ec7397..e9f50c521 100644 --- a/src/spdx3/model/integrity_method.py +++ b/src/spdx3/model/integrity_method.py @@ -8,7 +8,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from enum import Enum, auto from typing import Optional from common.typing.dataclass_with_properties import dataclass_with_properties @@ -23,38 +22,3 @@ class IntegrityMethod: def __init__(self, comment: Optional[str] = None): check_types_and_set_values(self, locals()) - - -class HashAlgorithm(Enum): - BLAKE2B256 = auto() - BLAKE2B384 = auto() - BLAKE2B512 = auto() - BLAKE3 = auto() - MD2 = auto() - MD4 = auto() - MD5 = auto() - MD6 = auto() - OTHER = auto() - SHA1 = auto() - SHA224 = auto() - SHA256 = auto() - SHA3_224 = auto() - SHA3_256 = auto() - SHA3_384 = auto() - SHA3_512 = auto() - SHA384 = auto() - SHA512 = auto() - SPDXPVCSHA1 = auto() - SPDXPVCSHA256 = auto() - - -@dataclass_with_properties -class Hash(IntegrityMethod): - algorithm: HashAlgorithm = None - hash_value: str = None - """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent - class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super - class but as we have taken care of all fields this warning can be ignored.""" - - def __init__(self, algorithm: HashAlgorithm, hash_value: str, comment: Optional[str] = None): - check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index 8612412ba..b891d26c0 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -15,7 +15,7 @@ from spdx3.model.creation_information import CreationInformation from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.element import Artifact +from spdx3.model.artifact import Artifact from spdx3.model.software.software_purpose import SoftwarePurpose diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 7a96e8c45..1ee366818 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -15,7 +15,7 @@ from common.typing.type_checks import check_types_and_set_values from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.element import Artifact +from spdx3.model.artifact import Artifact from spdx3.model.software.software_purpose import SoftwarePurpose diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index 0365cb9b6..15ef629e5 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -15,7 +15,8 @@ from spdx3.model.creation_information import CreationInformation from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.element import Bom, Element +from spdx3.model.element import Element +from spdx3.model.bom import Bom from spdx3.model.external_map import ExternalMap from spdx3.model.namespace_map import NamespaceMap diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index a558fbc8c..ec1924cef 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -16,7 +16,7 @@ from common.typing.dataclass_with_properties import dataclass_with_properties from spdx3.model.software.software_purpose import SoftwarePurpose -from spdx3.model.element import Artifact +from spdx3.model.artifact import Artifact @dataclass_with_properties diff --git a/src/spdx3/model/spdx_collection.py b/src/spdx3/model/spdx_collection.py new file mode 100644 index 000000000..739623b77 --- /dev/null +++ b/src/spdx3/model/spdx_collection.py @@ -0,0 +1,42 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from dataclasses import field +from typing import List, Optional + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values +from spdx3.model.creation_information import CreationInformation +from spdx3.model.element import Element +from spdx3.model.external_map import ExternalMap +from spdx3.model.integrity_method import IntegrityMethod +from spdx3.model.namespace_map import NamespaceMap + + +@dataclass_with_properties +class SpdxCollection(Element): + # due to the inheritance we need to make all fields non-default in the __annotation__, the __init__ method still raises an error if required fields are not set + elements: List[Element] = field(default_factory=list) + root_elements: List[Element] = field(default_factory=list) + namespaces: Optional[List[NamespaceMap]] = field(default_factory=list) + imports: Optional[List[ExternalMap]] = field(default_factory=list) + """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent + class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super + class but as we have taken care of all fields this warning can be ignored.""" + + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], + root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None): + namespaces = [] if namespaces is None else namespaces + imports = [] if imports is None else imports + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index f80422438..d1537d41c 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -15,7 +15,8 @@ from spdx3.model.creation_information import CreationInformation from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.element import Bundle, Element +from spdx3.model.element import Element +from spdx3.model.bundle import Bundle from spdx3.model.external_map import ExternalMap from spdx3.model.namespace_map import NamespaceMap diff --git a/tests/spdx3/model/test_artifact.py b/tests/spdx3/model/test_artifact.py new file mode 100644 index 000000000..d68e44b65 --- /dev/null +++ b/tests/spdx3/model/test_artifact.py @@ -0,0 +1,35 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from spdx3.model.artifact import Artifact + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization_artifact(creation_info): + artifact = Artifact("SPDXRef-Artifact", creation_info, originated_by=None) + + assert artifact.spdx_id == "SPDXRef-Artifact" + assert artifact.creation_info == creation_info + assert artifact.originated_by is None + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_invalid_initialization_artifact(creation_info): + with pytest.raises(TypeError) as err: + Artifact(65, creation_info, originated_by=54) + + assert err.value.args[0] == ['SetterError Artifact: type of argument "spdx_id" must be str; got int ' + 'instead: 65', + 'SetterError Artifact: type of argument "originated_by" must be NoneType; got ' + 'int instead: 54'] diff --git a/tests/spdx3/model/test_bom.py b/tests/spdx3/model/test_bom.py new file mode 100644 index 000000000..4259cbd07 --- /dev/null +++ b/tests/spdx3/model/test_bom.py @@ -0,0 +1,39 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from unittest import mock + +import pytest + +from spdx3.model.bom import Bom + + +@mock.patch("spdx3.model.element.Element", autospec=True) +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization_bom(creation_information, element): + bom = Bom("SPDXRef-Bom", creation_information, elements=[element], root_elements=[element]) + + assert bom.spdx_id == "SPDXRef-Bom" + assert bom.creation_info == creation_information + assert bom.elements == [element] + assert bom.root_elements == [element] + + +def test_invalid_initialization_bom(): + with pytest.raises(TypeError) as err: + Bom(1, "Creation Information", elements=[5], root_elements=[]) + + assert err.value.args[0] == ['SetterError Bom: type of argument "spdx_id" must be str; got int instead: 1', + 'SetterError Bom: type of argument "creation_info" must be ' + 'spdx3.model.creation_information.CreationInformation; got str instead: ' + 'Creation Information', + 'SetterError Bom: type of argument "elements"[0] must be ' + 'spdx3.model.element.Element; got int instead: [5]'] diff --git a/tests/spdx3/model/test_bundle.py b/tests/spdx3/model/test_bundle.py new file mode 100644 index 000000000..24c5d1a01 --- /dev/null +++ b/tests/spdx3/model/test_bundle.py @@ -0,0 +1,44 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from spdx3.model.bundle import Bundle + + +@mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) +@mock.patch("spdx3.model.element.Element", autospec=True) +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization_bundle(creation_information, element, namespace): + bundle = Bundle("SPDXRef-Bundle", creation_information, elements=[element], root_elements=[element], + namespaces=[namespace], context="context") + + assert bundle.spdx_id == "SPDXRef-Bundle" + assert bundle.creation_info == creation_information + assert bundle.elements == [element] + assert bundle.root_elements == [element] + assert bundle.context == "context" + assert bundle.namespaces == [namespace] + + +@mock.patch("spdx3.model.element.Element", autospec=True) +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_invalid_initialization_bundle(creation_information, element): + with pytest.raises(TypeError) as err: + Bundle(4, creation_information, elements=[element], root_elements=[element], namespaces=True, context=["yes"]) + + assert err.value.args[0] == ['SetterError Bundle: type of argument "spdx_id" must be str; got int instead: ' + '4', + 'SetterError Bundle: type of argument "namespaces" must be one of ' + '(List[spdx3.model.namespace_map.NamespaceMap], NoneType); got bool instead: True', + 'SetterError Bundle: type of argument "context" must be one of (str, ' + "NoneType); got list instead: ['yes']"] diff --git a/tests/spdx3/model/test_element.py b/tests/spdx3/model/test_element.py index 161feafc0..0e51fbb19 100644 --- a/tests/spdx3/model/test_element.py +++ b/tests/spdx3/model/test_element.py @@ -12,7 +12,7 @@ import pytest -from spdx3.model.element import Element, Artifact, SpdxCollection, Bundle, Bom +from spdx3.model.element import Element @mock.patch("spdx3.model.creation_information.CreationInformation") @@ -32,108 +32,3 @@ def test_invalid_initialization_element(creation_info): 'instead: 54', 'SetterError Element: type of argument "name" must be one of (str, NoneType); ' 'got int instead: 76'] - - -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_artifact(creation_info): - artifact = Artifact("SPDXRef-Artifact", creation_info, originated_by=None) - - assert artifact.spdx_id == "SPDXRef-Artifact" - assert artifact.creation_info == creation_info - assert artifact.originated_by is None - - -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization_artifact(creation_info): - with pytest.raises(TypeError) as err: - Artifact(65, creation_info, originated_by=54) - - assert err.value.args[0] == ['SetterError Artifact: type of argument "spdx_id" must be str; got int ' - 'instead: 65', - 'SetterError Artifact: type of argument "originated_by" must be NoneType; got ' - 'int instead: 54'] - - -@mock.patch("spdx3.model.external_map.ExternalMap", autospec=True) -@mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) -@mock.patch("spdx3.model.element.Element", autospec=True) -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_spdx_collection(creation_information, element, namespace_map, external_map): - spdx_collection = SpdxCollection("SPDXRef-Collection", creation_information, elements=[element], - root_elements=[element], namespaces=[namespace_map], imports=[external_map]) - - assert spdx_collection.spdx_id == "SPDXRef-Collection" - assert spdx_collection.creation_info == creation_information - assert spdx_collection.elements == [element] - assert spdx_collection.root_elements == [element] - assert spdx_collection.namespaces == [namespace_map] - assert spdx_collection.imports == [external_map] - - -@mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization_spdx_collection(creation_information, namespace_map): - with pytest.raises(TypeError) as err: - SpdxCollection("SPDXRef-Collection", creation_information, elements=[None], root_elements=3, - namespaces=namespace_map, - imports=["ExternalMap"]) - - assert err.value.args[0] == ['SetterError SpdxCollection: type of argument "elements"[0] must be ' - 'spdx3.model.element.Element; got NoneType instead: [None]', - 'SetterError SpdxCollection: type of argument "root_elements" must be a list; ' - 'got int instead: 3', - 'SetterError SpdxCollection: type of argument "imports" must be one of ' - '(List[spdx3.model.external_map.ExternalMap], NoneType); got list instead: ' - "['ExternalMap']"] - - -@mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) -@mock.patch("spdx3.model.element.Element", autospec=True) -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_bundle(creation_information, element, namespace): - bundle = Bundle("SPDXRef-Bundle", creation_information, elements=[element], root_elements=[element], - namespaces=[namespace], context="context") - - assert bundle.spdx_id == "SPDXRef-Bundle" - assert bundle.creation_info == creation_information - assert bundle.elements == [element] - assert bundle.root_elements == [element] - assert bundle.context == "context" - assert bundle.namespaces == [namespace] - - -@mock.patch("spdx3.model.element.Element", autospec=True) -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization_bundle(creation_information, element): - with pytest.raises(TypeError) as err: - Bundle(4, creation_information, elements=[element], root_elements=[element], namespaces=True, context=["yes"]) - - assert err.value.args[0] == ['SetterError Bundle: type of argument "spdx_id" must be str; got int instead: ' - '4', - 'SetterError Bundle: type of argument "namespaces" must be one of ' - '(List[spdx3.model.namespace_map.NamespaceMap], NoneType); got bool instead: True', - 'SetterError Bundle: type of argument "context" must be one of (str, ' - "NoneType); got list instead: ['yes']"] - - -@mock.patch("spdx3.model.element.Element", autospec=True) -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_bom(creation_information, element): - bom = Bom("SPDXRef-Bom", creation_information, elements=[element], root_elements=[element]) - - assert bom.spdx_id == "SPDXRef-Bom" - assert bom.creation_info == creation_information - assert bom.elements == [element] - assert bom.root_elements == [element] - - -def test_invalid_initialization_bom(): - with pytest.raises(TypeError) as err: - Bom(1, "Creation Information", elements=[5], root_elements=[]) - - assert err.value.args[0] == ['SetterError Bom: type of argument "spdx_id" must be str; got int instead: 1', - 'SetterError Bom: type of argument "creation_info" must be ' - 'spdx3.model.creation_information.CreationInformation; got str instead: ' - 'Creation Information', - 'SetterError Bom: type of argument "elements"[0] must be ' - 'spdx3.model.element.Element; got int instead: [5]'] diff --git a/tests/spdx3/model/test_hash.py b/tests/spdx3/model/test_hash.py new file mode 100644 index 000000000..45b508dfa --- /dev/null +++ b/tests/spdx3/model/test_hash.py @@ -0,0 +1,30 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import pytest + +from spdx3.model.hash import Hash, HashAlgorithm + + +def test_correct_initialization_hash(): + hash = Hash(algorithm=HashAlgorithm.SHA1, hash_value="value") + + assert hash.algorithm == HashAlgorithm.SHA1 + assert hash.hash_value == "value" + + +def test_invalid_initialization_hash(): + with pytest.raises(TypeError) as err: + Hash("SHA1", 345) + + assert err.value.args[0] == ['SetterError Hash: type of argument "algorithm" must be ' + 'spdx3.model.hash.HashAlgorithm; got str instead: SHA1', + 'SetterError Hash: type of argument "hash_value" must be str; got int ' + 'instead: 345'] diff --git a/tests/spdx3/model/test_integrity_method.py b/tests/spdx3/model/test_integrity_method.py index 70c379aec..cd237710c 100644 --- a/tests/spdx3/model/test_integrity_method.py +++ b/tests/spdx3/model/test_integrity_method.py @@ -10,7 +10,7 @@ # limitations under the License. import pytest -from spdx3.model.integrity_method import IntegrityMethod, Hash, HashAlgorithm +from spdx3.model.integrity_method import IntegrityMethod def test_correct_initialization_integrity_method(): @@ -25,20 +25,3 @@ def test_invalid_initialization_integrity_method(): assert err.value.args[0] == ['SetterError IntegrityMethod: type of argument "comment" must be one of (str, ' "NoneType); got list instead: ['some comments', 'and some more comments']"] - - -def test_correct_initialization_hash(): - hash = Hash(algorithm=HashAlgorithm.SHA1, hash_value="value") - - assert hash.algorithm == HashAlgorithm.SHA1 - assert hash.hash_value == "value" - - -def test_invalid_initialization_hash(): - with pytest.raises(TypeError) as err: - Hash("SHA1", 345) - - assert err.value.args[0] == ['SetterError Hash: type of argument "algorithm" must be ' - 'spdx3.model.integrity_method.HashAlgorithm; got str instead: SHA1', - 'SetterError Hash: type of argument "hash_value" must be str; got int ' - 'instead: 345'] diff --git a/tests/spdx3/model/test_spdx_collection.py b/tests/spdx3/model/test_spdx_collection.py new file mode 100644 index 000000000..fb3820b30 --- /dev/null +++ b/tests/spdx3/model/test_spdx_collection.py @@ -0,0 +1,48 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from spdx3.model.spdx_collection import SpdxCollection + + +@mock.patch("spdx3.model.external_map.ExternalMap", autospec=True) +@mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) +@mock.patch("spdx3.model.element.Element", autospec=True) +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization_spdx_collection(creation_information, element, namespace_map, external_map): + spdx_collection = SpdxCollection("SPDXRef-Collection", creation_information, elements=[element], + root_elements=[element], namespaces=[namespace_map], imports=[external_map]) + + assert spdx_collection.spdx_id == "SPDXRef-Collection" + assert spdx_collection.creation_info == creation_information + assert spdx_collection.elements == [element] + assert spdx_collection.root_elements == [element] + assert spdx_collection.namespaces == [namespace_map] + assert spdx_collection.imports == [external_map] + + +@mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_invalid_initialization_spdx_collection(creation_information, namespace_map): + with pytest.raises(TypeError) as err: + SpdxCollection("SPDXRef-Collection", creation_information, elements=[None], root_elements=3, + namespaces=namespace_map, + imports=["ExternalMap"]) + + assert err.value.args[0] == ['SetterError SpdxCollection: type of argument "elements"[0] must be ' + 'spdx3.model.element.Element; got NoneType instead: [None]', + 'SetterError SpdxCollection: type of argument "root_elements" must be a list; ' + 'got int instead: 3', + 'SetterError SpdxCollection: type of argument "imports" must be one of ' + '(List[spdx3.model.external_map.ExternalMap], NoneType); got list instead: ' + "['ExternalMap']"] From a78ef585782085092c14faddff773f82a8dc2beb Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 18 Jan 2023 15:11:16 +0100 Subject: [PATCH 107/354] [review] shorten comment about pycharm warning, add comment for abstract classes Signed-off-by: Meret Behrens --- src/spdx3/model/artifact.py | 6 +++--- src/spdx3/model/bom.py | 4 +--- src/spdx3/model/bundle.py | 4 +--- src/spdx3/model/spdx_collection.py | 6 +++--- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/spdx3/model/artifact.py b/src/spdx3/model/artifact.py index 2162bac5e..eec85317e 100644 --- a/src/spdx3/model/artifact.py +++ b/src/spdx3/model/artifact.py @@ -19,11 +19,11 @@ @dataclass_with_properties class Artifact(Element): + # This should be an abstract class and should not be instantiated directly. + # We need to investigate if we can combine dataclasses with abstract base classes (https://github.com/spdx/tools-python/issues/431) originated_by: None = None # placeholder for Actor - """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent - class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super - class but as we have taken care of all fields this warning can be ignored.""" + # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, diff --git a/src/spdx3/model/bom.py b/src/spdx3/model/bom.py index 5483a13ef..506b2c08e 100644 --- a/src/spdx3/model/bom.py +++ b/src/spdx3/model/bom.py @@ -22,9 +22,7 @@ @dataclass_with_properties class Bom(Bundle): - """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent - class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super - class but as we have taken care of all fields this warning can be ignored.""" + # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, diff --git a/src/spdx3/model/bundle.py b/src/spdx3/model/bundle.py index 96bddf84a..5a2ea42c1 100644 --- a/src/spdx3/model/bundle.py +++ b/src/spdx3/model/bundle.py @@ -23,9 +23,7 @@ @dataclass_with_properties class Bundle(SpdxCollection): context: Optional[str] = None - """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent - class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super - class but as we have taken care of all fields this warning can be ignored.""" + # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, diff --git a/src/spdx3/model/spdx_collection.py b/src/spdx3/model/spdx_collection.py index 739623b77..3d5a23e0e 100644 --- a/src/spdx3/model/spdx_collection.py +++ b/src/spdx3/model/spdx_collection.py @@ -22,14 +22,14 @@ @dataclass_with_properties class SpdxCollection(Element): + # This should be an abstract class and should not be instantiated directly. + # We need to investigate if we can combine dataclasses with abstract base classes (https://github.com/spdx/tools-python/issues/431) # due to the inheritance we need to make all fields non-default in the __annotation__, the __init__ method still raises an error if required fields are not set elements: List[Element] = field(default_factory=list) root_elements: List[Element] = field(default_factory=list) namespaces: Optional[List[NamespaceMap]] = field(default_factory=list) imports: Optional[List[ExternalMap]] = field(default_factory=list) - """We overwrite the constructor of the inherited class so that all fields (including the fields from the parent - class) are set. Pycharm (and probably also other IDEs) warns about a missing call to the constructor of the super - class but as we have taken care of all fields this warning can be ignored.""" + # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, From e5666d4027b74497d303aa9ad242d06b19a9472f Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 17 Jan 2023 14:46:51 +0100 Subject: [PATCH 108/354] [refactor] rename tests Signed-off-by: Meret Behrens --- tests/spdx3/model/software/test_file.py | 4 ++-- tests/spdx3/model/software/test_package.py | 4 ++-- tests/spdx3/model/software/test_sbom.py | 4 ++-- tests/spdx3/model/software/test_snippet.py | 4 ++-- tests/spdx3/model/test_artifact.py | 4 ++-- tests/spdx3/model/test_bom.py | 4 ++-- tests/spdx3/model/test_bundle.py | 4 ++-- tests/spdx3/model/test_element.py | 4 ++-- tests/spdx3/model/test_hash.py | 4 ++-- tests/spdx3/model/test_integrity_method.py | 4 ++-- tests/spdx3/model/test_spdx_collection.py | 4 ++-- 11 files changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index 35dd77aea..47c4dce13 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -18,7 +18,7 @@ @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_file(creation_information): +def test_correct_initialization(creation_information): file = File("SPDXRef-File", creation_information, content_identifier="https://any.uri", file_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE], content_type="MediaType") @@ -30,7 +30,7 @@ def test_correct_initialization_file(creation_information): @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization_file(creation_information): +def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: File(1, creation_information, content_identifier=3, file_purpose=SoftwarePurpose.FILE, content_type=SoftwarePurpose.ARCHIVE) diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index fc9b702db..2933085f3 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -18,7 +18,7 @@ @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_package(creation_information): +def test_correct_initialization(creation_information): package = Package("SPDXRef-Package", creation_information, content_identifier="https://any.uri", package_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH], download_location="https://downloadlocation", package_uri="https://package.uri", @@ -34,7 +34,7 @@ def test_correct_initialization_package(creation_information): @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization_package(creation_information): +def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Package("SPDXRef-Package", creation_information, content_identifier=3, package_purpose=SoftwarePurpose.FILE, download_location=4, package_uri=["uris"], homepage=True) diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index dfb1b9062..f03c30d00 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -17,7 +17,7 @@ @mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_sbom(creation_information, element): +def test_correct_initialization(creation_information, element): sbom = Sbom("SPDXRef-Sbom", creation_information, elements=[element, element], root_elements=[element]) assert sbom.spdx_id == "SPDXRef-Sbom" @@ -25,7 +25,7 @@ def test_correct_initialization_sbom(creation_information, element): assert sbom.elements == [element, element] assert sbom.root_elements == [element] -def test_invalid_initialization_sbom(): +def test_invalid_initialization(): with pytest.raises(TypeError) as err: Sbom(2, {"creation_info": [3, 4, 5]}, elements=[], root_elements=[]) diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index 8b6ae3b9d..2b0e72fc5 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -18,7 +18,7 @@ @mock.patch("spdx3.model.software.snippet.Snippet", autospec=True) -def test_correct_initialization_snippet(creation_information): +def test_correct_initialization(creation_information): snippet = Snippet("SPDXRef-Snippet", creation_information, content_identifier="https://content.identifier", snippet_purpose=[SoftwarePurpose.SOURCE], byte_range=(3, 4), line_range=(346, 456)) @@ -31,7 +31,7 @@ def test_correct_initialization_snippet(creation_information): @mock.patch("spdx3.model.software.snippet.Snippet", autospec=True) -def test_invalid_initialization_snippet(creation_information): +def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Snippet(2, creation_information, originated_by=34, byte_range="34:45") diff --git a/tests/spdx3/model/test_artifact.py b/tests/spdx3/model/test_artifact.py index d68e44b65..533de4166 100644 --- a/tests/spdx3/model/test_artifact.py +++ b/tests/spdx3/model/test_artifact.py @@ -16,7 +16,7 @@ @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_artifact(creation_info): +def test_correct_initialization(creation_info): artifact = Artifact("SPDXRef-Artifact", creation_info, originated_by=None) assert artifact.spdx_id == "SPDXRef-Artifact" @@ -25,7 +25,7 @@ def test_correct_initialization_artifact(creation_info): @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization_artifact(creation_info): +def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: Artifact(65, creation_info, originated_by=54) diff --git a/tests/spdx3/model/test_bom.py b/tests/spdx3/model/test_bom.py index 4259cbd07..5311a1c81 100644 --- a/tests/spdx3/model/test_bom.py +++ b/tests/spdx3/model/test_bom.py @@ -18,7 +18,7 @@ @mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_bom(creation_information, element): +def test_correct_initialization(creation_information, element): bom = Bom("SPDXRef-Bom", creation_information, elements=[element], root_elements=[element]) assert bom.spdx_id == "SPDXRef-Bom" @@ -27,7 +27,7 @@ def test_correct_initialization_bom(creation_information, element): assert bom.root_elements == [element] -def test_invalid_initialization_bom(): +def test_invalid_initialization(): with pytest.raises(TypeError) as err: Bom(1, "Creation Information", elements=[5], root_elements=[]) diff --git a/tests/spdx3/model/test_bundle.py b/tests/spdx3/model/test_bundle.py index 24c5d1a01..78ac27eec 100644 --- a/tests/spdx3/model/test_bundle.py +++ b/tests/spdx3/model/test_bundle.py @@ -18,7 +18,7 @@ @mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) @mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_bundle(creation_information, element, namespace): +def test_correct_initialization(creation_information, element, namespace): bundle = Bundle("SPDXRef-Bundle", creation_information, elements=[element], root_elements=[element], namespaces=[namespace], context="context") @@ -32,7 +32,7 @@ def test_correct_initialization_bundle(creation_information, element, namespace) @mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization_bundle(creation_information, element): +def test_invalid_initialization(creation_information, element): with pytest.raises(TypeError) as err: Bundle(4, creation_information, elements=[element], root_elements=[element], namespaces=True, context=["yes"]) diff --git a/tests/spdx3/model/test_element.py b/tests/spdx3/model/test_element.py index 0e51fbb19..a34e5d82f 100644 --- a/tests/spdx3/model/test_element.py +++ b/tests/spdx3/model/test_element.py @@ -16,7 +16,7 @@ @mock.patch("spdx3.model.creation_information.CreationInformation") -def test_correct_initialization_element(creation_info): +def test_correct_initialization(creation_info): element = Element("SPDXRef-Element", creation_info) assert element.spdx_id == "SPDXRef-Element" @@ -24,7 +24,7 @@ def test_correct_initialization_element(creation_info): @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization_element(creation_info): +def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: Element(54, creation_info, name=76) diff --git a/tests/spdx3/model/test_hash.py b/tests/spdx3/model/test_hash.py index 45b508dfa..6fcce2fe2 100644 --- a/tests/spdx3/model/test_hash.py +++ b/tests/spdx3/model/test_hash.py @@ -13,14 +13,14 @@ from spdx3.model.hash import Hash, HashAlgorithm -def test_correct_initialization_hash(): +def test_correct_initialization(): hash = Hash(algorithm=HashAlgorithm.SHA1, hash_value="value") assert hash.algorithm == HashAlgorithm.SHA1 assert hash.hash_value == "value" -def test_invalid_initialization_hash(): +def test_invalid_initialization(): with pytest.raises(TypeError) as err: Hash("SHA1", 345) diff --git a/tests/spdx3/model/test_integrity_method.py b/tests/spdx3/model/test_integrity_method.py index cd237710c..c3d3c8fa4 100644 --- a/tests/spdx3/model/test_integrity_method.py +++ b/tests/spdx3/model/test_integrity_method.py @@ -13,13 +13,13 @@ from spdx3.model.integrity_method import IntegrityMethod -def test_correct_initialization_integrity_method(): +def test_correct_initialization(): integrity_method = IntegrityMethod(comment="This is a comment.") assert integrity_method.comment == "This is a comment." -def test_invalid_initialization_integrity_method(): +def test_invalid_initialization(): with pytest.raises(TypeError) as err: IntegrityMethod(["some comments", "and some more comments"]) diff --git a/tests/spdx3/model/test_spdx_collection.py b/tests/spdx3/model/test_spdx_collection.py index fb3820b30..ad6eaa978 100644 --- a/tests/spdx3/model/test_spdx_collection.py +++ b/tests/spdx3/model/test_spdx_collection.py @@ -19,7 +19,7 @@ @mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) @mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization_spdx_collection(creation_information, element, namespace_map, external_map): +def test_correct_initialization(creation_information, element, namespace_map, external_map): spdx_collection = SpdxCollection("SPDXRef-Collection", creation_information, elements=[element], root_elements=[element], namespaces=[namespace_map], imports=[external_map]) @@ -33,7 +33,7 @@ def test_correct_initialization_spdx_collection(creation_information, element, n @mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization_spdx_collection(creation_information, namespace_map): +def test_invalid_initialization(creation_information, namespace_map): with pytest.raises(TypeError) as err: SpdxCollection("SPDXRef-Collection", creation_information, elements=[None], root_elements=3, namespaces=namespace_map, From 0864a932eddbc147b37329b028739cf378394c74 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 17 Jan 2023 15:47:49 +0100 Subject: [PATCH 109/354] [spdx3.0] add annotation Signed-off-by: Meret Behrens --- src/spdx3/model/annotation.py | 41 +++++++++++++++++++++++++ tests/spdx3/model/test_annotation.py | 45 ++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/spdx3/model/annotation.py create mode 100644 tests/spdx3/model/test_annotation.py diff --git a/src/spdx3/model/annotation.py b/src/spdx3/model/annotation.py new file mode 100644 index 000000000..2b4c3ba53 --- /dev/null +++ b/src/spdx3/model/annotation.py @@ -0,0 +1,41 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from dataclasses import field +from enum import Enum, auto +from typing import Optional, List + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values + +from spdx3.model.integrity_method import IntegrityMethod + +from spdx3.model.creation_information import CreationInformation + +from spdx3.model.element import Element + +class AnnotationType(Enum): + REVIEW = auto() + OTHER = auto() + +@dataclass_with_properties +class Annotation(Element): + annotation_type: AnnotationType = None + subject: List[Element] = field(default_factory=list) + content_type: Optional[str] = None # placeholder for MediaType + statement: Optional[str] = None + # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). + def __init__(self, spdx_id: str, creation_info: CreationInformation, annotation_type: AnnotationType, + subject: List[Element], name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, content_type: Optional[str] = None, + statement: Optional[str] = None): + check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/model/test_annotation.py b/tests/spdx3/model/test_annotation.py new file mode 100644 index 000000000..beaf1a27c --- /dev/null +++ b/tests/spdx3/model/test_annotation.py @@ -0,0 +1,45 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +import pytest + +from spdx3.model.annotation import Annotation, AnnotationType + + +@mock.patch("spdx3.model.element.Element", autospec=True) +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_correct_initialization(creation_information, element): + annotation = Annotation("SPDXRef-Annotation", creation_information, AnnotationType.OTHER, [element], + content_type="mediaType", statement="This is a statement") + + assert annotation.spdx_id == "SPDXRef-Annotation" + assert annotation.creation_info == creation_information + assert annotation.annotation_type == AnnotationType.OTHER + assert annotation.subject == [element] + assert annotation.content_type == "mediaType" + assert annotation.statement == "This is a statement" + + +@mock.patch("spdx3.model.creation_information.CreationInformation") +def test_invalid_initialization(creation_information): + with pytest.raises(TypeError) as err: + Annotation("SPDXRef-Annotation", creation_information, "REVIEW", {"element": 1}, content_type=4, + statement=["some statements"]) + + assert err.value.args[0] == ['SetterError Annotation: type of argument "annotation_type" must be ' + 'spdx3.model.annotation.AnnotationType; got str instead: REVIEW', + 'SetterError Annotation: type of argument "subject" must be a list; got dict ' + "instead: {'element': 1}", + 'SetterError Annotation: type of argument "content_type" must be one of (str, ' + 'NoneType); got int instead: 4', + 'SetterError Annotation: type of argument "statement" must be one of (str, ' + "NoneType); got list instead: ['some statements']"] From c63e1c4f25a2bdbfe5dfad096abce766c46635a6 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 17 Jan 2023 16:02:41 +0100 Subject: [PATCH 110/354] [spdx3.0] add external reference Signed-off-by: Meret Behrens --- src/spdx3/model/external_reference.py | 39 ++++++++++++++++++++ tests/spdx3/model/test_external_reference.py | 37 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/spdx3/model/external_reference.py create mode 100644 tests/spdx3/model/test_external_reference.py diff --git a/src/spdx3/model/external_reference.py b/src/spdx3/model/external_reference.py new file mode 100644 index 000000000..bcfdfb171 --- /dev/null +++ b/src/spdx3/model/external_reference.py @@ -0,0 +1,39 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from dataclasses import field +from enum import Enum, auto +from typing import Optional, List + +from common.typing.type_checks import check_types_and_set_values + +from common.typing.dataclass_with_properties import dataclass_with_properties + + +class ExternalReferenceType(Enum): + ALT_DOWNLOAD_LOCATION = auto() + ALT_WEB_PAGE = auto() + OTHER = auto() + SECURITY_ADVISORY = auto() + SECURITY_FIX = auto() + SECURITY_OTHER = auto() + + +@dataclass_with_properties +class ExternalReference: + external_reference_type: Optional[ExternalReferenceType] = None + locator: List[str] = field(default_factory=list) + content_type: Optional[str] = None # placeholder for MediaType + comment: Optional[str] = None + + def __init__(self, external_reference_type: Optional[ExternalReferenceType] = None, locator: List[str] = None, + content_type: Optional[str] = None, comment: Optional[str] = None): + locator = [] if locator is None else locator + check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/model/test_external_reference.py b/tests/spdx3/model/test_external_reference.py new file mode 100644 index 000000000..1ab731ca9 --- /dev/null +++ b/tests/spdx3/model/test_external_reference.py @@ -0,0 +1,37 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import pytest + +from spdx3.model.external_reference import ExternalReference, ExternalReferenceType + + +def test_correct_initialization(): + external_reference = ExternalReference(ExternalReferenceType.SECURITY_ADVISORY, ["https://anyURI"], "MediaType", + "This is a comment") + assert external_reference.external_reference_type == ExternalReferenceType.SECURITY_ADVISORY + assert external_reference.locator == ["https://anyURI"] + assert external_reference.content_type == "MediaType" + assert external_reference.comment == "This is a comment" + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + ExternalReference("OTHER", "a URI", 34, True) + + assert err.value.args[0] == ['SetterError ExternalReference: type of argument "external_reference_type" ' + 'must be one of (spdx3.model.external_reference.ExternalReferenceType, ' + 'NoneType); got str instead: OTHER', + 'SetterError ExternalReference: type of argument "locator" must be a list; ' + 'got str instead: a URI', + 'SetterError ExternalReference: type of argument "content_type" must be one ' + 'of (str, NoneType); got int instead: 34', + 'SetterError ExternalReference: type of argument "comment" must be one of ' + '(str, NoneType); got bool instead: True'] From 2b5b23ade0f5406963db2473575858c35f93a983 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 17 Jan 2023 16:04:50 +0100 Subject: [PATCH 111/354] [spdx3.0] add external identifier type Signed-off-by: Meret Behrens --- src/spdx3/model/external_identifier.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/spdx3/model/external_identifier.py diff --git a/src/spdx3/model/external_identifier.py b/src/spdx3/model/external_identifier.py new file mode 100644 index 000000000..8993a9d93 --- /dev/null +++ b/src/spdx3/model/external_identifier.py @@ -0,0 +1,21 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from enum import Enum, auto + + +class ExternalIdentifierType(Enum): + CPE22 = auto() + CPE23 = auto() + GITOID = auto() + OTHER = auto() + PKG_URL = auto() + SWHID = auto() + SWID = auto() From 894dca715eb138b818f3fcb5db687e4a7643066a Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 17 Jan 2023 16:24:04 +0100 Subject: [PATCH 112/354] [fix] rewrite tests for incomplete initialization Signed-off-by: Meret Behrens --- tests/spdx3/model/test_creation_information.py | 12 ++++++------ tests/spdx3/model/test_spdx_document.py | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py index d1bc6db53..5e50cda5b 100644 --- a/tests/spdx3/model/test_creation_information.py +++ b/tests/spdx3/model/test_creation_information.py @@ -12,16 +12,16 @@ from unittest import mock import pytest +from semantic_version import Version from spdx3.model.creation_information import CreationInformation -@mock.patch("semantic_version.Version", autospec=True) -def test_correct_initialization(version): - creation_information = CreationInformation(version, datetime(2023, 1, 11, 16, 21), None, ["core", "software"], +def test_correct_initialization(): + creation_information = CreationInformation(Version("3.0.0"), datetime(2023, 1, 11, 16, 21), None, ["core", "software"], "CC0") - assert creation_information.spec_version == version + assert creation_information.spec_version == Version("3.0.0") assert creation_information.created == datetime(2023, 1, 11, 16, 21) assert creation_information.created_by is None assert creation_information.profile == ["core", "software"] @@ -46,5 +46,5 @@ def test_incomplete_initialization(): with pytest.raises(TypeError) as err: CreationInformation("2.3") - assert err.value.args[0] == ('CreationInformation.__init__() missing 3 required positional arguments: ' - "'created', 'created_by', and 'profile'") + assert "__init__() missing 3 required positional arguments: 'created', 'created_by', and 'profile'" in \ + err.value.args[0] diff --git a/tests/spdx3/model/test_spdx_document.py b/tests/spdx3/model/test_spdx_document.py index 02e2fdf7f..866163110 100644 --- a/tests/spdx3/model/test_spdx_document.py +++ b/tests/spdx3/model/test_spdx_document.py @@ -44,7 +44,7 @@ def test_invalid_initialization(): @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_incomplete_initialization(creation_information): with pytest.raises(TypeError) as err: - SpdxDocument("SPDXRef-Docuement", creation_information) + SpdxDocument("SPDXRef-Document", creation_information) - assert err.value.args[ - 0] == "SpdxDocument.__init__() missing 3 required positional arguments: 'name', 'elements', and 'root_elements'" + assert "__init__() missing 3 required positional arguments: 'name', 'elements', and 'root_elements'" in \ + err.value.args[0] From 2c45a7d1530fc3453c38716cb57c929af0ccf00b Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 18 Jan 2023 08:40:38 +0100 Subject: [PATCH 113/354] update README.md The current implementation is also aligned with the latest commit as there were only changes concerning AI (which is not implemented yet) and some renaming (mainly the suffixes "vocab" from vocabularies were deleted which was never added to the implementation of the prototype in first place). Signed-off-by: Meret Behrens --- src/spdx3/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx3/README.md b/src/spdx3/README.md index 0f1092d57..0fed300d0 100644 --- a/src/spdx3/README.md +++ b/src/spdx3/README.md @@ -1,2 +1,2 @@ -This implementation is mainly based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 2612c160d861fae53a3b44009ca0e1aa0fd6857f). +This implementation is mainly based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: d1d333acb93f8f1c7889dd156ffe5ee59b468d62). From 435dbaa52a055c4078a43e83d93e01d889320ddf Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 09:23:38 +0100 Subject: [PATCH 114/354] [issue-431] make Element, Artifact, SpdxCollection and IntegrityMethod abstract Signed-off-by: Meret Behrens --- src/spdx3/model/annotation.py | 1 - src/spdx3/model/artifact.py | 16 ++----- src/spdx3/model/bundle.py | 1 - src/spdx3/model/element.py | 15 ++---- src/spdx3/model/hash.py | 3 +- src/spdx3/model/integrity_method.py | 11 ++--- src/spdx3/model/relationship.py | 1 - src/spdx3/model/software/file.py | 2 +- src/spdx3/model/software/package.py | 2 +- src/spdx3/model/software/snippet.py | 2 +- src/spdx3/model/spdx_collection.py | 20 ++------ ...ity_method.py => test_abstract_classes.py} | 18 ++++--- tests/spdx3/model/test_artifact.py | 35 -------------- tests/spdx3/model/test_element.py | 34 ------------- tests/spdx3/model/test_spdx_collection.py | 48 ------------------- 15 files changed, 31 insertions(+), 178 deletions(-) rename tests/spdx3/model/{test_integrity_method.py => test_abstract_classes.py} (58%) delete mode 100644 tests/spdx3/model/test_artifact.py delete mode 100644 tests/spdx3/model/test_element.py delete mode 100644 tests/spdx3/model/test_spdx_collection.py diff --git a/src/spdx3/model/annotation.py b/src/spdx3/model/annotation.py index 2b4c3ba53..0914a03ec 100644 --- a/src/spdx3/model/annotation.py +++ b/src/spdx3/model/annotation.py @@ -31,7 +31,6 @@ class Annotation(Element): subject: List[Element] = field(default_factory=list) content_type: Optional[str] = None # placeholder for MediaType statement: Optional[str] = None - # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, annotation_type: AnnotationType, subject: List[Element], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, diff --git a/src/spdx3/model/artifact.py b/src/spdx3/model/artifact.py index eec85317e..e76a41f41 100644 --- a/src/spdx3/model/artifact.py +++ b/src/spdx3/model/artifact.py @@ -8,24 +8,16 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, List +from abc import abstractmethod from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.creation_information import CreationInformation from spdx3.model.element import Element -from spdx3.model.integrity_method import IntegrityMethod @dataclass_with_properties class Artifact(Element): - # This should be an abstract class and should not be instantiated directly. - # We need to investigate if we can combine dataclasses with abstract base classes (https://github.com/spdx/tools-python/issues/431) originated_by: None = None # placeholder for Actor - # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, originated_by: None = None): - check_types_and_set_values(self, locals()) + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx3/model/bundle.py b/src/spdx3/model/bundle.py index 5a2ea42c1..eef4e9db8 100644 --- a/src/spdx3/model/bundle.py +++ b/src/spdx3/model/bundle.py @@ -23,7 +23,6 @@ @dataclass_with_properties class Bundle(SpdxCollection): context: Optional[str] = None - # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index 33192349c..9ff65f678 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -8,10 +8,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from abc import ABC, abstractmethod from dataclasses import field from typing import Optional, List -from common.typing.type_checks import check_types_and_set_values from common.typing.dataclass_with_properties import dataclass_with_properties from spdx3.model.creation_information import CreationInformation @@ -19,9 +19,7 @@ @dataclass_with_properties -class Element: - # This should be an abstract class and should not be instantiated directly. - # We need to investigate if we can combine dataclasses with abstract base classes (https://github.com/spdx/tools-python/issues/431) +class Element(ABC): spdx_id: str # IRI creation_info: CreationInformation name: Optional[str] = None @@ -33,9 +31,6 @@ class Element: external_identifier: None = None # placeholder for ExternalIdentifier extension: None = None # placeholder for extension - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None): - verified_using = [] if verified_using is None else verified_using - check_types_and_set_values(self, locals()) + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx3/model/hash.py b/src/spdx3/model/hash.py index 90d56b8b3..0198f675f 100644 --- a/src/spdx3/model/hash.py +++ b/src/spdx3/model/hash.py @@ -15,6 +15,7 @@ from common.typing.type_checks import check_types_and_set_values from spdx3.model.integrity_method import IntegrityMethod + class HashAlgorithm(Enum): BLAKE2B256 = auto() BLAKE2B384 = auto() @@ -42,8 +43,6 @@ class HashAlgorithm(Enum): class Hash(IntegrityMethod): algorithm: HashAlgorithm = None hash_value: str = None - # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, algorithm: HashAlgorithm, hash_value: str, comment: Optional[str] = None): check_types_and_set_values(self, locals()) - diff --git a/src/spdx3/model/integrity_method.py b/src/spdx3/model/integrity_method.py index e9f50c521..eb52eb623 100644 --- a/src/spdx3/model/integrity_method.py +++ b/src/spdx3/model/integrity_method.py @@ -8,17 +8,16 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from abc import ABC, abstractmethod from typing import Optional from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values @dataclass_with_properties -class IntegrityMethod: - # This should be an abstract class and should not be instantiated directly. - # We need to investigate if we can combine dataclasses with abstract base classes (https://github.com/spdx/tools-python/issues/431) +class IntegrityMethod(ABC): comment: Optional[str] = None - def __init__(self, comment: Optional[str] = None): - check_types_and_set_values(self, locals()) + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx3/model/relationship.py b/src/spdx3/model/relationship.py index f46b73568..816d45662 100644 --- a/src/spdx3/model/relationship.py +++ b/src/spdx3/model/relationship.py @@ -76,7 +76,6 @@ class Relationship(Element): to: List[Element] = None relationship_type: RelationshipType = None completeness: Optional[RelationshipCompleteness] = None - # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, from_element: Element, to: List[Element], relationship_type: RelationshipType, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index b891d26c0..9e44fa5ec 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -24,7 +24,7 @@ class File(Artifact): content_identifier: Optional[str] = None # should be a valid URI file_purpose: Optional[List[SoftwarePurpose]] = None content_type: Optional[str] = None # placeholder for MediaType - # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 1ee366818..8af73a788 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -26,7 +26,7 @@ class Package(Artifact): download_location: Optional[str] = None # anyURI package_uri: Optional[str] = None # anyURI homepage: Optional[str] = None # anyURI - # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index ec1924cef..d6530e9e4 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -25,7 +25,7 @@ class Snippet(Artifact): snippet_purpose: Optional[List[SoftwarePurpose]] = None byte_range: Optional[Tuple[int, int]] = None line_range: Optional[Tuple[int, int]] = None - # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, external_references: None = None, external_identifier: None = None, diff --git a/src/spdx3/model/spdx_collection.py b/src/spdx3/model/spdx_collection.py index 3d5a23e0e..eb780b8b1 100644 --- a/src/spdx3/model/spdx_collection.py +++ b/src/spdx3/model/spdx_collection.py @@ -8,35 +8,25 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from abc import abstractmethod from dataclasses import field from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.creation_information import CreationInformation + from spdx3.model.element import Element from spdx3.model.external_map import ExternalMap -from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.namespace_map import NamespaceMap @dataclass_with_properties class SpdxCollection(Element): - # This should be an abstract class and should not be instantiated directly. - # We need to investigate if we can combine dataclasses with abstract base classes (https://github.com/spdx/tools-python/issues/431) # due to the inheritance we need to make all fields non-default in the __annotation__, the __init__ method still raises an error if required fields are not set elements: List[Element] = field(default_factory=list) root_elements: List[Element] = field(default_factory=list) namespaces: Optional[List[NamespaceMap]] = field(default_factory=list) imports: Optional[List[ExternalMap]] = field(default_factory=list) - # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). - def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], - root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None): - namespaces = [] if namespaces is None else namespaces - imports = [] if imports is None else imports - check_types_and_set_values(self, locals()) + @abstractmethod + def __init__(self): + pass diff --git a/tests/spdx3/model/test_integrity_method.py b/tests/spdx3/model/test_abstract_classes.py similarity index 58% rename from tests/spdx3/model/test_integrity_method.py rename to tests/spdx3/model/test_abstract_classes.py index c3d3c8fa4..1a854a553 100644 --- a/tests/spdx3/model/test_integrity_method.py +++ b/tests/spdx3/model/test_abstract_classes.py @@ -10,18 +10,16 @@ # limitations under the License. import pytest +from spdx3.model.artifact import Artifact +from spdx3.model.element import Element from spdx3.model.integrity_method import IntegrityMethod +from spdx3.model.spdx_collection import SpdxCollection -def test_correct_initialization(): - integrity_method = IntegrityMethod(comment="This is a comment.") - - assert integrity_method.comment == "This is a comment." - - -def test_invalid_initialization(): +@pytest.mark.parametrize("abstract_class", [Element, Artifact, SpdxCollection, IntegrityMethod]) +def test_initialization_throws_error(abstract_class): with pytest.raises(TypeError) as err: - IntegrityMethod(["some comments", "and some more comments"]) + abstract_class() - assert err.value.args[0] == ['SetterError IntegrityMethod: type of argument "comment" must be one of (str, ' - "NoneType); got list instead: ['some comments', 'and some more comments']"] + assert err.value.args[ + 0] == f"Can't instantiate abstract class {abstract_class.__name__} with abstract method __init__" diff --git a/tests/spdx3/model/test_artifact.py b/tests/spdx3/model/test_artifact.py deleted file mode 100644 index 533de4166..000000000 --- a/tests/spdx3/model/test_artifact.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from unittest import mock - -import pytest - -from spdx3.model.artifact import Artifact - - -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization(creation_info): - artifact = Artifact("SPDXRef-Artifact", creation_info, originated_by=None) - - assert artifact.spdx_id == "SPDXRef-Artifact" - assert artifact.creation_info == creation_info - assert artifact.originated_by is None - - -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization(creation_info): - with pytest.raises(TypeError) as err: - Artifact(65, creation_info, originated_by=54) - - assert err.value.args[0] == ['SetterError Artifact: type of argument "spdx_id" must be str; got int ' - 'instead: 65', - 'SetterError Artifact: type of argument "originated_by" must be NoneType; got ' - 'int instead: 54'] diff --git a/tests/spdx3/model/test_element.py b/tests/spdx3/model/test_element.py deleted file mode 100644 index a34e5d82f..000000000 --- a/tests/spdx3/model/test_element.py +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from unittest import mock - -import pytest - -from spdx3.model.element import Element - - -@mock.patch("spdx3.model.creation_information.CreationInformation") -def test_correct_initialization(creation_info): - element = Element("SPDXRef-Element", creation_info) - - assert element.spdx_id == "SPDXRef-Element" - assert element.creation_info == creation_info - - -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization(creation_info): - with pytest.raises(TypeError) as err: - Element(54, creation_info, name=76) - - assert err.value.args[0] == ['SetterError Element: type of argument "spdx_id" must be str; got int ' - 'instead: 54', - 'SetterError Element: type of argument "name" must be one of (str, NoneType); ' - 'got int instead: 76'] diff --git a/tests/spdx3/model/test_spdx_collection.py b/tests/spdx3/model/test_spdx_collection.py deleted file mode 100644 index ad6eaa978..000000000 --- a/tests/spdx3/model/test_spdx_collection.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from unittest import mock - -import pytest - -from spdx3.model.spdx_collection import SpdxCollection - - -@mock.patch("spdx3.model.external_map.ExternalMap", autospec=True) -@mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) -@mock.patch("spdx3.model.element.Element", autospec=True) -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization(creation_information, element, namespace_map, external_map): - spdx_collection = SpdxCollection("SPDXRef-Collection", creation_information, elements=[element], - root_elements=[element], namespaces=[namespace_map], imports=[external_map]) - - assert spdx_collection.spdx_id == "SPDXRef-Collection" - assert spdx_collection.creation_info == creation_information - assert spdx_collection.elements == [element] - assert spdx_collection.root_elements == [element] - assert spdx_collection.namespaces == [namespace_map] - assert spdx_collection.imports == [external_map] - - -@mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization(creation_information, namespace_map): - with pytest.raises(TypeError) as err: - SpdxCollection("SPDXRef-Collection", creation_information, elements=[None], root_elements=3, - namespaces=namespace_map, - imports=["ExternalMap"]) - - assert err.value.args[0] == ['SetterError SpdxCollection: type of argument "elements"[0] must be ' - 'spdx3.model.element.Element; got NoneType instead: [None]', - 'SetterError SpdxCollection: type of argument "root_elements" must be a list; ' - 'got int instead: 3', - 'SetterError SpdxCollection: type of argument "imports" must be one of ' - '(List[spdx3.model.external_map.ExternalMap], NoneType); got list instead: ' - "['ExternalMap']"] From 7a9acc660e81bc9f6e433281d3144daa132a2b6d Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 10:05:21 +0100 Subject: [PATCH 115/354] [fix] assert only part of the error message as the message differs for different python versions Signed-off-by: Meret Behrens --- tests/spdx3/model/test_abstract_classes.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/spdx3/model/test_abstract_classes.py b/tests/spdx3/model/test_abstract_classes.py index 1a854a553..fcdd4027b 100644 --- a/tests/spdx3/model/test_abstract_classes.py +++ b/tests/spdx3/model/test_abstract_classes.py @@ -21,5 +21,4 @@ def test_initialization_throws_error(abstract_class): with pytest.raises(TypeError) as err: abstract_class() - assert err.value.args[ - 0] == f"Can't instantiate abstract class {abstract_class.__name__} with abstract method __init__" + assert f"Can't instantiate abstract class {abstract_class.__name__}" in err.value.args[0] From 594ee430fc67f117de10283e2b84a1337a39fd99 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 11:27:37 +0100 Subject: [PATCH 116/354] [fix] update type hint for verified_using Signed-off-by: Meret Behrens --- src/spdx3/model/relationship.py | 11 +++++++---- src/spdx3/model/software/file.py | 12 +++++++----- src/spdx3/model/software/package.py | 18 ++++++++++-------- src/spdx3/model/software/sbom.py | 7 ++++--- src/spdx3/model/software/snippet.py | 9 +++++---- src/spdx3/model/spdx_document.py | 10 +++++----- 6 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/spdx3/model/relationship.py b/src/spdx3/model/relationship.py index 816d45662..2fa10d261 100644 --- a/src/spdx3/model/relationship.py +++ b/src/spdx3/model/relationship.py @@ -18,6 +18,7 @@ from spdx3.model.element import Element from common.typing.dataclass_with_properties import dataclass_with_properties +from spdx3.model.integrity_method import IntegrityMethod class RelationshipType(Enum): @@ -76,9 +77,11 @@ class Relationship(Element): to: List[Element] = None relationship_type: RelationshipType = None completeness: Optional[RelationshipCompleteness] = None + def __init__(self, spdx_id: str, creation_info: CreationInformation, from_element: Element, to: List[Element], - relationship_type: RelationshipType, name: Optional[str] = None, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, completeness: Optional[RelationshipCompleteness] = None): + relationship_type: RelationshipType, name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, + completeness: Optional[RelationshipCompleteness] = None): check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index 9e44fa5ec..d3a1c0b62 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -16,19 +16,21 @@ from common.typing.dataclass_with_properties import dataclass_with_properties from spdx3.model.artifact import Artifact +from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.software.software_purpose import SoftwarePurpose @dataclass_with_properties class File(Artifact): - content_identifier: Optional[str] = None # should be a valid URI + content_identifier: Optional[str] = None # should be a valid URI file_purpose: Optional[List[SoftwarePurpose]] = None - content_type: Optional[str] = None # placeholder for MediaType + content_type: Optional[str] = None # placeholder for MediaType def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, - file_purpose: Optional[SoftwarePurpose] = None, content_type: Optional[str] = None): + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, originated_by: None = None, + content_identifier: Optional[str] = None, file_purpose: Optional[SoftwarePurpose] = None, + content_type: Optional[str] = None): file_purpose = [] if file_purpose is None else file_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 8af73a788..1591f5169 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -16,22 +16,24 @@ from common.typing.dataclass_with_properties import dataclass_with_properties from spdx3.model.artifact import Artifact +from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.software.software_purpose import SoftwarePurpose @dataclass_with_properties class Package(Artifact): - content_identifier: Optional[str] = None # anyURI + content_identifier: Optional[str] = None # anyURI package_purpose: Optional[List[SoftwarePurpose]] = None - download_location: Optional[str] = None # anyURI - package_uri: Optional[str] = None # anyURI - homepage: Optional[str] = None # anyURI + download_location: Optional[str] = None # anyURI + package_uri: Optional[str] = None # anyURI + homepage: Optional[str] = None # anyURI def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, - package_purpose: Optional[List[SoftwarePurpose]] = None, download_location: Optional[str] = None, - package_uri: Optional[str] = None, homepage: Optional[str] = None): + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, originated_by: None = None, + content_identifier: Optional[str] = None, package_purpose: Optional[List[SoftwarePurpose]] = None, + download_location: Optional[str] = None, package_uri: Optional[str] = None, + homepage: Optional[str] = None): package_purpose = [] if package_purpose is None else package_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index 15ef629e5..6cfda60ea 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -18,6 +18,7 @@ from spdx3.model.element import Element from spdx3.model.bom import Bom from spdx3.model.external_map import ExternalMap +from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.namespace_map import NamespaceMap @@ -26,9 +27,9 @@ class Sbom(Bom): # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, verified_using: None = None, - external_references: None = None, external_identifier: None = None, extension: None = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): check_types_and_set_values(self, locals()) - diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index d6530e9e4..dc076298d 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -15,6 +15,7 @@ from spdx3.model.creation_information import CreationInformation from common.typing.dataclass_with_properties import dataclass_with_properties +from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.software.software_purpose import SoftwarePurpose from spdx3.model.artifact import Artifact @@ -28,9 +29,9 @@ class Snippet(Artifact): def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: None = None, external_references: None = None, external_identifier: None = None, - extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, - snippet_purpose: Optional[List[SoftwarePurpose]] = None, byte_range: Optional[Tuple[int, int]] = None, - line_range: Optional[Tuple[int, int]] = None): + verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, + external_identifier: None = None, extension: None = None, originated_by: None = None, + content_identifier: Optional[str] = None, snippet_purpose: Optional[List[SoftwarePurpose]] = None, + byte_range: Optional[Tuple[int, int]] = None, line_range: Optional[Tuple[int, int]] = None): snippet_purpose = [] if snippet_purpose is None else snippet_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index d1537d41c..2e055fedd 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -18,6 +18,7 @@ from spdx3.model.element import Element from spdx3.model.bundle import Bundle from spdx3.model.external_map import ExternalMap +from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.namespace_map import NamespaceMap @@ -27,9 +28,8 @@ class SpdxDocument(Bundle): # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, elements: List[Element], root_elements: List[Element], summary: Optional[str] = None, description: Optional[str] = None, - comment: Optional[str] = None, verified_using: None = None, external_references: None = None, - external_identifier: None = None, extension: None = None, namespace: Optional[NamespaceMap] = None, - imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): - + comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, + external_references: None = None, external_identifier: None = None, extension: None = None, + namespace: Optional[NamespaceMap] = None, imports: Optional[List[ExternalMap]] = None, + context: Optional[str] = None): check_types_and_set_values(self, locals()) - From b23a2617b5b310f226e5d4d76a5bc1681aff0e7e Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 11:35:49 +0100 Subject: [PATCH 117/354] [spdx3.0] set optional lists to empty lists per default Signed-off-by: Meret Behrens --- src/spdx3/model/annotation.py | 1 + src/spdx3/model/bom.py | 3 +++ src/spdx3/model/bundle.py | 3 +++ src/spdx3/model/relationship.py | 1 + src/spdx3/model/software/file.py | 3 ++- src/spdx3/model/software/package.py | 1 + src/spdx3/model/software/sbom.py | 3 +++ src/spdx3/model/software/snippet.py | 1 + src/spdx3/model/spdx_document.py | 5 ++++- tests/spdx3/model/software/test_file.py | 2 +- 10 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/spdx3/model/annotation.py b/src/spdx3/model/annotation.py index 0914a03ec..a0403ea19 100644 --- a/src/spdx3/model/annotation.py +++ b/src/spdx3/model/annotation.py @@ -37,4 +37,5 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, annotation_ verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, external_identifier: None = None, extension: None = None, content_type: Optional[str] = None, statement: Optional[str] = None): + verified_using = [] if verified_using is None else verified_using check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/bom.py b/src/spdx3/model/bom.py index 506b2c08e..f6986306d 100644 --- a/src/spdx3/model/bom.py +++ b/src/spdx3/model/bom.py @@ -31,4 +31,7 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: L external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + verified_using = [] if verified_using is None else verified_using + namespaces = [] if namespaces is None else namespaces + imports = [] if imports is None else imports check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/bundle.py b/src/spdx3/model/bundle.py index eef4e9db8..1f1761a96 100644 --- a/src/spdx3/model/bundle.py +++ b/src/spdx3/model/bundle.py @@ -31,4 +31,7 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: L external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + verified_using = [] if verified_using is None else verified_using + namespaces = [] if namespaces is None else namespaces + imports = [] if imports is None else imports check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/relationship.py b/src/spdx3/model/relationship.py index 2fa10d261..5a9349d6b 100644 --- a/src/spdx3/model/relationship.py +++ b/src/spdx3/model/relationship.py @@ -84,4 +84,5 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, from_elemen verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, external_identifier: None = None, extension: None = None, completeness: Optional[RelationshipCompleteness] = None): + verified_using = [] if verified_using is None else verified_using check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index d3a1c0b62..ac2442c17 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -30,7 +30,8 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, external_identifier: None = None, extension: None = None, originated_by: None = None, - content_identifier: Optional[str] = None, file_purpose: Optional[SoftwarePurpose] = None, + content_identifier: Optional[str] = None, file_purpose: Optional[List[SoftwarePurpose]] = None, content_type: Optional[str] = None): + verified_using = [] if verified_using is None else verified_using file_purpose = [] if file_purpose is None else file_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 1591f5169..0e883cb05 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -35,5 +35,6 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio content_identifier: Optional[str] = None, package_purpose: Optional[List[SoftwarePurpose]] = None, download_location: Optional[str] = None, package_uri: Optional[str] = None, homepage: Optional[str] = None): + verified_using = [] if verified_using is None else verified_using package_purpose = [] if package_purpose is None else package_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index 6cfda60ea..060ec2b35 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -32,4 +32,7 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: L external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + verified_using = [] if verified_using is None else verified_using + namespaces = [] if namespaces is None else namespaces + imports = [] if imports is None else imports check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index dc076298d..13591d5ed 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -33,5 +33,6 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio external_identifier: None = None, extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, snippet_purpose: Optional[List[SoftwarePurpose]] = None, byte_range: Optional[Tuple[int, int]] = None, line_range: Optional[Tuple[int, int]] = None): + verified_using = [] if verified_using is None else verified_using snippet_purpose = [] if snippet_purpose is None else snippet_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index 2e055fedd..3221cbaa1 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -30,6 +30,9 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, root_elements: List[Element], summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, external_identifier: None = None, extension: None = None, - namespace: Optional[NamespaceMap] = None, imports: Optional[List[ExternalMap]] = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + verified_using = [] if verified_using is None else verified_using + namespaces = [] if namespaces is None else namespaces + imports = [] if imports is None else imports check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index 47c4dce13..77bf568eb 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -19,7 +19,7 @@ @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): - file = File("SPDXRef-File", creation_information, content_identifier="https://any.uri", + file = File("SPDXRef-File", creation_information, verified_using=None, content_identifier="https://any.uri", file_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE], content_type="MediaType") assert file.spdx_id == "SPDXRef-File" From f4ce8731442f4c10a6c076588f853b9baed9785f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 19 Jan 2023 12:22:56 +0100 Subject: [PATCH 118/354] add SpdxIdMap to easily collect and reference all elements in the data model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/spdx_id_map.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/spdx3/spdx_id_map.py diff --git a/src/spdx3/spdx_id_map.py b/src/spdx3/spdx_id_map.py new file mode 100644 index 000000000..0a17f86bd --- /dev/null +++ b/src/spdx3/spdx_id_map.py @@ -0,0 +1,29 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Dict + +from spdx3.model.element import Element + + +class SpdxIdMap: + _spdx_id_map: Dict[str, Element] + + def __init__(self, spdx_id_map: Dict[str, Element] = None): + self._spdx_id_map = spdx_id_map if spdx_id_map else {} + + def add_element(self, element: Element): + self._spdx_id_map[element.spdx_id] = element + + def get_element(self, spdx_id: str) -> Element: + return self._spdx_id_map[spdx_id] + + def get_full_map(self) -> Dict[str, Element]: + return self._spdx_id_map From 9cdcf2eceea48b491753a2069fcceec956965520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 19 Jan 2023 12:36:06 +0100 Subject: [PATCH 119/354] replace Element references with str/spdx_ids MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/model/annotation.py | 4 ++-- src/spdx3/model/bom.py | 4 ++-- src/spdx3/model/bundle.py | 4 ++-- src/spdx3/model/relationship.py | 6 +++--- src/spdx3/model/software/sbom.py | 4 ++-- src/spdx3/model/spdx_collection.py | 4 ++-- src/spdx3/model/spdx_document.py | 4 ++-- src/spdx3/spdx_id_map.py | 20 ++++++++++---------- tests/spdx3/model/software/test_sbom.py | 9 ++++----- tests/spdx3/model/test_annotation.py | 7 +++---- tests/spdx3/model/test_bom.py | 11 +++++------ tests/spdx3/model/test_bundle.py | 21 +++++++++++---------- tests/spdx3/model/test_relationship.py | 13 ++++++------- tests/spdx3/model/test_spdx_document.py | 13 ++++++------- 14 files changed, 60 insertions(+), 64 deletions(-) diff --git a/src/spdx3/model/annotation.py b/src/spdx3/model/annotation.py index a0403ea19..e806d83e1 100644 --- a/src/spdx3/model/annotation.py +++ b/src/spdx3/model/annotation.py @@ -28,11 +28,11 @@ class AnnotationType(Enum): @dataclass_with_properties class Annotation(Element): annotation_type: AnnotationType = None - subject: List[Element] = field(default_factory=list) + subject: List[str] = field(default_factory=list) content_type: Optional[str] = None # placeholder for MediaType statement: Optional[str] = None def __init__(self, spdx_id: str, creation_info: CreationInformation, annotation_type: AnnotationType, - subject: List[Element], name: Optional[str] = None, summary: Optional[str] = None, + subject: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, external_identifier: None = None, extension: None = None, content_type: Optional[str] = None, diff --git a/src/spdx3/model/bom.py b/src/spdx3/model/bom.py index f6986306d..23d8cb801 100644 --- a/src/spdx3/model/bom.py +++ b/src/spdx3/model/bom.py @@ -24,8 +24,8 @@ class Bom(Bundle): # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). - def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], - root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[str], + root_elements: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, external_identifier: None = None, extension: None = None, diff --git a/src/spdx3/model/bundle.py b/src/spdx3/model/bundle.py index 1f1761a96..dd6ef3556 100644 --- a/src/spdx3/model/bundle.py +++ b/src/spdx3/model/bundle.py @@ -24,8 +24,8 @@ class Bundle(SpdxCollection): context: Optional[str] = None - def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], - root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[str], + root_elements: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, external_identifier: None = None, extension: None = None, diff --git a/src/spdx3/model/relationship.py b/src/spdx3/model/relationship.py index 5a9349d6b..80d679ca5 100644 --- a/src/spdx3/model/relationship.py +++ b/src/spdx3/model/relationship.py @@ -73,12 +73,12 @@ class RelationshipCompleteness(Enum): @dataclass_with_properties class Relationship(Element): # due to the inheritance we need to make all fields non-default in the __annotation__, the __init__ method still raises an error if required fields are not set - from_element: Element = None - to: List[Element] = None + from_element: str = None + to: List[str] = None relationship_type: RelationshipType = None completeness: Optional[RelationshipCompleteness] = None - def __init__(self, spdx_id: str, creation_info: CreationInformation, from_element: Element, to: List[Element], + def __init__(self, spdx_id: str, creation_info: CreationInformation, from_element: str, to: List[str], relationship_type: RelationshipType, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index 060ec2b35..5b287a5c9 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -25,8 +25,8 @@ @dataclass_with_properties class Sbom(Bom): # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). - def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[Element], - root_elements: List[Element], name: Optional[str] = None, summary: Optional[str] = None, + def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[str], + root_elements: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, external_identifier: None = None, extension: None = None, diff --git a/src/spdx3/model/spdx_collection.py b/src/spdx3/model/spdx_collection.py index eb780b8b1..caaf497fb 100644 --- a/src/spdx3/model/spdx_collection.py +++ b/src/spdx3/model/spdx_collection.py @@ -22,8 +22,8 @@ @dataclass_with_properties class SpdxCollection(Element): # due to the inheritance we need to make all fields non-default in the __annotation__, the __init__ method still raises an error if required fields are not set - elements: List[Element] = field(default_factory=list) - root_elements: List[Element] = field(default_factory=list) + elements: List[str] = field(default_factory=list) + root_elements: List[str] = field(default_factory=list) namespaces: Optional[List[NamespaceMap]] = field(default_factory=list) imports: Optional[List[ExternalMap]] = field(default_factory=list) diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index 3221cbaa1..54ddd1a69 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -26,8 +26,8 @@ class SpdxDocument(Bundle): # The inherited field "name" is required for a SpdxDocument, no longer optional. # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, elements: List[Element], - root_elements: List[Element], summary: Optional[str] = None, description: Optional[str] = None, + def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, elements: List[str], + root_elements: List[str], summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, diff --git a/src/spdx3/spdx_id_map.py b/src/spdx3/spdx_id_map.py index 0a17f86bd..66e9ae9ab 100644 --- a/src/spdx3/spdx_id_map.py +++ b/src/spdx3/spdx_id_map.py @@ -1,13 +1,13 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from typing import Dict from spdx3.model.element import Element diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index f03c30d00..f3d64a4a2 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -15,15 +15,14 @@ from spdx3.model.software.sbom import Sbom -@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization(creation_information, element): - sbom = Sbom("SPDXRef-Sbom", creation_information, elements=[element, element], root_elements=[element]) +def test_correct_initialization(creation_information): + sbom = Sbom("SPDXRef-Sbom", creation_information, elements=["spdx_id1", "spdx_id2"], root_elements=["spdx_id3"]) assert sbom.spdx_id == "SPDXRef-Sbom" assert sbom.creation_info == creation_information - assert sbom.elements == [element, element] - assert sbom.root_elements == [element] + assert sbom.elements == ["spdx_id1", "spdx_id2"] + assert sbom.root_elements == ["spdx_id3"] def test_invalid_initialization(): with pytest.raises(TypeError) as err: diff --git a/tests/spdx3/model/test_annotation.py b/tests/spdx3/model/test_annotation.py index beaf1a27c..97c618767 100644 --- a/tests/spdx3/model/test_annotation.py +++ b/tests/spdx3/model/test_annotation.py @@ -15,16 +15,15 @@ from spdx3.model.annotation import Annotation, AnnotationType -@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization(creation_information, element): - annotation = Annotation("SPDXRef-Annotation", creation_information, AnnotationType.OTHER, [element], +def test_correct_initialization(creation_information): + annotation = Annotation("SPDXRef-Annotation", creation_information, AnnotationType.OTHER, ["spdx_id1"], content_type="mediaType", statement="This is a statement") assert annotation.spdx_id == "SPDXRef-Annotation" assert annotation.creation_info == creation_information assert annotation.annotation_type == AnnotationType.OTHER - assert annotation.subject == [element] + assert annotation.subject == ["spdx_id1"] assert annotation.content_type == "mediaType" assert annotation.statement == "This is a statement" diff --git a/tests/spdx3/model/test_bom.py b/tests/spdx3/model/test_bom.py index 5311a1c81..e3b38448a 100644 --- a/tests/spdx3/model/test_bom.py +++ b/tests/spdx3/model/test_bom.py @@ -16,15 +16,14 @@ from spdx3.model.bom import Bom -@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization(creation_information, element): - bom = Bom("SPDXRef-Bom", creation_information, elements=[element], root_elements=[element]) +def test_correct_initialization(creation_information): + bom = Bom("SPDXRef-Bom", creation_information, elements=["spdx_id1"], root_elements=["spdx_id2"]) assert bom.spdx_id == "SPDXRef-Bom" assert bom.creation_info == creation_information - assert bom.elements == [element] - assert bom.root_elements == [element] + assert bom.elements == ["spdx_id1"] + assert bom.root_elements == ["spdx_id2"] def test_invalid_initialization(): @@ -36,4 +35,4 @@ def test_invalid_initialization(): 'spdx3.model.creation_information.CreationInformation; got str instead: ' 'Creation Information', 'SetterError Bom: type of argument "elements"[0] must be ' - 'spdx3.model.element.Element; got int instead: [5]'] + 'str; got int instead: [5]'] diff --git a/tests/spdx3/model/test_bundle.py b/tests/spdx3/model/test_bundle.py index 78ac27eec..ec33d2627 100644 --- a/tests/spdx3/model/test_bundle.py +++ b/tests/spdx3/model/test_bundle.py @@ -16,28 +16,29 @@ @mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) -@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization(creation_information, element, namespace): - bundle = Bundle("SPDXRef-Bundle", creation_information, elements=[element], root_elements=[element], +def test_correct_initialization(creation_information, namespace): + bundle = Bundle("SPDXRef-Bundle", creation_information, elements=["spdx_id1"], root_elements=["spdx_id2"], namespaces=[namespace], context="context") assert bundle.spdx_id == "SPDXRef-Bundle" assert bundle.creation_info == creation_information - assert bundle.elements == [element] - assert bundle.root_elements == [element] + assert bundle.elements == ["spdx_id1"] + assert bundle.root_elements == ["spdx_id2"] assert bundle.context == "context" assert bundle.namespaces == [namespace] -@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_invalid_initialization(creation_information, element): +def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: - Bundle(4, creation_information, elements=[element], root_elements=[element], namespaces=True, context=["yes"]) + Bundle(4, creation_information, elements="spdx_id1", root_elements=[42], namespaces=True, context=["yes"]) - assert err.value.args[0] == ['SetterError Bundle: type of argument "spdx_id" must be str; got int instead: ' - '4', + assert err.value.args[0] == ['SetterError Bundle: type of argument "spdx_id" must be str; got int instead: 4', + 'SetterError Bundle: type of argument "elements" must be a list; got str ' + 'instead: spdx_id1', + 'SetterError Bundle: type of argument "root_elements"[0] must be str; got int ' + 'instead: [42]', 'SetterError Bundle: type of argument "namespaces" must be one of ' '(List[spdx3.model.namespace_map.NamespaceMap], NoneType); got bool instead: True', 'SetterError Bundle: type of argument "context" must be one of (str, ' diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py index d35555468..5eed1bd3e 100644 --- a/tests/spdx3/model/test_relationship.py +++ b/tests/spdx3/model/test_relationship.py @@ -15,16 +15,15 @@ from spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness -@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization(creation_information, element): - relationship = Relationship("SPDXRef-Relationship", creation_information, element, [element, element], +def test_correct_initialization(creation_information): + relationship = Relationship("SPDXRef-Relationship", creation_information, "spdx_id1", ["spdx_id2", "spdx_id3"], RelationshipType.DESCRIBES, completeness=RelationshipCompleteness.UNKNOWN) assert relationship.spdx_id == "SPDXRef-Relationship" assert relationship.creation_info == creation_information - assert relationship.from_element == element - assert relationship.to == [element, element] + assert relationship.from_element == "spdx_id1" + assert relationship.to == ["spdx_id2", "spdx_id3"] assert relationship.relationship_type == RelationshipType.DESCRIBES assert relationship.completeness == RelationshipCompleteness.UNKNOWN @@ -32,10 +31,10 @@ def test_correct_initialization(creation_information, element): @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: - Relationship("SPDXRef-Relationship", creation_information, "Element", 5, "Relationshiptype", completeness=True) + Relationship("SPDXRef-Relationship", creation_information, 42, 5, "Relationshiptype", completeness=True) assert err.value.args[0] == ['SetterError Relationship: type of argument "from_element" must be ' - 'spdx3.model.element.Element; got str instead: Element', + 'str; got int instead: 42', 'SetterError Relationship: type of argument "to" must be a list; got int ' 'instead: 5', 'SetterError Relationship: type of argument "relationship_type" must be ' diff --git a/tests/spdx3/model/test_spdx_document.py b/tests/spdx3/model/test_spdx_document.py index 866163110..f4d260bf0 100644 --- a/tests/spdx3/model/test_spdx_document.py +++ b/tests/spdx3/model/test_spdx_document.py @@ -15,17 +15,16 @@ from spdx3.model.spdx_document import SpdxDocument -@mock.patch("spdx3.model.element.Element", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_correct_initialization(creation_information, element): - spdx_document = SpdxDocument("SPDXRef-DOCUMENT", creation_information, "Test document", elements=[element], - root_elements=[element]) +def test_correct_initialization(creation_information): + spdx_document = SpdxDocument("SPDXRef-DOCUMENT", creation_information, "Test document", elements=["spdx_id1"], + root_elements=["spdx_id2"]) assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" assert spdx_document.creation_info == creation_information assert spdx_document.name == "Test document" - assert spdx_document.elements == [element] - assert spdx_document.root_elements == [element] + assert spdx_document.elements == ["spdx_id1"] + assert spdx_document.root_elements == ["spdx_id2"] def test_invalid_initialization(): @@ -38,7 +37,7 @@ def test_invalid_initialization(): 'spdx3.model.creation_information.CreationInformation; got dict instead: ' "{'info': 5}", 'SetterError SpdxDocument: type of argument "elements"[0] must be ' - 'spdx3.model.element.Element; got int instead: [8]'] + 'str; got int instead: [8]'] @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) From ecf9655acac7e433b58049eb00c53ea02ea3020b Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 13:44:05 +0100 Subject: [PATCH 120/354] [spdx3.0] correct type hint for external_references and set empty list per default Signed-off-by: Meret Behrens --- src/spdx3/model/annotation.py | 14 ++++++++++---- src/spdx3/model/bom.py | 11 +++++++---- src/spdx3/model/bundle.py | 11 +++++++---- src/spdx3/model/element.py | 4 +++- src/spdx3/model/software/file.py | 11 +++++++---- src/spdx3/model/software/package.py | 13 ++++++++----- src/spdx3/model/software/sbom.py | 11 +++++++---- src/spdx3/model/software/snippet.py | 12 ++++++++---- src/spdx3/model/spdx_document.py | 5 ++++- 9 files changed, 61 insertions(+), 31 deletions(-) diff --git a/src/spdx3/model/annotation.py b/src/spdx3/model/annotation.py index e806d83e1..ae3db1d50 100644 --- a/src/spdx3/model/annotation.py +++ b/src/spdx3/model/annotation.py @@ -12,6 +12,8 @@ from enum import Enum, auto from typing import Optional, List +from spdx3.model.external_reference import ExternalReference + from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -21,21 +23,25 @@ from spdx3.model.element import Element + class AnnotationType(Enum): REVIEW = auto() OTHER = auto() + @dataclass_with_properties class Annotation(Element): annotation_type: AnnotationType = None subject: List[str] = field(default_factory=list) - content_type: Optional[str] = None # placeholder for MediaType + content_type: Optional[str] = None # placeholder for MediaType statement: Optional[str] = None + def __init__(self, spdx_id: str, creation_info: CreationInformation, annotation_type: AnnotationType, subject: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, content_type: Optional[str] = None, - statement: Optional[str] = None): + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, + extension: None = None, content_type: Optional[str] = None, statement: Optional[str] = None): verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/bom.py b/src/spdx3/model/bom.py index 23d8cb801..a5eacfb63 100644 --- a/src/spdx3/model/bom.py +++ b/src/spdx3/model/bom.py @@ -10,6 +10,8 @@ # limitations under the License. from typing import List, Optional +from spdx3.model.external_reference import ExternalReference + from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values from spdx3.model.creation_information import CreationInformation @@ -27,11 +29,12 @@ class Bom(Bundle): def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[str], root_elements: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, - context: Optional[str] = None): + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, + extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, + imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/bundle.py b/src/spdx3/model/bundle.py index dd6ef3556..b11e35e0e 100644 --- a/src/spdx3/model/bundle.py +++ b/src/spdx3/model/bundle.py @@ -10,6 +10,8 @@ # limitations under the License. from typing import Optional, List +from spdx3.model.external_reference import ExternalReference + from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values from spdx3.model.creation_information import CreationInformation @@ -27,11 +29,12 @@ class Bundle(SpdxCollection): def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[str], root_elements: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, - context: Optional[str] = None): + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, + extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, + imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index 9ff65f678..489fe7490 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -12,6 +12,8 @@ from dataclasses import field from typing import Optional, List +from spdx3.model.external_reference import ExternalReference + from common.typing.dataclass_with_properties import dataclass_with_properties from spdx3.model.creation_information import CreationInformation @@ -27,7 +29,7 @@ class Element(ABC): description: Optional[str] = None comment: Optional[str] = None verified_using: Optional[List[IntegrityMethod]] = field(default_factory=list) - external_references: None = None # placeholder for ExternalReference + external_references: Optional[List[ExternalReference]] = field(default_factory=list) external_identifier: None = None # placeholder for ExternalIdentifier extension: None = None # placeholder for extension diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index ac2442c17..1705024b5 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -10,6 +10,8 @@ # limitations under the License. from typing import Optional, List +from spdx3.model.external_reference import ExternalReference + from common.typing.type_checks import check_types_and_set_values from spdx3.model.creation_information import CreationInformation @@ -28,10 +30,11 @@ class File(Artifact): def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, originated_by: None = None, - content_identifier: Optional[str] = None, file_purpose: Optional[List[SoftwarePurpose]] = None, - content_type: Optional[str] = None): + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, + extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, + file_purpose: Optional[List[SoftwarePurpose]] = None, content_type: Optional[str] = None): verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references file_purpose = [] if file_purpose is None else file_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 0e883cb05..7263a9817 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -10,6 +10,8 @@ # limitations under the License. from typing import Optional, List +from spdx3.model.external_reference import ExternalReference + from spdx3.model.creation_information import CreationInformation from common.typing.type_checks import check_types_and_set_values @@ -30,11 +32,12 @@ class Package(Artifact): def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, originated_by: None = None, - content_identifier: Optional[str] = None, package_purpose: Optional[List[SoftwarePurpose]] = None, - download_location: Optional[str] = None, package_uri: Optional[str] = None, - homepage: Optional[str] = None): + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, + extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, + package_purpose: Optional[List[SoftwarePurpose]] = None, download_location: Optional[str] = None, + package_uri: Optional[str] = None, homepage: Optional[str] = None): verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references package_purpose = [] if package_purpose is None else package_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index 5b287a5c9..1bb4657fa 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -10,6 +10,8 @@ # limitations under the License. from typing import Optional, List +from spdx3.model.external_reference import ExternalReference + from common.typing.type_checks import check_types_and_set_values from spdx3.model.creation_information import CreationInformation @@ -28,11 +30,12 @@ class Sbom(Bom): def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[str], root_elements: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, - context: Optional[str] = None): + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, + extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, + imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index 13591d5ed..da902bb5e 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -10,6 +10,8 @@ # limitations under the License. from typing import Optional, Tuple, List +from spdx3.model.external_reference import ExternalReference + from common.typing.type_checks import check_types_and_set_values from spdx3.model.creation_information import CreationInformation @@ -29,10 +31,12 @@ class Snippet(Artifact): def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, originated_by: None = None, - content_identifier: Optional[str] = None, snippet_purpose: Optional[List[SoftwarePurpose]] = None, - byte_range: Optional[Tuple[int, int]] = None, line_range: Optional[Tuple[int, int]] = None): + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, + extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, + snippet_purpose: Optional[List[SoftwarePurpose]] = None, byte_range: Optional[Tuple[int, int]] = None, + line_range: Optional[Tuple[int, int]] = None): verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references snippet_purpose = [] if snippet_purpose is None else snippet_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index 54ddd1a69..1394f3ed2 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -10,6 +10,8 @@ # limitations under the License. from typing import Optional, List +from spdx3.model.external_reference import ExternalReference + from common.typing.type_checks import check_types_and_set_values from spdx3.model.creation_information import CreationInformation @@ -29,10 +31,11 @@ class SpdxDocument(Bundle): def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, elements: List[str], root_elements: List[str], summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, - external_references: None = None, external_identifier: None = None, extension: None = None, + external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports check_types_and_set_values(self, locals()) From 76ce527d1dbdab36d92ce169a18bb4bd35afce79 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 14:09:14 +0100 Subject: [PATCH 121/354] [spdx3.0] add writer for classes in core profile Signed-off-by: Meret Behrens --- src/spdx3/writer/console/__init__.py | 2 + src/spdx3/writer/console/annotation_writer.py | 25 ++++++++++++ src/spdx3/writer/console/artifact_writer.py | 20 ++++++++++ src/spdx3/writer/console/bom_writer.py | 20 ++++++++++ src/spdx3/writer/console/bundle_writer.py | 22 +++++++++++ src/spdx3/writer/console/console.py | 21 ++++++++++ .../console/creation_information_writer.py | 24 ++++++++++++ src/spdx3/writer/console/element_writer.py | 39 +++++++++++++++++++ .../writer/console/external_map_writer.py | 26 +++++++++++++ .../console/external_reference_writer.py | 22 +++++++++++ src/spdx3/writer/console/hash_writer.py | 23 +++++++++++ .../writer/console/integrity_method_writer.py | 18 +++++++++ .../writer/console/namespace_map_writer.py | 19 +++++++++ .../writer/console/relationship_writer.py | 22 +++++++++++ .../writer/console/spdx_collection_writer.py | 28 +++++++++++++ .../writer/console/spdx_document_writer.py | 19 +++++++++ 16 files changed, 350 insertions(+) create mode 100644 src/spdx3/writer/console/__init__.py create mode 100644 src/spdx3/writer/console/annotation_writer.py create mode 100644 src/spdx3/writer/console/artifact_writer.py create mode 100644 src/spdx3/writer/console/bom_writer.py create mode 100644 src/spdx3/writer/console/bundle_writer.py create mode 100644 src/spdx3/writer/console/console.py create mode 100644 src/spdx3/writer/console/creation_information_writer.py create mode 100644 src/spdx3/writer/console/element_writer.py create mode 100644 src/spdx3/writer/console/external_map_writer.py create mode 100644 src/spdx3/writer/console/external_reference_writer.py create mode 100644 src/spdx3/writer/console/hash_writer.py create mode 100644 src/spdx3/writer/console/integrity_method_writer.py create mode 100644 src/spdx3/writer/console/namespace_map_writer.py create mode 100644 src/spdx3/writer/console/relationship_writer.py create mode 100644 src/spdx3/writer/console/spdx_collection_writer.py create mode 100644 src/spdx3/writer/console/spdx_document_writer.py diff --git a/src/spdx3/writer/console/__init__.py b/src/spdx3/writer/console/__init__.py new file mode 100644 index 000000000..c2d090abc --- /dev/null +++ b/src/spdx3/writer/console/__init__.py @@ -0,0 +1,2 @@ +""" This is a temporary package to write the implemented model of spdx3.0 to console. As soon as serialization formats + are properly defined this package can be deleted.""" diff --git a/src/spdx3/writer/console/annotation_writer.py b/src/spdx3/writer/console/annotation_writer.py new file mode 100644 index 000000000..7caa9c968 --- /dev/null +++ b/src/spdx3/writer/console/annotation_writer.py @@ -0,0 +1,25 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.writer.console.console import write_value +from spdx3.writer.console.element_writer import write_element_properties + +from spdx3.model.annotation import Annotation + + +def write_annotation(annotation: Annotation, text_output: TextIO): + text_output.write("## Annotation\n") + write_element_properties(annotation, text_output) + write_value("annotation_type", annotation.annotation_type.name, text_output) + text_output.write(f"# subjects: {', '.join(annotation.subject)}") + write_value("content_type", annotation.content_type, text_output) + write_value("statement", annotation.statement, text_output) diff --git a/src/spdx3/writer/console/artifact_writer.py b/src/spdx3/writer/console/artifact_writer.py new file mode 100644 index 000000000..a0bd27f76 --- /dev/null +++ b/src/spdx3/writer/console/artifact_writer.py @@ -0,0 +1,20 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.writer.console.element_writer import write_element_properties + +from spdx3.model.artifact import Artifact + + +def write_artifact_properties(artifact: Artifact, text_output: TextIO): + write_element_properties(artifact, text_output) + # write_value("originated_by", artifact.originated_by) not implemented yet diff --git a/src/spdx3/writer/console/bom_writer.py b/src/spdx3/writer/console/bom_writer.py new file mode 100644 index 000000000..4da6dcfbf --- /dev/null +++ b/src/spdx3/writer/console/bom_writer.py @@ -0,0 +1,20 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.bom import Bom +from spdx3.writer.console.bundle_writer import write_bundle + + +def write_bom(bom: Bom, text_output: TextIO, heading: bool = True): + if heading: + text_output.write("## Bom\n") + write_bundle(bom, text_output, False) diff --git a/src/spdx3/writer/console/bundle_writer.py b/src/spdx3/writer/console/bundle_writer.py new file mode 100644 index 000000000..35a7faf59 --- /dev/null +++ b/src/spdx3/writer/console/bundle_writer.py @@ -0,0 +1,22 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.bundle import Bundle +from spdx3.writer.console.console import write_value +from spdx3.writer.console.spdx_collection_writer import write_collection + + +def write_bundle(bundle: Bundle, text_output: TextIO, heading: bool = True): + if heading: + text_output.write("## Bundle\n") + write_collection(bundle, text_output) + write_value("context", bundle.context, text_output) diff --git a/src/spdx3/writer/console/console.py b/src/spdx3/writer/console/console.py new file mode 100644 index 000000000..5ea74e3e0 --- /dev/null +++ b/src/spdx3/writer/console/console.py @@ -0,0 +1,21 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import TextIO, Union, Optional + + +def write_value(tag: str, value: Optional[Union[bool, str]], out: TextIO): + """ This function is duplicated from spdx.writer.tagvalue.tag_value_writer_helper_functions and slightly adapted to + make indentation of output possible.""" + if not value: + return + else: + out.write(f"{tag}: {value}\n") diff --git a/src/spdx3/writer/console/creation_information_writer.py b/src/spdx3/writer/console/creation_information_writer.py new file mode 100644 index 000000000..1f1139073 --- /dev/null +++ b/src/spdx3/writer/console/creation_information_writer.py @@ -0,0 +1,24 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx.datetime_conversions import datetime_to_iso_string +from spdx3.model.creation_information import CreationInformation +from spdx3.writer.console.console import write_value + + +def write_creation_info(creation_info: CreationInformation, text_output: TextIO): + text_output.write("# Creation Information\n") + write_value("specVersion", str(creation_info.spec_version), text_output) + write_value("created", datetime_to_iso_string(creation_info.created), text_output) + # write_value("Created By", creation_info.created_by, text_output) not implemented yet + write_value("profile", ", ".join(creation_info.profile), text_output) + write_value("data license", creation_info.data_license, text_output) diff --git a/src/spdx3/writer/console/element_writer.py b/src/spdx3/writer/console/element_writer.py new file mode 100644 index 000000000..3917e0e2d --- /dev/null +++ b/src/spdx3/writer/console/element_writer.py @@ -0,0 +1,39 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading +from spdx3.model.element import Element +from spdx3.writer.console.console import write_value +from spdx3.writer.console.creation_information_writer import write_creation_info +from spdx3.writer.console.external_reference_writer import write_external_reference +from spdx3.writer.console.hash_writer import write_hash + + +def write_element_properties(element: Element, text_output: TextIO): + write_value("SPDXID", element.spdx_id, text_output) + write_value("name", element.name, text_output) + write_creation_info(element.creation_info, text_output) + write_value("summary", element.summary, text_output) + write_value("description", element.description, text_output) + write_value("comment", element.comment, text_output) + write_optional_heading(element.verified_using, "Verified using", text_output) + for integrity_method in element.verified_using: + # for now Hash is the only child class of the abstract class IntegrityMethod, as soon as there are more inherited + # classes we need to implement a logic that determines the correct write function for the "integrity_method" object + write_hash(integrity_method, text_output, heading=False) + write_optional_heading(element.external_references, "External References", text_output) + for external_reference in element.external_references: + write_external_reference(external_reference, text_output) + + + + diff --git a/src/spdx3/writer/console/external_map_writer.py b/src/spdx3/writer/console/external_map_writer.py new file mode 100644 index 000000000..fc9456a7a --- /dev/null +++ b/src/spdx3/writer/console/external_map_writer.py @@ -0,0 +1,26 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading +from spdx3.model.external_map import ExternalMap +from spdx3.writer.console.console import write_value +from spdx3.writer.console.hash_writer import write_hash + + +def write_external_map(external_map: ExternalMap, text_output: TextIO): + write_value("external_id", external_map.external_id, text_output) + write_optional_heading(external_map.verified_using, "# Verified using", text_output) + for integrity_method in external_map.verified_using: + # for now Hash is the only child class of the abstract class IntegrityMethod, as soon as there are more inherited + # classes we need to implement a logic that determines the correct write function for the "integrity_method" object + write_hash(integrity_method, text_output, heading=False) + write_value("location_hint", external_map.location_hint, text_output) diff --git a/src/spdx3/writer/console/external_reference_writer.py b/src/spdx3/writer/console/external_reference_writer.py new file mode 100644 index 000000000..2bd8cc91c --- /dev/null +++ b/src/spdx3/writer/console/external_reference_writer.py @@ -0,0 +1,22 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.external_reference import ExternalReference +from spdx3.writer.console.console import write_value + + +def write_external_reference(external_reference: ExternalReference, text_output: TextIO): + write_value("type", external_reference.external_reference_type.name, text_output) + write_value("locator", ", ".join(external_reference.locator), text_output) + write_value("content_type", external_reference.content_type, text_output) + write_value("comment", external_reference.comment, text_output) + diff --git a/src/spdx3/writer/console/hash_writer.py b/src/spdx3/writer/console/hash_writer.py new file mode 100644 index 000000000..cee4bee53 --- /dev/null +++ b/src/spdx3/writer/console/hash_writer.py @@ -0,0 +1,23 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.hash import Hash +from spdx3.writer.console.console import write_value +from spdx3.writer.console.integrity_method_writer import write_integrity_method + + +def write_hash(hash_object: Hash, text_output: TextIO, heading: bool): + if heading: + text_output.write("## Hash\n") + write_value("algorithm", hash_object.algorithm.name, text_output) + write_value("hash_value", hash_object.hash_value, text_output) + write_integrity_method(hash_object, text_output) diff --git a/src/spdx3/writer/console/integrity_method_writer.py b/src/spdx3/writer/console/integrity_method_writer.py new file mode 100644 index 000000000..d42f14505 --- /dev/null +++ b/src/spdx3/writer/console/integrity_method_writer.py @@ -0,0 +1,18 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.integrity_method import IntegrityMethod +from spdx3.writer.console.console import write_value + + +def write_integrity_method(integrity_method: IntegrityMethod, text_output: TextIO): + write_value("comment", integrity_method.comment, text_output) diff --git a/src/spdx3/writer/console/namespace_map_writer.py b/src/spdx3/writer/console/namespace_map_writer.py new file mode 100644 index 000000000..048390008 --- /dev/null +++ b/src/spdx3/writer/console/namespace_map_writer.py @@ -0,0 +1,19 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.namespace_map import NamespaceMap +from spdx3.writer.console.console import write_value + + +def write_namespace_map(namespace_map: NamespaceMap, text_output: TextIO): + write_value("prefix", namespace_map.prefix, text_output) + write_value("namespace", namespace_map.namespace, text_output) diff --git a/src/spdx3/writer/console/relationship_writer.py b/src/spdx3/writer/console/relationship_writer.py new file mode 100644 index 000000000..421252f93 --- /dev/null +++ b/src/spdx3/writer/console/relationship_writer.py @@ -0,0 +1,22 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.relationship import Relationship +from spdx3.writer.console.console import write_value + + +def write_relationship(relationship: Relationship, text_output: TextIO): + text_output.write("## Relationship\n") + write_value("from_element", relationship.from_element, text_output) + write_value("to", ", ".join(relationship.to), text_output) + write_value("relationship_type", relationship.relationship_type.name, text_output) + write_value("completeness", relationship.completeness.name, text_output) diff --git a/src/spdx3/writer/console/spdx_collection_writer.py b/src/spdx3/writer/console/spdx_collection_writer.py new file mode 100644 index 000000000..18afd6de8 --- /dev/null +++ b/src/spdx3/writer/console/spdx_collection_writer.py @@ -0,0 +1,28 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading +from spdx3.model.spdx_collection import SpdxCollection +from spdx3.writer.console.element_writer import write_element_properties +from spdx3.writer.console.external_map_writer import write_external_map +from spdx3.writer.console.namespace_map_writer import write_namespace_map + + +def write_collection(collection: SpdxCollection, text_output: TextIO): + write_element_properties(collection, text_output) + text_output.write(f"# Elements: {', '.join(collection.elements)}\n") + write_optional_heading(collection.namespaces, "# Namespaces\n", text_output) + for namespace_map in collection.namespaces: + write_namespace_map(namespace_map, text_output) + write_optional_heading(collection.imports, "# Imports\n", text_output) + for external_map in collection.imports: + write_external_map(external_map, text_output) diff --git a/src/spdx3/writer/console/spdx_document_writer.py b/src/spdx3/writer/console/spdx_document_writer.py new file mode 100644 index 000000000..0848bb62b --- /dev/null +++ b/src/spdx3/writer/console/spdx_document_writer.py @@ -0,0 +1,19 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.spdx_document import SpdxDocument +from spdx3.writer.console.bundle_writer import write_bundle + + +def write_spdx_document(spdx_document: SpdxDocument, text_output: TextIO): + text_output.write("## SPDX Document\n") + write_bundle(spdx_document, text_output, False) From 831a0687f07f92fe409a3ad5fd7909ef1ccf89b1 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 14:18:05 +0100 Subject: [PATCH 122/354] [spdx3.0] add writer for classes in software profile Signed-off-by: Meret Behrens --- src/spdx3/writer/console/software/__init__.py | 0 .../writer/console/software/file_writer.py | 23 +++++++++++++++++ .../writer/console/software/package_writer.py | 25 +++++++++++++++++++ .../writer/console/software/sbom_writer.py | 19 ++++++++++++++ .../writer/console/software/snippet_writer.py | 25 +++++++++++++++++++ 5 files changed, 92 insertions(+) create mode 100644 src/spdx3/writer/console/software/__init__.py create mode 100644 src/spdx3/writer/console/software/file_writer.py create mode 100644 src/spdx3/writer/console/software/package_writer.py create mode 100644 src/spdx3/writer/console/software/sbom_writer.py create mode 100644 src/spdx3/writer/console/software/snippet_writer.py diff --git a/src/spdx3/writer/console/software/__init__.py b/src/spdx3/writer/console/software/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx3/writer/console/software/file_writer.py b/src/spdx3/writer/console/software/file_writer.py new file mode 100644 index 000000000..b339edfa8 --- /dev/null +++ b/src/spdx3/writer/console/software/file_writer.py @@ -0,0 +1,23 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.software.file import File +from spdx3.writer.console.artifact_writer import write_artifact_properties +from spdx3.writer.console.console import write_value + + +def write_file(file: File, text_output: TextIO): + text_output.write("## File\n") + write_artifact_properties(file, text_output) + write_value("content_identifier", file.content_identifier, text_output) + write_value("file_purpose", ", ".join([purpose.name for purpose in file.file_purpose]), text_output) + write_value("content_type", file.content_type, text_output) diff --git a/src/spdx3/writer/console/software/package_writer.py b/src/spdx3/writer/console/software/package_writer.py new file mode 100644 index 000000000..c8606be30 --- /dev/null +++ b/src/spdx3/writer/console/software/package_writer.py @@ -0,0 +1,25 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.software.package import Package +from spdx3.writer.console.artifact_writer import write_artifact_properties +from spdx3.writer.console.console import write_value + + +def write_package(package: Package, text_output: TextIO): + text_output.write("## Package\n") + write_artifact_properties(package, text_output) + write_value("content_identifier", package.content_identifier, text_output) + write_value("package_purpose", ", ".join([purpose.name for purpose in package.package_purpose]), text_output) + write_value("download_location", package.download_location, text_output) + write_value("package_uri", package.package_uri, text_output) + write_value("homepage", package.homepage, text_output) diff --git a/src/spdx3/writer/console/software/sbom_writer.py b/src/spdx3/writer/console/software/sbom_writer.py new file mode 100644 index 000000000..56e3ee153 --- /dev/null +++ b/src/spdx3/writer/console/software/sbom_writer.py @@ -0,0 +1,19 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.software.sbom import Sbom +from spdx3.writer.console.bom_writer import write_bom + + +def write_sbom(sbom: Sbom, text_output: TextIO): + text_output.write("## Sbom\n") + write_bom(sbom, text_output, False) diff --git a/src/spdx3/writer/console/software/snippet_writer.py b/src/spdx3/writer/console/software/snippet_writer.py new file mode 100644 index 000000000..44191aaf9 --- /dev/null +++ b/src/spdx3/writer/console/software/snippet_writer.py @@ -0,0 +1,25 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range +from spdx3.model.software.snippet import Snippet +from spdx3.writer.console.artifact_writer import write_artifact_properties +from spdx3.writer.console.console import write_value + + +def write_snippet(snippet: Snippet, text_output: TextIO): + text_output.write("## Snippet\n") + write_artifact_properties(snippet, text_output) + write_value("content_identifier", snippet.content_identifier, text_output) + write_value("snippet_purpose", ", ".join([purpose.name for purpose in snippet.snippet_purpose]), text_output) + write_range("byte_range", snippet.byte_range, text_output) + write_range("line_range", snippet.line_range, text_output) From f8822358dc2acf53c129fa5b20131b519a9f400a Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 14:50:33 +0100 Subject: [PATCH 123/354] [spdx3.0] add writer for SpdxIdMap Signed-off-by: Meret Behrens --- .../writer/console/spdx_id_map_writer.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/spdx3/writer/console/spdx_id_map_writer.py diff --git a/src/spdx3/writer/console/spdx_id_map_writer.py b/src/spdx3/writer/console/spdx_id_map_writer.py new file mode 100644 index 000000000..022be23f9 --- /dev/null +++ b/src/spdx3/writer/console/spdx_id_map_writer.py @@ -0,0 +1,51 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.annotation import Annotation +from spdx3.model.bom import Bom +from spdx3.model.bundle import Bundle + +from spdx3.model.software.file import File +from spdx3.model.software.package import Package +from spdx3.model.relationship import Relationship +from spdx3.model.software.sbom import Sbom +from spdx3.model.software.snippet import Snippet +from spdx3.model.spdx_document import SpdxDocument +from spdx3.spdx_id_map import SpdxIdMap + +from spdx3.writer.console.annotation_writer import write_annotation +from spdx3.writer.console.bom_writer import write_bom +from spdx3.writer.console.bundle_writer import write_bundle +from spdx3.writer.console.relationship_writer import write_relationship +from spdx3.writer.console.software.file_writer import write_file +from spdx3.writer.console.software.package_writer import write_package +from spdx3.writer.console.software.sbom_writer import write_sbom +from spdx3.writer.console.software.snippet_writer import write_snippet +from spdx3.writer.console.spdx_document_writer import write_spdx_document + +MAP_CLASS_TO_WRITE_METHOD = { + Annotation: write_annotation, + Relationship: write_relationship, + Bundle: write_bundle, + SpdxDocument: write_spdx_document, + Bom: write_bom, + File: write_file, + Package: write_package, + Snippet: write_snippet, + Sbom: write_sbom +} +def write_spdx_id_map(spdx_id_map: SpdxIdMap, text_output: TextIO): + for element in spdx_id_map.get_full_map().values(): + write_method = MAP_CLASS_TO_WRITE_METHOD[type(element)] + write_method(element, text_output) + text_output.write("\n") + From 9d171782aa80e78e9c3e8e6d1392521042ffb192 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 12 Jan 2023 12:17:45 +0100 Subject: [PATCH 124/354] [spdx3.0] add basic conversion from document 2.x to 3.0 Signed-off-by: Meret Behrens --- src/conversion/__init__.py | 10 ++++ .../convert_creation_information.py | 49 +++++++++++++++++++ src/conversion/convert_spdx_document.py | 24 +++++++++ src/conversion/message.py | 16 ++++++ .../test_spdx_document_conversion.py | 26 ++++++++++ 5 files changed, 125 insertions(+) create mode 100644 src/conversion/__init__.py create mode 100644 src/conversion/convert_creation_information.py create mode 100644 src/conversion/convert_spdx_document.py create mode 100644 src/conversion/message.py create mode 100644 tests/conversion/test_spdx_document_conversion.py diff --git a/src/conversion/__init__.py b/src/conversion/__init__.py new file mode 100644 index 000000000..86c12c704 --- /dev/null +++ b/src/conversion/__init__.py @@ -0,0 +1,10 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/conversion/convert_creation_information.py b/src/conversion/convert_creation_information.py new file mode 100644 index 000000000..0e354c1a9 --- /dev/null +++ b/src/conversion/convert_creation_information.py @@ -0,0 +1,49 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from datetime import datetime + +from semantic_version import Version + +from conversion.message import print_missing_conversion +from spdx3.model.spdx_document import SpdxDocument + +from spdx3.model.creation_information import CreationInformation + +from spdx.model.document import CreationInfo + + +def convert_creation_information(creation_info: CreationInfo) -> SpdxDocument: + # creation_info.spdx_id -> spdx_document.spdx_id + spdx_id = creation_info.spdx_id + + # creation_info.name -> spdx_document.name + name = creation_info.name + + # creation_info.document_namespace -> ? + print("\n") + print_missing_conversion("creation_info.document_namespace", 0) + # creation_info.creators -> creation_information.creators (not implemented yet) + print_missing_conversion("creation_info.creators", 1, "of creators") + created: datetime = creation_info.created + # creation_info.creator_comment -> ? + print_missing_conversion("creation_info.creator_comment", 0) + data_license = creation_info.data_license + # creation_info.external_document_refs -> spdx_document.imports + imports = creation_info.external_document_refs + print_missing_conversion("creation_info.external_document_refs", 0, "ExternalDocumentRef -> ExternalMap") + # creation_info.license_list_version -> ? + print_missing_conversion("creation_info.license_list_version",0) + # creation_info.document_comment -> spdx_document.comment + document_comment = creation_info.document_comment + creation_information = CreationInformation(Version("3.0.0"), created, None, [], data_license) + spdx_document = SpdxDocument(spdx_id=spdx_id, creation_info=creation_information, name=name, comment=document_comment) + + return spdx_document diff --git a/src/conversion/convert_spdx_document.py b/src/conversion/convert_spdx_document.py new file mode 100644 index 000000000..07b6eb3b9 --- /dev/null +++ b/src/conversion/convert_spdx_document.py @@ -0,0 +1,24 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from conversion.convert_creation_information import convert_creation_information +from spdx3.model.spdx_document import SpdxDocument + +from spdx.model.document import Document as Document2 + +""" We want to implement a conversion from the data model in src.spdx to the data model in src.spdx3. + As there are many fundamental differences between these version we want each conversion method to take + the object from src.spdx and return all objects that the input is translated to.""" +def convert_spdx_document(document: Document2) -> SpdxDocument: + spdx_document: SpdxDocument = convert_creation_information(document.creation_info) + + return spdx_document + diff --git a/src/conversion/message.py b/src/conversion/message.py new file mode 100644 index 000000000..fda13845c --- /dev/null +++ b/src/conversion/message.py @@ -0,0 +1,16 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +MISSING_CONVERSION_REASONS = {0: "missing conversion rule", 1: "missing implementation"} + + +def print_missing_conversion(field: str, reason, additional_information: str= ""): + print(f"{field} not converted: {MISSING_CONVERSION_REASONS[reason]} {additional_information}") diff --git a/tests/conversion/test_spdx_document_conversion.py b/tests/conversion/test_spdx_document_conversion.py new file mode 100644 index 000000000..56cb8dc53 --- /dev/null +++ b/tests/conversion/test_spdx_document_conversion.py @@ -0,0 +1,26 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from semantic_version import Version + +from spdx.model.document import Document +from spdx3.model.spdx_document import SpdxDocument + +from conversion.convert_spdx_document import convert_spdx_document +from tests.fixtures import document_fixture + +def test_spdx_document_conversion(): + document: Document = document_fixture() + + spdx_document: SpdxDocument = convert_spdx_document(document) + + assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" + assert spdx_document.name == "documentName" + assert spdx_document.creation_info.spec_version == Version("3.0.0") From 099f383271b1b647d4e6c9bda971d9ddb0104636 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 12 Jan 2023 14:02:07 +0100 Subject: [PATCH 125/354] [spdx3.0] add package conversion Signed-off-by: Meret Behrens --- src/conversion/package_conversion.py | 55 +++++++++++++++++++++ tests/conversion/test_package_conversion.py | 26 ++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/conversion/package_conversion.py create mode 100644 tests/conversion/test_package_conversion.py diff --git a/src/conversion/package_conversion.py b/src/conversion/package_conversion.py new file mode 100644 index 000000000..065742f71 --- /dev/null +++ b/src/conversion/package_conversion.py @@ -0,0 +1,55 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from spdx3.model.creation_information import CreationInformation + +from conversion.message import print_missing_conversion +from spdx3.model.software.software_purpose import SoftwarePurpose + +from spdx.model.package import Package as Package2 +from spdx3.model.software.package import Package + + +def convert_package(package2: Package2, creation_information: CreationInformation) -> Package: + spdx_id = package2.spdx_id + name = package2.name + download_location = package2.download_location + # package2.version -> ? + print("\n") + print_missing_conversion("package2.version", 0) + # package.file_name -> ? + print_missing_conversion("package2.file_name", 0) + # package.supplier -> Relationship, suppliedBy? + print_missing_conversion("package2.supplier", 1, "of relationships") + # package.originator -> package.originated_by + print_missing_conversion("package2.originator", 1, "of actors") + # package.files_analyzed -> ? + print_missing_conversion("package2.files_analyzed", 0) + # package.verification_code -> package.verified_using + print_missing_conversion("package2.verification_code", 1, "of IntegrityMethod") + # package.checksums -> package.verified_using + print_missing_conversion("package2.checksums", 1, "of IntegrityMethod") + homepage = package2.homepage + print_missing_conversion("package2.source_info", 0) + print_missing_conversion("package2.license_concluded, package2.license_info_from_files, package2.license_declared, " + "package2.license_comment, package2.copyright_text", 0, + "and missing definition of license profile") + summary = package2.summary + description = package2.description + comment = package2.comment + print_missing_conversion("package2.external_references", 1, "of ExternalReferences / ExternalIdentifiers") + print_missing_conversion("package2.attribution_texts", 0) + package_purpose = [SoftwarePurpose[ + package2.primary_package_purpose.name]] if package2.primary_package_purpose else [] + print_missing_conversion("package2.release_date, package2.built_date, package2.valid_until_date", 0) + + package = Package(spdx_id, creation_information, name, download_location=download_location, homepage=homepage, summary=summary, + description=description, comment=comment, package_purpose=package_purpose) + return package diff --git a/tests/conversion/test_package_conversion.py b/tests/conversion/test_package_conversion.py new file mode 100644 index 000000000..85d670e8b --- /dev/null +++ b/tests/conversion/test_package_conversion.py @@ -0,0 +1,26 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from conversion.package_conversion import convert_package +from spdx3.model.software.package import Package + +from tests.fixtures import package_fixture +from spdx.model.package import Package as Package2 + + +@mock.patch("spdx3.model.creation_information.CreationInformation") +def test_convert_package(creation_information): + package2: Package2 = package_fixture() + + package: Package = convert_package(package2, creation_information=creation_information) + + assert package.spdx_id == "SPDXRef-Package" From f0ec308c4ebe5a856ce72258a374156318446e98 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 12 Jan 2023 15:40:21 +0100 Subject: [PATCH 126/354] [spdx3.0] rename Signed-off-by: Meret Behrens --- ...tion_information.py => creation_information_conversion.py} | 0 .../{convert_spdx_document.py => spdx_document_conversion.py} | 2 +- tests/conversion/test_spdx_document_conversion.py | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/conversion/{convert_creation_information.py => creation_information_conversion.py} (100%) rename src/conversion/{convert_spdx_document.py => spdx_document_conversion.py} (93%) diff --git a/src/conversion/convert_creation_information.py b/src/conversion/creation_information_conversion.py similarity index 100% rename from src/conversion/convert_creation_information.py rename to src/conversion/creation_information_conversion.py diff --git a/src/conversion/convert_spdx_document.py b/src/conversion/spdx_document_conversion.py similarity index 93% rename from src/conversion/convert_spdx_document.py rename to src/conversion/spdx_document_conversion.py index 07b6eb3b9..8ebffa65c 100644 --- a/src/conversion/convert_spdx_document.py +++ b/src/conversion/spdx_document_conversion.py @@ -9,7 +9,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from conversion.convert_creation_information import convert_creation_information +from conversion.creation_information_conversion import convert_creation_information from spdx3.model.spdx_document import SpdxDocument from spdx.model.document import Document as Document2 diff --git a/tests/conversion/test_spdx_document_conversion.py b/tests/conversion/test_spdx_document_conversion.py index 56cb8dc53..e395f0c02 100644 --- a/tests/conversion/test_spdx_document_conversion.py +++ b/tests/conversion/test_spdx_document_conversion.py @@ -13,10 +13,10 @@ from spdx.model.document import Document from spdx3.model.spdx_document import SpdxDocument -from conversion.convert_spdx_document import convert_spdx_document +from conversion.spdx_document_conversion import convert_spdx_document from tests.fixtures import document_fixture -def test_spdx_document_conversion(): +def test_convert_spdx_document(): document: Document = document_fixture() spdx_document: SpdxDocument = convert_spdx_document(document) From 688debd90caf2aecea4571a7cf0ec8c557d449ea Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 12 Jan 2023 15:43:49 +0100 Subject: [PATCH 127/354] [spdx3.0] add package_conversion to document_conversion Signed-off-by: Meret Behrens --- src/conversion/spdx_document_conversion.py | 3 +++ tests/conversion/test_spdx_document_conversion.py | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/conversion/spdx_document_conversion.py b/src/conversion/spdx_document_conversion.py index 8ebffa65c..29defb3a4 100644 --- a/src/conversion/spdx_document_conversion.py +++ b/src/conversion/spdx_document_conversion.py @@ -10,6 +10,7 @@ # limitations under the License. from conversion.creation_information_conversion import convert_creation_information +from conversion.package_conversion import convert_package from spdx3.model.spdx_document import SpdxDocument from spdx.model.document import Document as Document2 @@ -19,6 +20,8 @@ the object from src.spdx and return all objects that the input is translated to.""" def convert_spdx_document(document: Document2) -> SpdxDocument: spdx_document: SpdxDocument = convert_creation_information(document.creation_info) + for package in document.packages: + spdx_document.elements.append(convert_package(package, creation_information=spdx_document.creation_info)) return spdx_document diff --git a/tests/conversion/test_spdx_document_conversion.py b/tests/conversion/test_spdx_document_conversion.py index e395f0c02..0a5ab96da 100644 --- a/tests/conversion/test_spdx_document_conversion.py +++ b/tests/conversion/test_spdx_document_conversion.py @@ -16,6 +16,7 @@ from conversion.spdx_document_conversion import convert_spdx_document from tests.fixtures import document_fixture + def test_convert_spdx_document(): document: Document = document_fixture() @@ -24,3 +25,4 @@ def test_convert_spdx_document(): assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" assert spdx_document.name == "documentName" assert spdx_document.creation_info.spec_version == Version("3.0.0") + assert len(spdx_document.elements) == 1 # so far only package conversion is implemented, so there is only one element From 421b3607ec91b8dbaf56f0458cc326245591112d Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 12 Jan 2023 16:37:44 +0100 Subject: [PATCH 128/354] [spdx3.0] add file_conversion Signed-off-by: Meret Behrens --- src/conversion/file_conversion.py | 36 +++++++++++++++++++ src/conversion/spdx_document_conversion.py | 4 +++ tests/conversion/test_file_conversion.py | 26 ++++++++++++++ .../test_spdx_document_conversion.py | 2 +- 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/conversion/file_conversion.py create mode 100644 tests/conversion/test_file_conversion.py diff --git a/src/conversion/file_conversion.py b/src/conversion/file_conversion.py new file mode 100644 index 000000000..75f34b407 --- /dev/null +++ b/src/conversion/file_conversion.py @@ -0,0 +1,36 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from conversion.message import print_missing_conversion +from spdx3.model.software.file import File + +from spdx3.model.creation_information import CreationInformation + +from spdx.model.file import File as File2 + + +def convert_file(file2: File2, creation_information: CreationInformation) -> File: + name = file2.name + spdx_id = file2.spdx_id + # file.checksums -> file.verifiedUsing + print("\n") + print_missing_conversion("file.checksums", 1, "for IntegrityMethod") + # file.file_types -> file.content_type (MediaType with Cardinality 1) + print_missing_conversion("file.file_type", 0, "different cardinalities") + print_missing_conversion( + "file.concluded_license, file.license_info_in_file, file.license_comment, file.copyright_text", 0, + "missing definition for license profile") + + comment = file2.comment + print_missing_conversion("file.notice, file.contributors, file.attribution_texts", 0, + "missing definition for license profile") + + file = File(spdx_id, creation_info=creation_information, name=name, comment=comment) + return file diff --git a/src/conversion/spdx_document_conversion.py b/src/conversion/spdx_document_conversion.py index 29defb3a4..21e6a0f30 100644 --- a/src/conversion/spdx_document_conversion.py +++ b/src/conversion/spdx_document_conversion.py @@ -10,6 +10,7 @@ # limitations under the License. from conversion.creation_information_conversion import convert_creation_information +from conversion.file_conversion import convert_file from conversion.package_conversion import convert_package from spdx3.model.spdx_document import SpdxDocument @@ -23,5 +24,8 @@ def convert_spdx_document(document: Document2) -> SpdxDocument: for package in document.packages: spdx_document.elements.append(convert_package(package, creation_information=spdx_document.creation_info)) + for file in document.files: + spdx_document.elements.append(convert_file(file, creation_information=spdx_document.creation_info)) + return spdx_document diff --git a/tests/conversion/test_file_conversion.py b/tests/conversion/test_file_conversion.py new file mode 100644 index 000000000..f29c0792a --- /dev/null +++ b/tests/conversion/test_file_conversion.py @@ -0,0 +1,26 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from conversion.file_conversion import convert_file +from spdx3.model.software.file import File + +from tests.fixtures import file_fixture +from spdx.model.file import File as File2 + + +@mock.patch("spdx3.model.creation_information.CreationInformation") +def test_convert_file(creation_information): + file2: File2 = file_fixture() + + file: File = convert_file(file2, creation_information=creation_information) + + assert file.spdx_id == "SPDXRef-File" diff --git a/tests/conversion/test_spdx_document_conversion.py b/tests/conversion/test_spdx_document_conversion.py index 0a5ab96da..7678f5d97 100644 --- a/tests/conversion/test_spdx_document_conversion.py +++ b/tests/conversion/test_spdx_document_conversion.py @@ -25,4 +25,4 @@ def test_convert_spdx_document(): assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" assert spdx_document.name == "documentName" assert spdx_document.creation_info.spec_version == Version("3.0.0") - assert len(spdx_document.elements) == 1 # so far only package conversion is implemented, so there is only one element + assert len(spdx_document.elements) == 2 # so far only package and file conversion are implemented, so there are only two elements (one package, one file) From be531a6e3d978302bb4b1ed4ae239988ac9d853f Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 12 Jan 2023 16:59:30 +0100 Subject: [PATCH 129/354] [spdx3.0] add snippet_conversion Signed-off-by: Meret Behrens --- src/conversion/snippet_conversion.py | 35 +++++++++++++++++++ src/conversion/spdx_document_conversion.py | 4 +++ tests/conversion/test_snippet_conversion.py | 25 +++++++++++++ .../test_spdx_document_conversion.py | 2 +- 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/conversion/snippet_conversion.py create mode 100644 tests/conversion/test_snippet_conversion.py diff --git a/src/conversion/snippet_conversion.py b/src/conversion/snippet_conversion.py new file mode 100644 index 000000000..14525016b --- /dev/null +++ b/src/conversion/snippet_conversion.py @@ -0,0 +1,35 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from conversion.message import print_missing_conversion +from spdx3.model.software.snippet import Snippet + +from spdx3.model.creation_information import CreationInformation + +from spdx.model.snippet import Snippet as Snippet2 + + +def convert_snippet(snippet2: Snippet2, creation_information: CreationInformation) -> Snippet: + spdx_id = snippet2.spdx_id + print("\n") + print_missing_conversion("snippet.file_spdx_id", 0) + byte_range = snippet2.byte_range + line_range = snippet2.line_range + print_missing_conversion("snippet.concluded_license, snippet.license_info_in_snippet, snippet.license_comment," + "snippet.copyright_text", 0, "missing definitions for license profile") + comment = snippet2.comment + name = snippet2.name + + print_missing_conversion("snippet.attribution_texts", 0, "missing definitions for license profile") + + snippet = Snippet(spdx_id=spdx_id, creation_info=creation_information, byte_range=byte_range, line_range=line_range, + comment=comment, name=name) + + return snippet diff --git a/src/conversion/spdx_document_conversion.py b/src/conversion/spdx_document_conversion.py index 21e6a0f30..576f48d46 100644 --- a/src/conversion/spdx_document_conversion.py +++ b/src/conversion/spdx_document_conversion.py @@ -12,6 +12,7 @@ from conversion.creation_information_conversion import convert_creation_information from conversion.file_conversion import convert_file from conversion.package_conversion import convert_package +from conversion.snippet_conversion import convert_snippet from spdx3.model.spdx_document import SpdxDocument from spdx.model.document import Document as Document2 @@ -27,5 +28,8 @@ def convert_spdx_document(document: Document2) -> SpdxDocument: for file in document.files: spdx_document.elements.append(convert_file(file, creation_information=spdx_document.creation_info)) + for snippet in document.snippets: + spdx_document.elements.append(convert_snippet(snippet, creation_information=spdx_document.creation_info)) + return spdx_document diff --git a/tests/conversion/test_snippet_conversion.py b/tests/conversion/test_snippet_conversion.py new file mode 100644 index 000000000..f382b65bb --- /dev/null +++ b/tests/conversion/test_snippet_conversion.py @@ -0,0 +1,25 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from unittest import mock + +from conversion.snippet_conversion import convert_snippet +from tests.fixtures import snippet_fixture +from spdx.model.snippet import Snippet as Snippet2 +from spdx3.model.software.snippet import Snippet + + +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +def test_convert_snippet(creation_information): + snippet2: Snippet2 = snippet_fixture() + + snippet: Snippet = convert_snippet(snippet2, creation_information=creation_information) + + assert snippet.spdx_id == "SPDXRef-Snippet" diff --git a/tests/conversion/test_spdx_document_conversion.py b/tests/conversion/test_spdx_document_conversion.py index 7678f5d97..cc16cd351 100644 --- a/tests/conversion/test_spdx_document_conversion.py +++ b/tests/conversion/test_spdx_document_conversion.py @@ -25,4 +25,4 @@ def test_convert_spdx_document(): assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" assert spdx_document.name == "documentName" assert spdx_document.creation_info.spec_version == Version("3.0.0") - assert len(spdx_document.elements) == 2 # so far only package and file conversion are implemented, so there are only two elements (one package, one file) + assert len(spdx_document.elements) == 3 # document_fixture has exactly one package, one file and one snippet which are added to the elements list during conversion From 622aeb88b076d50a6ba97c86449fbfdd93025ff0 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 13 Jan 2023 10:27:11 +0100 Subject: [PATCH 130/354] [rename] use "spdx2_"-prefix Signed-off-by: Meret Behrens --- .../creation_information_conversion.py | 16 +++++++-------- src/conversion/file_conversion.py | 10 +++++----- src/conversion/package_conversion.py | 20 +++++++++---------- src/conversion/snippet_conversion.py | 14 ++++++------- src/conversion/spdx_document_conversion.py | 4 ++-- tests/conversion/test_file_conversion.py | 6 +++--- tests/conversion/test_package_conversion.py | 6 +++--- tests/conversion/test_snippet_conversion.py | 6 +++--- .../test_spdx_document_conversion.py | 6 +++--- 9 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/conversion/creation_information_conversion.py b/src/conversion/creation_information_conversion.py index 0e354c1a9..140948171 100644 --- a/src/conversion/creation_information_conversion.py +++ b/src/conversion/creation_information_conversion.py @@ -17,32 +17,32 @@ from spdx3.model.creation_information import CreationInformation -from spdx.model.document import CreationInfo +from spdx.model.document import CreationInfo as Spdx2_CreationInfo -def convert_creation_information(creation_info: CreationInfo) -> SpdxDocument: +def convert_creation_information(spdx2_creation_info: Spdx2_CreationInfo) -> SpdxDocument: # creation_info.spdx_id -> spdx_document.spdx_id - spdx_id = creation_info.spdx_id + spdx_id = spdx2_creation_info.spdx_id # creation_info.name -> spdx_document.name - name = creation_info.name + name = spdx2_creation_info.name # creation_info.document_namespace -> ? print("\n") print_missing_conversion("creation_info.document_namespace", 0) # creation_info.creators -> creation_information.creators (not implemented yet) print_missing_conversion("creation_info.creators", 1, "of creators") - created: datetime = creation_info.created + created: datetime = spdx2_creation_info.created # creation_info.creator_comment -> ? print_missing_conversion("creation_info.creator_comment", 0) - data_license = creation_info.data_license + data_license = spdx2_creation_info.data_license # creation_info.external_document_refs -> spdx_document.imports - imports = creation_info.external_document_refs + imports = spdx2_creation_info.external_document_refs print_missing_conversion("creation_info.external_document_refs", 0, "ExternalDocumentRef -> ExternalMap") # creation_info.license_list_version -> ? print_missing_conversion("creation_info.license_list_version",0) # creation_info.document_comment -> spdx_document.comment - document_comment = creation_info.document_comment + document_comment = spdx2_creation_info.document_comment creation_information = CreationInformation(Version("3.0.0"), created, None, [], data_license) spdx_document = SpdxDocument(spdx_id=spdx_id, creation_info=creation_information, name=name, comment=document_comment) diff --git a/src/conversion/file_conversion.py b/src/conversion/file_conversion.py index 75f34b407..4ad4a7cf8 100644 --- a/src/conversion/file_conversion.py +++ b/src/conversion/file_conversion.py @@ -13,12 +13,12 @@ from spdx3.model.creation_information import CreationInformation -from spdx.model.file import File as File2 +from spdx.model.file import File as Spdx2_File -def convert_file(file2: File2, creation_information: CreationInformation) -> File: - name = file2.name - spdx_id = file2.spdx_id +def convert_file(spdx2_file: Spdx2_File, creation_information: CreationInformation) -> File: + name = spdx2_file.name + spdx_id = spdx2_file.spdx_id # file.checksums -> file.verifiedUsing print("\n") print_missing_conversion("file.checksums", 1, "for IntegrityMethod") @@ -28,7 +28,7 @@ def convert_file(file2: File2, creation_information: CreationInformation) -> Fil "file.concluded_license, file.license_info_in_file, file.license_comment, file.copyright_text", 0, "missing definition for license profile") - comment = file2.comment + comment = spdx2_file.comment print_missing_conversion("file.notice, file.contributors, file.attribution_texts", 0, "missing definition for license profile") diff --git a/src/conversion/package_conversion.py b/src/conversion/package_conversion.py index 065742f71..51eb5dbda 100644 --- a/src/conversion/package_conversion.py +++ b/src/conversion/package_conversion.py @@ -13,14 +13,14 @@ from conversion.message import print_missing_conversion from spdx3.model.software.software_purpose import SoftwarePurpose -from spdx.model.package import Package as Package2 +from spdx.model.package import Package as Spdx2_Package from spdx3.model.software.package import Package -def convert_package(package2: Package2, creation_information: CreationInformation) -> Package: - spdx_id = package2.spdx_id - name = package2.name - download_location = package2.download_location +def convert_package(spdx2_package: Spdx2_Package, creation_information: CreationInformation) -> Package: + spdx_id = spdx2_package.spdx_id + name = spdx2_package.name + download_location = spdx2_package.download_location # package2.version -> ? print("\n") print_missing_conversion("package2.version", 0) @@ -36,18 +36,18 @@ def convert_package(package2: Package2, creation_information: CreationInformatio print_missing_conversion("package2.verification_code", 1, "of IntegrityMethod") # package.checksums -> package.verified_using print_missing_conversion("package2.checksums", 1, "of IntegrityMethod") - homepage = package2.homepage + homepage = spdx2_package.homepage print_missing_conversion("package2.source_info", 0) print_missing_conversion("package2.license_concluded, package2.license_info_from_files, package2.license_declared, " "package2.license_comment, package2.copyright_text", 0, "and missing definition of license profile") - summary = package2.summary - description = package2.description - comment = package2.comment + summary = spdx2_package.summary + description = spdx2_package.description + comment = spdx2_package.comment print_missing_conversion("package2.external_references", 1, "of ExternalReferences / ExternalIdentifiers") print_missing_conversion("package2.attribution_texts", 0) package_purpose = [SoftwarePurpose[ - package2.primary_package_purpose.name]] if package2.primary_package_purpose else [] + spdx2_package.primary_package_purpose.name]] if spdx2_package.primary_package_purpose else [] print_missing_conversion("package2.release_date, package2.built_date, package2.valid_until_date", 0) package = Package(spdx_id, creation_information, name, download_location=download_location, homepage=homepage, summary=summary, diff --git a/src/conversion/snippet_conversion.py b/src/conversion/snippet_conversion.py index 14525016b..ef9236078 100644 --- a/src/conversion/snippet_conversion.py +++ b/src/conversion/snippet_conversion.py @@ -13,19 +13,19 @@ from spdx3.model.creation_information import CreationInformation -from spdx.model.snippet import Snippet as Snippet2 +from spdx.model.snippet import Snippet as Spdx2_Snippet -def convert_snippet(snippet2: Snippet2, creation_information: CreationInformation) -> Snippet: - spdx_id = snippet2.spdx_id +def convert_snippet(spdx2_snippet: Spdx2_Snippet, creation_information: CreationInformation) -> Snippet: + spdx_id = spdx2_snippet.spdx_id print("\n") print_missing_conversion("snippet.file_spdx_id", 0) - byte_range = snippet2.byte_range - line_range = snippet2.line_range + byte_range = spdx2_snippet.byte_range + line_range = spdx2_snippet.line_range print_missing_conversion("snippet.concluded_license, snippet.license_info_in_snippet, snippet.license_comment," "snippet.copyright_text", 0, "missing definitions for license profile") - comment = snippet2.comment - name = snippet2.name + comment = spdx2_snippet.comment + name = spdx2_snippet.name print_missing_conversion("snippet.attribution_texts", 0, "missing definitions for license profile") diff --git a/src/conversion/spdx_document_conversion.py b/src/conversion/spdx_document_conversion.py index 576f48d46..54d2ca427 100644 --- a/src/conversion/spdx_document_conversion.py +++ b/src/conversion/spdx_document_conversion.py @@ -15,12 +15,12 @@ from conversion.snippet_conversion import convert_snippet from spdx3.model.spdx_document import SpdxDocument -from spdx.model.document import Document as Document2 +from spdx.model.document import Document as Spdx2_Document """ We want to implement a conversion from the data model in src.spdx to the data model in src.spdx3. As there are many fundamental differences between these version we want each conversion method to take the object from src.spdx and return all objects that the input is translated to.""" -def convert_spdx_document(document: Document2) -> SpdxDocument: +def convert_spdx_document(document: Spdx2_Document) -> SpdxDocument: spdx_document: SpdxDocument = convert_creation_information(document.creation_info) for package in document.packages: spdx_document.elements.append(convert_package(package, creation_information=spdx_document.creation_info)) diff --git a/tests/conversion/test_file_conversion.py b/tests/conversion/test_file_conversion.py index f29c0792a..db6493744 100644 --- a/tests/conversion/test_file_conversion.py +++ b/tests/conversion/test_file_conversion.py @@ -14,13 +14,13 @@ from spdx3.model.software.file import File from tests.fixtures import file_fixture -from spdx.model.file import File as File2 +from spdx.model.file import File as Spdx2_File @mock.patch("spdx3.model.creation_information.CreationInformation") def test_convert_file(creation_information): - file2: File2 = file_fixture() + spdx2_file: Spdx2_File = file_fixture() - file: File = convert_file(file2, creation_information=creation_information) + file: File = convert_file(spdx2_file, creation_information=creation_information) assert file.spdx_id == "SPDXRef-File" diff --git a/tests/conversion/test_package_conversion.py b/tests/conversion/test_package_conversion.py index 85d670e8b..927a473f9 100644 --- a/tests/conversion/test_package_conversion.py +++ b/tests/conversion/test_package_conversion.py @@ -14,13 +14,13 @@ from spdx3.model.software.package import Package from tests.fixtures import package_fixture -from spdx.model.package import Package as Package2 +from spdx.model.package import Package as Spdx2_Package @mock.patch("spdx3.model.creation_information.CreationInformation") def test_convert_package(creation_information): - package2: Package2 = package_fixture() + spdx2_package: Spdx2_Package = package_fixture() - package: Package = convert_package(package2, creation_information=creation_information) + package: Package = convert_package(spdx2_package, creation_information=creation_information) assert package.spdx_id == "SPDXRef-Package" diff --git a/tests/conversion/test_snippet_conversion.py b/tests/conversion/test_snippet_conversion.py index f382b65bb..d9f045273 100644 --- a/tests/conversion/test_snippet_conversion.py +++ b/tests/conversion/test_snippet_conversion.py @@ -12,14 +12,14 @@ from conversion.snippet_conversion import convert_snippet from tests.fixtures import snippet_fixture -from spdx.model.snippet import Snippet as Snippet2 +from spdx.model.snippet import Snippet as Spdx2_Snippet from spdx3.model.software.snippet import Snippet @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_convert_snippet(creation_information): - snippet2: Snippet2 = snippet_fixture() + spdx2_snippet: Spdx2_Snippet = snippet_fixture() - snippet: Snippet = convert_snippet(snippet2, creation_information=creation_information) + snippet: Snippet = convert_snippet(spdx2_snippet, creation_information=creation_information) assert snippet.spdx_id == "SPDXRef-Snippet" diff --git a/tests/conversion/test_spdx_document_conversion.py b/tests/conversion/test_spdx_document_conversion.py index cc16cd351..786378be9 100644 --- a/tests/conversion/test_spdx_document_conversion.py +++ b/tests/conversion/test_spdx_document_conversion.py @@ -10,7 +10,7 @@ # limitations under the License. from semantic_version import Version -from spdx.model.document import Document +from spdx.model.document import Document as Spdx2_Document from spdx3.model.spdx_document import SpdxDocument from conversion.spdx_document_conversion import convert_spdx_document @@ -18,9 +18,9 @@ def test_convert_spdx_document(): - document: Document = document_fixture() + spdx2_document: Spdx2_Document = document_fixture() - spdx_document: SpdxDocument = convert_spdx_document(document) + spdx_document: SpdxDocument = convert_spdx_document(spdx2_document) assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" assert spdx_document.name == "documentName" From a255ef8fb27147d4936ce09c17b3b91e83dfb83a Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 13 Jan 2023 10:34:50 +0100 Subject: [PATCH 131/354] [refactor] move conversion from src level to spdx3 Signed-off-by: Meret Behrens --- src/{ => spdx3}/conversion/__init__.py | 0 .../conversion/creation_information_conversion.py | 2 +- src/{ => spdx3}/conversion/file_conversion.py | 2 +- src/{ => spdx3}/conversion/message.py | 0 src/{ => spdx3}/conversion/package_conversion.py | 2 +- src/{ => spdx3}/conversion/snippet_conversion.py | 2 +- src/{ => spdx3}/conversion/spdx_document_conversion.py | 8 ++++---- tests/{ => spdx3}/conversion/test_file_conversion.py | 2 +- tests/{ => spdx3}/conversion/test_package_conversion.py | 2 +- tests/{ => spdx3}/conversion/test_snippet_conversion.py | 2 +- .../conversion/test_spdx_document_conversion.py | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) rename src/{ => spdx3}/conversion/__init__.py (100%) rename src/{ => spdx3}/conversion/creation_information_conversion.py (97%) rename src/{ => spdx3}/conversion/file_conversion.py (96%) rename src/{ => spdx3}/conversion/message.py (100%) rename src/{ => spdx3}/conversion/package_conversion.py (97%) rename src/{ => spdx3}/conversion/snippet_conversion.py (96%) rename src/{ => spdx3}/conversion/spdx_document_conversion.py (85%) rename tests/{ => spdx3}/conversion/test_file_conversion.py (94%) rename tests/{ => spdx3}/conversion/test_package_conversion.py (94%) rename tests/{ => spdx3}/conversion/test_snippet_conversion.py (94%) rename tests/{ => spdx3}/conversion/test_spdx_document_conversion.py (94%) diff --git a/src/conversion/__init__.py b/src/spdx3/conversion/__init__.py similarity index 100% rename from src/conversion/__init__.py rename to src/spdx3/conversion/__init__.py diff --git a/src/conversion/creation_information_conversion.py b/src/spdx3/conversion/creation_information_conversion.py similarity index 97% rename from src/conversion/creation_information_conversion.py rename to src/spdx3/conversion/creation_information_conversion.py index 140948171..b37b72815 100644 --- a/src/conversion/creation_information_conversion.py +++ b/src/spdx3/conversion/creation_information_conversion.py @@ -12,7 +12,7 @@ from semantic_version import Version -from conversion.message import print_missing_conversion +from spdx3.conversion.message import print_missing_conversion from spdx3.model.spdx_document import SpdxDocument from spdx3.model.creation_information import CreationInformation diff --git a/src/conversion/file_conversion.py b/src/spdx3/conversion/file_conversion.py similarity index 96% rename from src/conversion/file_conversion.py rename to src/spdx3/conversion/file_conversion.py index 4ad4a7cf8..75ec21cad 100644 --- a/src/conversion/file_conversion.py +++ b/src/spdx3/conversion/file_conversion.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from conversion.message import print_missing_conversion +from spdx3.conversion.message import print_missing_conversion from spdx3.model.software.file import File from spdx3.model.creation_information import CreationInformation diff --git a/src/conversion/message.py b/src/spdx3/conversion/message.py similarity index 100% rename from src/conversion/message.py rename to src/spdx3/conversion/message.py diff --git a/src/conversion/package_conversion.py b/src/spdx3/conversion/package_conversion.py similarity index 97% rename from src/conversion/package_conversion.py rename to src/spdx3/conversion/package_conversion.py index 51eb5dbda..d7285e0c6 100644 --- a/src/conversion/package_conversion.py +++ b/src/spdx3/conversion/package_conversion.py @@ -10,7 +10,7 @@ # limitations under the License. from spdx3.model.creation_information import CreationInformation -from conversion.message import print_missing_conversion +from spdx3.conversion.message import print_missing_conversion from spdx3.model.software.software_purpose import SoftwarePurpose from spdx.model.package import Package as Spdx2_Package diff --git a/src/conversion/snippet_conversion.py b/src/spdx3/conversion/snippet_conversion.py similarity index 96% rename from src/conversion/snippet_conversion.py rename to src/spdx3/conversion/snippet_conversion.py index ef9236078..81c428a0a 100644 --- a/src/conversion/snippet_conversion.py +++ b/src/spdx3/conversion/snippet_conversion.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from conversion.message import print_missing_conversion +from spdx3.conversion.message import print_missing_conversion from spdx3.model.software.snippet import Snippet from spdx3.model.creation_information import CreationInformation diff --git a/src/conversion/spdx_document_conversion.py b/src/spdx3/conversion/spdx_document_conversion.py similarity index 85% rename from src/conversion/spdx_document_conversion.py rename to src/spdx3/conversion/spdx_document_conversion.py index 54d2ca427..5e69c96ad 100644 --- a/src/conversion/spdx_document_conversion.py +++ b/src/spdx3/conversion/spdx_document_conversion.py @@ -9,10 +9,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from conversion.creation_information_conversion import convert_creation_information -from conversion.file_conversion import convert_file -from conversion.package_conversion import convert_package -from conversion.snippet_conversion import convert_snippet +from spdx3.conversion.creation_information_conversion import convert_creation_information +from spdx3.conversion.file_conversion import convert_file +from spdx3.conversion.package_conversion import convert_package +from spdx3.conversion.snippet_conversion import convert_snippet from spdx3.model.spdx_document import SpdxDocument from spdx.model.document import Document as Spdx2_Document diff --git a/tests/conversion/test_file_conversion.py b/tests/spdx3/conversion/test_file_conversion.py similarity index 94% rename from tests/conversion/test_file_conversion.py rename to tests/spdx3/conversion/test_file_conversion.py index db6493744..02cbbc1ed 100644 --- a/tests/conversion/test_file_conversion.py +++ b/tests/spdx3/conversion/test_file_conversion.py @@ -10,7 +10,7 @@ # limitations under the License. from unittest import mock -from conversion.file_conversion import convert_file +from spdx3.conversion.file_conversion import convert_file from spdx3.model.software.file import File from tests.fixtures import file_fixture diff --git a/tests/conversion/test_package_conversion.py b/tests/spdx3/conversion/test_package_conversion.py similarity index 94% rename from tests/conversion/test_package_conversion.py rename to tests/spdx3/conversion/test_package_conversion.py index 927a473f9..9fff4a03f 100644 --- a/tests/conversion/test_package_conversion.py +++ b/tests/spdx3/conversion/test_package_conversion.py @@ -10,7 +10,7 @@ # limitations under the License. from unittest import mock -from conversion.package_conversion import convert_package +from spdx3.conversion.package_conversion import convert_package from spdx3.model.software.package import Package from tests.fixtures import package_fixture diff --git a/tests/conversion/test_snippet_conversion.py b/tests/spdx3/conversion/test_snippet_conversion.py similarity index 94% rename from tests/conversion/test_snippet_conversion.py rename to tests/spdx3/conversion/test_snippet_conversion.py index d9f045273..61c48db41 100644 --- a/tests/conversion/test_snippet_conversion.py +++ b/tests/spdx3/conversion/test_snippet_conversion.py @@ -10,7 +10,7 @@ # limitations under the License. from unittest import mock -from conversion.snippet_conversion import convert_snippet +from spdx3.conversion.snippet_conversion import convert_snippet from tests.fixtures import snippet_fixture from spdx.model.snippet import Snippet as Spdx2_Snippet from spdx3.model.software.snippet import Snippet diff --git a/tests/conversion/test_spdx_document_conversion.py b/tests/spdx3/conversion/test_spdx_document_conversion.py similarity index 94% rename from tests/conversion/test_spdx_document_conversion.py rename to tests/spdx3/conversion/test_spdx_document_conversion.py index 786378be9..db111d5a4 100644 --- a/tests/conversion/test_spdx_document_conversion.py +++ b/tests/spdx3/conversion/test_spdx_document_conversion.py @@ -13,7 +13,7 @@ from spdx.model.document import Document as Spdx2_Document from spdx3.model.spdx_document import SpdxDocument -from conversion.spdx_document_conversion import convert_spdx_document +from spdx3.conversion.spdx_document_conversion import convert_spdx_document from tests.fixtures import document_fixture From ae4416df89fb7c8a33c030f3f575d71fabaabe36 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 13 Jan 2023 10:59:29 +0100 Subject: [PATCH 132/354] [refactor] use bump instead of conversion as we write a conversion to migrate from spdx2 to spdx3 Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/__init__.py | 0 .../creation_information.py} | 4 ++-- .../file.py} | 4 ++-- .../message.py | 0 .../package.py} | 4 ++-- .../snippet.py} | 4 ++-- .../spdx_document.py} | 22 +++++++++---------- src/spdx3/conversion/__init__.py | 10 --------- .../test_file_bump.py} | 6 ++--- .../test_package_bump.py} | 7 +++--- .../test_snippet_bump.py} | 6 ++--- .../test_spdx_document_bump.py} | 8 +++---- 12 files changed, 33 insertions(+), 42 deletions(-) create mode 100644 src/spdx3/bump_from_spdx2/__init__.py rename src/spdx3/{conversion/creation_information_conversion.py => bump_from_spdx2/creation_information.py} (93%) rename src/spdx3/{conversion/file_conversion.py => bump_from_spdx2/file.py} (90%) rename src/spdx3/{conversion => bump_from_spdx2}/message.py (100%) rename src/spdx3/{conversion/package_conversion.py => bump_from_spdx2/package.py} (94%) rename src/spdx3/{conversion/snippet_conversion.py => bump_from_spdx2/snippet.py} (90%) rename src/spdx3/{conversion/spdx_document_conversion.py => bump_from_spdx2/spdx_document.py} (51%) delete mode 100644 src/spdx3/conversion/__init__.py rename tests/spdx3/{conversion/test_file_conversion.py => bump/test_file_bump.py} (82%) rename tests/spdx3/{conversion/test_package_conversion.py => bump/test_package_bump.py} (81%) rename tests/spdx3/{conversion/test_snippet_conversion.py => bump/test_snippet_bump.py} (81%) rename tests/spdx3/{conversion/test_spdx_document_conversion.py => bump/test_spdx_document_bump.py} (83%) diff --git a/src/spdx3/bump_from_spdx2/__init__.py b/src/spdx3/bump_from_spdx2/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx3/conversion/creation_information_conversion.py b/src/spdx3/bump_from_spdx2/creation_information.py similarity index 93% rename from src/spdx3/conversion/creation_information_conversion.py rename to src/spdx3/bump_from_spdx2/creation_information.py index b37b72815..0dd7277e0 100644 --- a/src/spdx3/conversion/creation_information_conversion.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -12,7 +12,7 @@ from semantic_version import Version -from spdx3.conversion.message import print_missing_conversion +from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.spdx_document import SpdxDocument from spdx3.model.creation_information import CreationInformation @@ -20,7 +20,7 @@ from spdx.model.document import CreationInfo as Spdx2_CreationInfo -def convert_creation_information(spdx2_creation_info: Spdx2_CreationInfo) -> SpdxDocument: +def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo) -> SpdxDocument: # creation_info.spdx_id -> spdx_document.spdx_id spdx_id = spdx2_creation_info.spdx_id diff --git a/src/spdx3/conversion/file_conversion.py b/src/spdx3/bump_from_spdx2/file.py similarity index 90% rename from src/spdx3/conversion/file_conversion.py rename to src/spdx3/bump_from_spdx2/file.py index 75ec21cad..a3e2a0f0d 100644 --- a/src/spdx3/conversion/file_conversion.py +++ b/src/spdx3/bump_from_spdx2/file.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from spdx3.conversion.message import print_missing_conversion +from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.software.file import File from spdx3.model.creation_information import CreationInformation @@ -16,7 +16,7 @@ from spdx.model.file import File as Spdx2_File -def convert_file(spdx2_file: Spdx2_File, creation_information: CreationInformation) -> File: +def bump_file(spdx2_file: Spdx2_File, creation_information: CreationInformation) -> File: name = spdx2_file.name spdx_id = spdx2_file.spdx_id # file.checksums -> file.verifiedUsing diff --git a/src/spdx3/conversion/message.py b/src/spdx3/bump_from_spdx2/message.py similarity index 100% rename from src/spdx3/conversion/message.py rename to src/spdx3/bump_from_spdx2/message.py diff --git a/src/spdx3/conversion/package_conversion.py b/src/spdx3/bump_from_spdx2/package.py similarity index 94% rename from src/spdx3/conversion/package_conversion.py rename to src/spdx3/bump_from_spdx2/package.py index d7285e0c6..a7e573596 100644 --- a/src/spdx3/conversion/package_conversion.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -10,14 +10,14 @@ # limitations under the License. from spdx3.model.creation_information import CreationInformation -from spdx3.conversion.message import print_missing_conversion +from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.software.software_purpose import SoftwarePurpose from spdx.model.package import Package as Spdx2_Package from spdx3.model.software.package import Package -def convert_package(spdx2_package: Spdx2_Package, creation_information: CreationInformation) -> Package: +def bump_package(spdx2_package: Spdx2_Package, creation_information: CreationInformation) -> Package: spdx_id = spdx2_package.spdx_id name = spdx2_package.name download_location = spdx2_package.download_location diff --git a/src/spdx3/conversion/snippet_conversion.py b/src/spdx3/bump_from_spdx2/snippet.py similarity index 90% rename from src/spdx3/conversion/snippet_conversion.py rename to src/spdx3/bump_from_spdx2/snippet.py index 81c428a0a..589aaa4a5 100644 --- a/src/spdx3/conversion/snippet_conversion.py +++ b/src/spdx3/bump_from_spdx2/snippet.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from spdx3.conversion.message import print_missing_conversion +from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.software.snippet import Snippet from spdx3.model.creation_information import CreationInformation @@ -16,7 +16,7 @@ from spdx.model.snippet import Snippet as Spdx2_Snippet -def convert_snippet(spdx2_snippet: Spdx2_Snippet, creation_information: CreationInformation) -> Snippet: +def bump_snippet(spdx2_snippet: Spdx2_Snippet, creation_information: CreationInformation) -> Snippet: spdx_id = spdx2_snippet.spdx_id print("\n") print_missing_conversion("snippet.file_spdx_id", 0) diff --git a/src/spdx3/conversion/spdx_document_conversion.py b/src/spdx3/bump_from_spdx2/spdx_document.py similarity index 51% rename from src/spdx3/conversion/spdx_document_conversion.py rename to src/spdx3/bump_from_spdx2/spdx_document.py index 5e69c96ad..722069404 100644 --- a/src/spdx3/conversion/spdx_document_conversion.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -9,27 +9,27 @@ # See the License for the specific language governing permissions and # limitations under the License. -from spdx3.conversion.creation_information_conversion import convert_creation_information -from spdx3.conversion.file_conversion import convert_file -from spdx3.conversion.package_conversion import convert_package -from spdx3.conversion.snippet_conversion import convert_snippet +from spdx3.bump_from_spdx2.creation_information import bump_creation_information +from spdx3.bump_from_spdx2.file import bump_file +from spdx3.bump_from_spdx2.package import bump_package +from spdx3.bump_from_spdx2.snippet import bump_snippet from spdx3.model.spdx_document import SpdxDocument from spdx.model.document import Document as Spdx2_Document -""" We want to implement a conversion from the data model in src.spdx to the data model in src.spdx3. - As there are many fundamental differences between these version we want each conversion method to take +""" We want to implement a bump_from_spdx2 from the data model in src.spdx to the data model in src.spdx3. + As there are many fundamental differences between these version we want each bump_from_spdx2 method to take the object from src.spdx and return all objects that the input is translated to.""" -def convert_spdx_document(document: Spdx2_Document) -> SpdxDocument: - spdx_document: SpdxDocument = convert_creation_information(document.creation_info) +def bump_spdx_document(document: Spdx2_Document) -> SpdxDocument: + spdx_document: SpdxDocument = bump_creation_information(document.creation_info) for package in document.packages: - spdx_document.elements.append(convert_package(package, creation_information=spdx_document.creation_info)) + spdx_document.elements.append(bump_package(package, creation_information=spdx_document.creation_info)) for file in document.files: - spdx_document.elements.append(convert_file(file, creation_information=spdx_document.creation_info)) + spdx_document.elements.append(bump_file(file, creation_information=spdx_document.creation_info)) for snippet in document.snippets: - spdx_document.elements.append(convert_snippet(snippet, creation_information=spdx_document.creation_info)) + spdx_document.elements.append(bump_snippet(snippet, creation_information=spdx_document.creation_info)) return spdx_document diff --git a/src/spdx3/conversion/__init__.py b/src/spdx3/conversion/__init__.py deleted file mode 100644 index 86c12c704..000000000 --- a/src/spdx3/conversion/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/tests/spdx3/conversion/test_file_conversion.py b/tests/spdx3/bump/test_file_bump.py similarity index 82% rename from tests/spdx3/conversion/test_file_conversion.py rename to tests/spdx3/bump/test_file_bump.py index 02cbbc1ed..a8b093457 100644 --- a/tests/spdx3/conversion/test_file_conversion.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -10,7 +10,7 @@ # limitations under the License. from unittest import mock -from spdx3.conversion.file_conversion import convert_file +from spdx3.bump_from_spdx2.file import bump_file from spdx3.model.software.file import File from tests.fixtures import file_fixture @@ -18,9 +18,9 @@ @mock.patch("spdx3.model.creation_information.CreationInformation") -def test_convert_file(creation_information): +def test_bump_file(creation_information): spdx2_file: Spdx2_File = file_fixture() - file: File = convert_file(spdx2_file, creation_information=creation_information) + file: File = bump_file(spdx2_file, creation_information=creation_information) assert file.spdx_id == "SPDXRef-File" diff --git a/tests/spdx3/conversion/test_package_conversion.py b/tests/spdx3/bump/test_package_bump.py similarity index 81% rename from tests/spdx3/conversion/test_package_conversion.py rename to tests/spdx3/bump/test_package_bump.py index 9fff4a03f..4743c3ac0 100644 --- a/tests/spdx3/conversion/test_package_conversion.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -10,7 +10,7 @@ # limitations under the License. from unittest import mock -from spdx3.conversion.package_conversion import convert_package +from spdx3.bump_from_spdx2.package import bump_package from spdx3.model.software.package import Package from tests.fixtures import package_fixture @@ -18,9 +18,10 @@ @mock.patch("spdx3.model.creation_information.CreationInformation") -def test_convert_package(creation_information): +def test_bump_package(creation_information): spdx2_package: Spdx2_Package = package_fixture() - package: Package = convert_package(spdx2_package, creation_information=creation_information) + package: Package = bump_package(spdx2_package, creation_information=creation_information) + assert package.spdx_id == "SPDXRef-Package" diff --git a/tests/spdx3/conversion/test_snippet_conversion.py b/tests/spdx3/bump/test_snippet_bump.py similarity index 81% rename from tests/spdx3/conversion/test_snippet_conversion.py rename to tests/spdx3/bump/test_snippet_bump.py index 61c48db41..f73847ebd 100644 --- a/tests/spdx3/conversion/test_snippet_conversion.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -10,16 +10,16 @@ # limitations under the License. from unittest import mock -from spdx3.conversion.snippet_conversion import convert_snippet +from spdx3.bump_from_spdx2.snippet import bump_snippet from tests.fixtures import snippet_fixture from spdx.model.snippet import Snippet as Spdx2_Snippet from spdx3.model.software.snippet import Snippet @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) -def test_convert_snippet(creation_information): +def test_bump_snippet(creation_information): spdx2_snippet: Spdx2_Snippet = snippet_fixture() - snippet: Snippet = convert_snippet(spdx2_snippet, creation_information=creation_information) + snippet: Snippet = bump_snippet(spdx2_snippet, creation_information=creation_information) assert snippet.spdx_id == "SPDXRef-Snippet" diff --git a/tests/spdx3/conversion/test_spdx_document_conversion.py b/tests/spdx3/bump/test_spdx_document_bump.py similarity index 83% rename from tests/spdx3/conversion/test_spdx_document_conversion.py rename to tests/spdx3/bump/test_spdx_document_bump.py index db111d5a4..488afad0a 100644 --- a/tests/spdx3/conversion/test_spdx_document_conversion.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -13,16 +13,16 @@ from spdx.model.document import Document as Spdx2_Document from spdx3.model.spdx_document import SpdxDocument -from spdx3.conversion.spdx_document_conversion import convert_spdx_document +from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document from tests.fixtures import document_fixture -def test_convert_spdx_document(): +def test_bump_spdx_document(): spdx2_document: Spdx2_Document = document_fixture() - spdx_document: SpdxDocument = convert_spdx_document(spdx2_document) + spdx_document: SpdxDocument = bump_spdx_document(spdx2_document) assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" assert spdx_document.name == "documentName" assert spdx_document.creation_info.spec_version == Version("3.0.0") - assert len(spdx_document.elements) == 3 # document_fixture has exactly one package, one file and one snippet which are added to the elements list during conversion + assert len(spdx_document.elements) == 3 # document_fixture has exactly one package, one file and one snippet which are added to the elements list during bump_from_spdx2 From 1be343d6d15ea19bccd326e18f961e87c400f210 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 13 Jan 2023 11:41:54 +0100 Subject: [PATCH 133/354] [spdx3.0, conversion] make elements and root_elements required for collections and all inherited classes Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/creation_information.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index 0dd7277e0..a15270752 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -40,10 +40,11 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo) -> SpdxDo imports = spdx2_creation_info.external_document_refs print_missing_conversion("creation_info.external_document_refs", 0, "ExternalDocumentRef -> ExternalMap") # creation_info.license_list_version -> ? - print_missing_conversion("creation_info.license_list_version",0) + print_missing_conversion("creation_info.license_list_version", 0) # creation_info.document_comment -> spdx_document.comment document_comment = spdx2_creation_info.document_comment creation_information = CreationInformation(Version("3.0.0"), created, None, [], data_license) - spdx_document = SpdxDocument(spdx_id=spdx_id, creation_info=creation_information, name=name, comment=document_comment) + spdx_document = SpdxDocument(spdx_id=spdx_id, creation_info=creation_information, name=name, + comment=document_comment, elements=[], root_elements=[]) return spdx_document From f888d79c5fad9d47d41a0f2bb254bd4b3cf28e57 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 10:23:42 +0100 Subject: [PATCH 134/354] [spdx3.0] add profiles to bump and newline for output Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/creation_information.py | 2 +- src/spdx3/bump_from_spdx2/spdx_document.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index a15270752..9a37892f6 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -43,7 +43,7 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo) -> SpdxDo print_missing_conversion("creation_info.license_list_version", 0) # creation_info.document_comment -> spdx_document.comment document_comment = spdx2_creation_info.document_comment - creation_information = CreationInformation(Version("3.0.0"), created, None, [], data_license) + creation_information = CreationInformation(Version("3.0.0"), created, None, ["core", "software", "licensing"], data_license) spdx_document = SpdxDocument(spdx_id=spdx_id, creation_info=creation_information, name=name, comment=document_comment, elements=[], root_elements=[]) diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx3/bump_from_spdx2/spdx_document.py index 722069404..aa448ff22 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -30,6 +30,6 @@ def bump_spdx_document(document: Spdx2_Document) -> SpdxDocument: for snippet in document.snippets: spdx_document.elements.append(bump_snippet(snippet, creation_information=spdx_document.creation_info)) - + print("\n") return spdx_document From 04655c4b01bfd176ade03a859a4f593f680df6cd Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 17 Jan 2023 09:09:54 +0100 Subject: [PATCH 135/354] [spdx3.0] add checksum bump Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/checksum.py | 27 +++++++++++++++ src/spdx3/bump_from_spdx2/file.py | 6 ++-- src/spdx3/bump_from_spdx2/package.py | 8 +++-- tests/spdx3/bump/test_checksum_bump.py | 48 ++++++++++++++++++++++++++ tests/spdx3/bump/test_file_bump.py | 6 ++-- 5 files changed, 88 insertions(+), 7 deletions(-) create mode 100644 src/spdx3/bump_from_spdx2/checksum.py create mode 100644 tests/spdx3/bump/test_checksum_bump.py diff --git a/src/spdx3/bump_from_spdx2/checksum.py b/src/spdx3/bump_from_spdx2/checksum.py new file mode 100644 index 000000000..a37e2caff --- /dev/null +++ b/src/spdx3/bump_from_spdx2/checksum.py @@ -0,0 +1,27 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from spdx.model.checksum import Checksum as Spdx2_Checksum, ChecksumAlgorithm +from spdx3.model.integrity_method import IntegrityMethod, HashAlgorithm, Hash + + +def bump_checksum(spdx2_checksum: Spdx2_Checksum) -> IntegrityMethod: + algorithm: HashAlgorithm = convert_checksum_algorithm_to_hash_algorithm(spdx2_checksum.algorithm) + value: str = spdx2_checksum.value + + return Hash(algorithm, value) + + +def convert_checksum_algorithm_to_hash_algorithm(checksum_algorithm: ChecksumAlgorithm) -> HashAlgorithm: + if checksum_algorithm.name.startswith("BLAKE"): + return HashAlgorithm[checksum_algorithm.name.replace("_","")] + if checksum_algorithm == ChecksumAlgorithm.ADLER32: + return HashAlgorithm.OTHER + return HashAlgorithm[checksum_algorithm.name] diff --git a/src/spdx3/bump_from_spdx2/file.py b/src/spdx3/bump_from_spdx2/file.py index a3e2a0f0d..da2dceb1b 100644 --- a/src/spdx3/bump_from_spdx2/file.py +++ b/src/spdx3/bump_from_spdx2/file.py @@ -8,6 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from spdx3.bump_from_spdx2.checksum import bump_checksum from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.software.file import File @@ -19,9 +20,9 @@ def bump_file(spdx2_file: Spdx2_File, creation_information: CreationInformation) -> File: name = spdx2_file.name spdx_id = spdx2_file.spdx_id + integrity_methods = [bump_checksum(checksum) for checksum in spdx2_file.checksums] # file.checksums -> file.verifiedUsing print("\n") - print_missing_conversion("file.checksums", 1, "for IntegrityMethod") # file.file_types -> file.content_type (MediaType with Cardinality 1) print_missing_conversion("file.file_type", 0, "different cardinalities") print_missing_conversion( @@ -32,5 +33,6 @@ def bump_file(spdx2_file: Spdx2_File, creation_information: CreationInformation) print_missing_conversion("file.notice, file.contributors, file.attribution_texts", 0, "missing definition for license profile") - file = File(spdx_id, creation_info=creation_information, name=name, comment=comment) + file = File(spdx_id, creation_info=creation_information, name=name, comment=comment, + verified_using=integrity_methods) return file diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index a7e573596..e74c68381 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -8,6 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from spdx3.bump_from_spdx2.checksum import bump_checksum from spdx3.model.creation_information import CreationInformation from spdx3.bump_from_spdx2.message import print_missing_conversion @@ -35,7 +36,7 @@ def bump_package(spdx2_package: Spdx2_Package, creation_information: CreationInf # package.verification_code -> package.verified_using print_missing_conversion("package2.verification_code", 1, "of IntegrityMethod") # package.checksums -> package.verified_using - print_missing_conversion("package2.checksums", 1, "of IntegrityMethod") + integrity_methods = [bump_checksum(checksum) for checksum in spdx2_package.checksums] homepage = spdx2_package.homepage print_missing_conversion("package2.source_info", 0) print_missing_conversion("package2.license_concluded, package2.license_info_from_files, package2.license_declared, " @@ -50,6 +51,7 @@ def bump_package(spdx2_package: Spdx2_Package, creation_information: CreationInf spdx2_package.primary_package_purpose.name]] if spdx2_package.primary_package_purpose else [] print_missing_conversion("package2.release_date, package2.built_date, package2.valid_until_date", 0) - package = Package(spdx_id, creation_information, name, download_location=download_location, homepage=homepage, summary=summary, - description=description, comment=comment, package_purpose=package_purpose) + package = Package(spdx_id, creation_information, name, verified_using=integrity_methods, + download_location=download_location, homepage=homepage, summary=summary, description=description, + comment=comment, package_purpose=package_purpose) return package diff --git a/tests/spdx3/bump/test_checksum_bump.py b/tests/spdx3/bump/test_checksum_bump.py new file mode 100644 index 000000000..2d2a23bbf --- /dev/null +++ b/tests/spdx3/bump/test_checksum_bump.py @@ -0,0 +1,48 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import pytest + +from fixtures import checksum_fixture +from spdx.model.checksum import ChecksumAlgorithm +from spdx3.bump_from_spdx2.checksum import bump_checksum, convert_checksum_algorithm_to_hash_algorithm +from spdx3.model.integrity_method import HashAlgorithm + + +def test_bump_checksum(): + checksum = checksum_fixture() + hash = bump_checksum(checksum) + + assert hash.algorithm == HashAlgorithm.SHA1 + assert hash.hash_value == "71c4025dd9897b364f3ebbb42c484ff43d00791c" + + +@pytest.mark.parametrize("checksum_algorithm,expected_hash_algorithm", + [(ChecksumAlgorithm.SHA1, HashAlgorithm.SHA1), + (ChecksumAlgorithm.SHA224, HashAlgorithm.SHA224), + (ChecksumAlgorithm.SHA256, HashAlgorithm.SHA256), + (ChecksumAlgorithm.SHA384, HashAlgorithm.SHA384), + (ChecksumAlgorithm.SHA512, HashAlgorithm.SHA512), + (ChecksumAlgorithm.SHA3_256, HashAlgorithm.SHA3_256), + (ChecksumAlgorithm.SHA3_384, HashAlgorithm.SHA3_384), + (ChecksumAlgorithm.SHA3_512, HashAlgorithm.SHA3_512), + (ChecksumAlgorithm.BLAKE2B_256, HashAlgorithm.BLAKE2B256), + (ChecksumAlgorithm.BLAKE2B_384, HashAlgorithm.BLAKE2B384), + (ChecksumAlgorithm.BLAKE2B_512, HashAlgorithm.BLAKE2B512), + (ChecksumAlgorithm.BLAKE3, HashAlgorithm.BLAKE3), + (ChecksumAlgorithm.MD2, HashAlgorithm.MD2), + (ChecksumAlgorithm.MD4, HashAlgorithm.MD4), + (ChecksumAlgorithm.MD5, HashAlgorithm.MD5), + (ChecksumAlgorithm.MD6, HashAlgorithm.MD6), + (ChecksumAlgorithm.ADLER32, HashAlgorithm.OTHER)]) +def test_bump_checksum_algorithm(checksum_algorithm, expected_hash_algorithm): + hash_algorithm = convert_checksum_algorithm_to_hash_algorithm(checksum_algorithm) + + assert hash_algorithm == expected_hash_algorithm diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index a8b093457..02b343169 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -11,16 +11,18 @@ from unittest import mock from spdx3.bump_from_spdx2.file import bump_file +from spdx3.model.integrity_method import IntegrityMethod, Hash, HashAlgorithm from spdx3.model.software.file import File from tests.fixtures import file_fixture from spdx.model.file import File as Spdx2_File - -@mock.patch("spdx3.model.creation_information.CreationInformation") +@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_bump_file(creation_information): spdx2_file: Spdx2_File = file_fixture() + integrity_method: Hash = Hash(HashAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c") file: File = bump_file(spdx2_file, creation_information=creation_information) assert file.spdx_id == "SPDXRef-File" + assert file.verified_using == [integrity_method] From 9f245398fa60adcd1092451b7f9bcb8dbff5e6e6 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 15:06:52 +0100 Subject: [PATCH 136/354] [fix] adapt import paths after rebase Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/checksum.py | 3 ++- tests/spdx3/bump/test_checksum_bump.py | 4 ++-- tests/spdx3/bump/test_file_bump.py | 4 ++-- tests/spdx3/bump/test_package_bump.py | 2 +- tests/spdx3/bump/test_snippet_bump.py | 2 +- tests/spdx3/bump/test_spdx_document_bump.py | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/checksum.py b/src/spdx3/bump_from_spdx2/checksum.py index a37e2caff..b52f422e1 100644 --- a/src/spdx3/bump_from_spdx2/checksum.py +++ b/src/spdx3/bump_from_spdx2/checksum.py @@ -9,7 +9,8 @@ # See the License for the specific language governing permissions and # limitations under the License. from spdx.model.checksum import Checksum as Spdx2_Checksum, ChecksumAlgorithm -from spdx3.model.integrity_method import IntegrityMethod, HashAlgorithm, Hash +from spdx3.model.integrity_method import IntegrityMethod +from spdx3.model.hash import HashAlgorithm, Hash def bump_checksum(spdx2_checksum: Spdx2_Checksum) -> IntegrityMethod: diff --git a/tests/spdx3/bump/test_checksum_bump.py b/tests/spdx3/bump/test_checksum_bump.py index 2d2a23bbf..6391110b5 100644 --- a/tests/spdx3/bump/test_checksum_bump.py +++ b/tests/spdx3/bump/test_checksum_bump.py @@ -10,10 +10,10 @@ # limitations under the License. import pytest -from fixtures import checksum_fixture +from tests.spdx.fixtures import checksum_fixture from spdx.model.checksum import ChecksumAlgorithm from spdx3.bump_from_spdx2.checksum import bump_checksum, convert_checksum_algorithm_to_hash_algorithm -from spdx3.model.integrity_method import HashAlgorithm +from spdx3.model.hash import HashAlgorithm def test_bump_checksum(): diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index 02b343169..e13406264 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -11,10 +11,10 @@ from unittest import mock from spdx3.bump_from_spdx2.file import bump_file -from spdx3.model.integrity_method import IntegrityMethod, Hash, HashAlgorithm +from spdx3.model.hash import Hash, HashAlgorithm from spdx3.model.software.file import File -from tests.fixtures import file_fixture +from tests.spdx.fixtures import file_fixture from spdx.model.file import File as Spdx2_File @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 4743c3ac0..e4137c52e 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -13,7 +13,7 @@ from spdx3.bump_from_spdx2.package import bump_package from spdx3.model.software.package import Package -from tests.fixtures import package_fixture +from tests.spdx.fixtures import package_fixture from spdx.model.package import Package as Spdx2_Package diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index f73847ebd..25c4ace42 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -11,7 +11,7 @@ from unittest import mock from spdx3.bump_from_spdx2.snippet import bump_snippet -from tests.fixtures import snippet_fixture +from tests.spdx.fixtures import snippet_fixture from spdx.model.snippet import Snippet as Spdx2_Snippet from spdx3.model.software.snippet import Snippet diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index 488afad0a..724b318d6 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -14,7 +14,7 @@ from spdx3.model.spdx_document import SpdxDocument from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document -from tests.fixtures import document_fixture +from tests.spdx.fixtures import document_fixture def test_bump_spdx_document(): From 8ed474a2c88d3e2a9fd0a835843167571901c105 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 16:21:00 +0100 Subject: [PATCH 137/354] [spdx3.0, writer] fix output Signed-off-by: Meret Behrens --- src/spdx3/writer/console/element_writer.py | 2 +- src/spdx3/writer/console/relationship_writer.py | 2 +- src/spdx3/writer/console/spdx_collection_writer.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/spdx3/writer/console/element_writer.py b/src/spdx3/writer/console/element_writer.py index 3917e0e2d..f1b533ee9 100644 --- a/src/spdx3/writer/console/element_writer.py +++ b/src/spdx3/writer/console/element_writer.py @@ -25,7 +25,7 @@ def write_element_properties(element: Element, text_output: TextIO): write_value("summary", element.summary, text_output) write_value("description", element.description, text_output) write_value("comment", element.comment, text_output) - write_optional_heading(element.verified_using, "Verified using", text_output) + write_optional_heading(element.verified_using, "verified using:\n", text_output) for integrity_method in element.verified_using: # for now Hash is the only child class of the abstract class IntegrityMethod, as soon as there are more inherited # classes we need to implement a logic that determines the correct write function for the "integrity_method" object diff --git a/src/spdx3/writer/console/relationship_writer.py b/src/spdx3/writer/console/relationship_writer.py index 421252f93..cf7fc694a 100644 --- a/src/spdx3/writer/console/relationship_writer.py +++ b/src/spdx3/writer/console/relationship_writer.py @@ -19,4 +19,4 @@ def write_relationship(relationship: Relationship, text_output: TextIO): write_value("from_element", relationship.from_element, text_output) write_value("to", ", ".join(relationship.to), text_output) write_value("relationship_type", relationship.relationship_type.name, text_output) - write_value("completeness", relationship.completeness.name, text_output) + write_value("completeness", relationship.completeness.name if relationship.completeness else None, text_output) diff --git a/src/spdx3/writer/console/spdx_collection_writer.py b/src/spdx3/writer/console/spdx_collection_writer.py index 18afd6de8..1a0f2c4db 100644 --- a/src/spdx3/writer/console/spdx_collection_writer.py +++ b/src/spdx3/writer/console/spdx_collection_writer.py @@ -19,7 +19,7 @@ def write_collection(collection: SpdxCollection, text_output: TextIO): write_element_properties(collection, text_output) - text_output.write(f"# Elements: {', '.join(collection.elements)}\n") + text_output.write(f"elements: {', '.join(collection.elements)}\n") write_optional_heading(collection.namespaces, "# Namespaces\n", text_output) for namespace_map in collection.namespaces: write_namespace_map(namespace_map, text_output) From 8b3c4a3ccf2c54343d741922acef2f74f2f5bf4c Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 16:22:10 +0100 Subject: [PATCH 138/354] [spdx3.0] delete double spaces in license header Signed-off-by: Meret Behrens --- tests/spdx3/bump/test_file_bump.py | 20 ++++++++++---------- tests/spdx3/bump/test_package_bump.py | 20 ++++++++++---------- tests/spdx3/bump/test_snippet_bump.py | 20 ++++++++++---------- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index e13406264..a7af63aa3 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -1,13 +1,13 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from unittest import mock from spdx3.bump_from_spdx2.file import bump_file diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index e4137c52e..e1cdda771 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -1,13 +1,13 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from unittest import mock from spdx3.bump_from_spdx2.package import bump_package diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index 25c4ace42..86d231fe6 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -1,13 +1,13 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from unittest import mock from spdx3.bump_from_spdx2.snippet import bump_snippet From 9f063e41fbd8fbe3d2b60770c80b1fd3673fe7f5 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 16:23:30 +0100 Subject: [PATCH 139/354] [spdx3.0] bump spdx 2.x document to SpdxIdMap Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/spdx_document.py | 36 ++++++++++++++++----- tests/spdx3/bump/test_spdx_document_bump.py | 36 +++++++++++---------- 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx3/bump_from_spdx2/spdx_document.py index aa448ff22..b4f1abebe 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -12,24 +12,44 @@ from spdx3.bump_from_spdx2.creation_information import bump_creation_information from spdx3.bump_from_spdx2.file import bump_file from spdx3.bump_from_spdx2.package import bump_package +from spdx3.bump_from_spdx2.relationship import bump_relationship from spdx3.bump_from_spdx2.snippet import bump_snippet +from spdx3.model.creation_information import CreationInformation from spdx3.model.spdx_document import SpdxDocument from spdx.model.document import Document as Spdx2_Document +from spdx3.spdx_id_map import SpdxIdMap """ We want to implement a bump_from_spdx2 from the data model in src.spdx to the data model in src.spdx3. As there are many fundamental differences between these version we want each bump_from_spdx2 method to take the object from src.spdx and return all objects that the input is translated to.""" -def bump_spdx_document(document: Spdx2_Document) -> SpdxDocument: +def bump_spdx_document(document: Spdx2_Document) -> SpdxIdMap: + spdx_id_map = SpdxIdMap() spdx_document: SpdxDocument = bump_creation_information(document.creation_info) - for package in document.packages: - spdx_document.elements.append(bump_package(package, creation_information=spdx_document.creation_info)) + creation_info: CreationInformation = spdx_document.creation_info - for file in document.files: - spdx_document.elements.append(bump_file(file, creation_information=spdx_document.creation_info)) + for spdx2_package in document.packages: + package = bump_package(spdx2_package, creation_information=creation_info) + spdx_id_map.add_element(package) + spdx_document.elements.append(package.spdx_id) + + for spdx2_file in document.files: + file = bump_file(spdx2_file, creation_information=creation_info) + spdx_id_map.add_element(file) + spdx_document.elements.append(file.spdx_id) + + for spdx2_snippet in document.snippets: + snippet = bump_snippet(spdx2_snippet, creation_information=creation_info) + spdx_id_map.add_element(snippet) + spdx_document.elements.append(snippet.spdx_id) + + for spdx2_relationship in document.relationships: + relationship = bump_relationship(spdx2_relationship, creation_information=creation_info) + spdx_id_map.add_element(relationship) + spdx_document.elements.append(relationship.spdx_id) + + spdx_id_map.add_element(spdx_document) - for snippet in document.snippets: - spdx_document.elements.append(bump_snippet(snippet, creation_information=spdx_document.creation_info)) print("\n") - return spdx_document + return spdx_id_map diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index 724b318d6..bdde7fcc2 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -1,28 +1,30 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from semantic_version import Version +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import sys from spdx.model.document import Document as Spdx2_Document -from spdx3.model.spdx_document import SpdxDocument from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document +from spdx3.spdx_id_map import SpdxIdMap +from spdx3.writer.console.spdx_id_map_writer import write_spdx_id_map from tests.spdx.fixtures import document_fixture def test_bump_spdx_document(): spdx2_document: Spdx2_Document = document_fixture() - spdx_document: SpdxDocument = bump_spdx_document(spdx2_document) + spdx_id_map: SpdxIdMap = bump_spdx_document(spdx2_document) - assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" - assert spdx_document.name == "documentName" - assert spdx_document.creation_info.spec_version == Version("3.0.0") - assert len(spdx_document.elements) == 3 # document_fixture has exactly one package, one file and one snippet which are added to the elements list during bump_from_spdx2 + write_spdx_id_map(spdx_id_map, sys.stdout) + + assert "SPDXRef-Package" in list(spdx_id_map.get_full_map().keys()) + assert len( + spdx_id_map.get_full_map().values()) == 4 # document_fixture has exactly one package, one file and one snippet which are added to the elements list during bump_from_spdx2 From fec615738446073de11830a4a4eab971bc47788a Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 16:34:10 +0100 Subject: [PATCH 140/354] [spdx3.0, fix] add type hint for external_references, set empty list per default Signed-off-by: Meret Behrens --- src/spdx3/model/relationship.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/spdx3/model/relationship.py b/src/spdx3/model/relationship.py index 80d679ca5..98c773889 100644 --- a/src/spdx3/model/relationship.py +++ b/src/spdx3/model/relationship.py @@ -11,6 +11,8 @@ from enum import Enum, auto from typing import List, Optional +from spdx3.model.external_reference import ExternalReference + from common.typing.type_checks import check_types_and_set_values from spdx3.model.creation_information import CreationInformation @@ -81,8 +83,9 @@ class Relationship(Element): def __init__(self, spdx_id: str, creation_info: CreationInformation, from_element: str, to: List[str], relationship_type: RelationshipType, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, external_references: None = None, - external_identifier: None = None, extension: None = None, - completeness: Optional[RelationshipCompleteness] = None): + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, + extension: None = None, completeness: Optional[RelationshipCompleteness] = None): verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references check_types_and_set_values(self, locals()) From ef89c96aa7ff79b1a5bce481198c47de0c12bea7 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 16:34:58 +0100 Subject: [PATCH 141/354] [spdx3.0, writer] fix output Signed-off-by: Meret Behrens --- src/spdx3/writer/console/annotation_writer.py | 2 +- src/spdx3/writer/console/relationship_writer.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/spdx3/writer/console/annotation_writer.py b/src/spdx3/writer/console/annotation_writer.py index 7caa9c968..95dacfcc6 100644 --- a/src/spdx3/writer/console/annotation_writer.py +++ b/src/spdx3/writer/console/annotation_writer.py @@ -20,6 +20,6 @@ def write_annotation(annotation: Annotation, text_output: TextIO): text_output.write("## Annotation\n") write_element_properties(annotation, text_output) write_value("annotation_type", annotation.annotation_type.name, text_output) - text_output.write(f"# subjects: {', '.join(annotation.subject)}") + text_output.write(f"subjects: {', '.join(annotation.subject)}\n") write_value("content_type", annotation.content_type, text_output) write_value("statement", annotation.statement, text_output) diff --git a/src/spdx3/writer/console/relationship_writer.py b/src/spdx3/writer/console/relationship_writer.py index cf7fc694a..8dc76997c 100644 --- a/src/spdx3/writer/console/relationship_writer.py +++ b/src/spdx3/writer/console/relationship_writer.py @@ -12,10 +12,12 @@ from spdx3.model.relationship import Relationship from spdx3.writer.console.console import write_value +from spdx3.writer.console.element_writer import write_element_properties def write_relationship(relationship: Relationship, text_output: TextIO): text_output.write("## Relationship\n") + write_element_properties(relationship, text_output) write_value("from_element", relationship.from_element, text_output) write_value("to", ", ".join(relationship.to), text_output) write_value("relationship_type", relationship.relationship_type.name, text_output) From f0d6ddbb1c7b0055e38b7736317f97d3b7edfb7a Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 16:35:48 +0100 Subject: [PATCH 142/354] [spdx3.0] add annotation bump Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/annotation.py | 21 +++++++++++++++++++++ src/spdx3/bump_from_spdx2/spdx_document.py | 17 +++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 src/spdx3/bump_from_spdx2/annotation.py diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py new file mode 100644 index 000000000..f4d9fc401 --- /dev/null +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -0,0 +1,21 @@ +from typing import List + +from spdx3.bump_from_spdx2.message import print_missing_conversion + +from spdx3.model.annotation import Annotation, AnnotationType + +from spdx.model.annotation import Annotation as Spdx2_Annotation +from spdx3.model.creation_information import CreationInformation + + +def bump_annotation(spdx2_annotation: Spdx2_Annotation, creation_info: CreationInformation, counter: int) -> Annotation: + spdx_id: str = f"SPDXRef-Annotation-{counter}" + creation_info.created = spdx2_annotation.annotation_date + # creation_info.created_by = bump_actor(spdx2_annotation.annotator) waiting for entity implementation + print("\n") + print_missing_conversion("annotation.annotator", 1, "of Entity") + annotation_type: AnnotationType = AnnotationType[spdx2_annotation.annotation_type.name] + subject: List[str] = [spdx2_annotation.spdx_id] + statement: str = spdx2_annotation.annotation_comment + + return Annotation(spdx_id, creation_info, annotation_type, subject, statement=statement) diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx3/bump_from_spdx2/spdx_document.py index b4f1abebe..44eb2c8bd 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - +from spdx3.bump_from_spdx2.annotation import bump_annotation from spdx3.bump_from_spdx2.creation_information import bump_creation_information from spdx3.bump_from_spdx2.file import bump_file from spdx3.bump_from_spdx2.package import bump_package @@ -29,25 +29,30 @@ def bump_spdx_document(document: Spdx2_Document) -> SpdxIdMap: creation_info: CreationInformation = spdx_document.creation_info for spdx2_package in document.packages: - package = bump_package(spdx2_package, creation_information=creation_info) + package = bump_package(spdx2_package, creation_info) spdx_id_map.add_element(package) spdx_document.elements.append(package.spdx_id) for spdx2_file in document.files: - file = bump_file(spdx2_file, creation_information=creation_info) + file = bump_file(spdx2_file, creation_info) spdx_id_map.add_element(file) spdx_document.elements.append(file.spdx_id) for spdx2_snippet in document.snippets: - snippet = bump_snippet(spdx2_snippet, creation_information=creation_info) + snippet = bump_snippet(spdx2_snippet, creation_info) spdx_id_map.add_element(snippet) spdx_document.elements.append(snippet.spdx_id) - for spdx2_relationship in document.relationships: - relationship = bump_relationship(spdx2_relationship, creation_information=creation_info) + for counter, spdx2_relationship in enumerate(document.relationships): + relationship = bump_relationship(spdx2_relationship, creation_info, counter) spdx_id_map.add_element(relationship) spdx_document.elements.append(relationship.spdx_id) + for counter, spdx2_annotation in enumerate(document.annotations): + annotation = bump_annotation(spdx2_annotation, creation_info, counter) + spdx_id_map.add_element(annotation) + spdx_document.elements.append(annotation.spdx_id) + spdx_id_map.add_element(spdx_document) print("\n") From 07f469ff08cb24342f0417c992084ad3c493e38b Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 16:38:18 +0100 Subject: [PATCH 143/354] [spdx3.0] add relationship bump Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/relationship.py | 70 +++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/spdx3/bump_from_spdx2/relationship.py diff --git a/src/spdx3/bump_from_spdx2/relationship.py b/src/spdx3/bump_from_spdx2/relationship.py new file mode 100644 index 000000000..f4b60135c --- /dev/null +++ b/src/spdx3/bump_from_spdx2/relationship.py @@ -0,0 +1,70 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Tuple, Optional + +from spdx.model.spdx_none import SpdxNone + +from spdx.model.spdx_no_assertion import SpdxNoAssertion + +from spdx3.bump_from_spdx2.message import print_missing_conversion +from spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness +from spdx3.model.creation_information import CreationInformation + +from spdx.model.relationship import Relationship as Spdx2_Relationship +from spdx.model.relationship import RelationshipType as Spdx2_RelationshipType + + +def bump_relationship(spdx2_relationship: Spdx2_Relationship, + creation_information: CreationInformation, counter: int) -> Relationship: + relationship_type, swap_direction = bump_relationship_type(spdx2_relationship.relationship_type) + + if isinstance(spdx2_relationship.related_spdx_element_id, SpdxNoAssertion): # how to translate none/ no assertion to element? + completeness = RelationshipCompleteness.UNKNOWN + elif isinstance(spdx2_relationship.related_spdx_element_id, SpdxNone): + completeness = RelationshipCompleteness.KNOWN + else: + completeness = None + + if swap_direction: + from_element = spdx2_relationship.related_spdx_element_id + to = [spdx2_relationship.spdx_element_id] + else: + from_element = spdx2_relationship.spdx_element_id + to = [spdx2_relationship.related_spdx_element_id] + comment = spdx2_relationship.comment + + relationship = Relationship(f"SPDXRef-Relationship-{counter}", creation_information, from_element, to, relationship_type, + comment=comment, completeness=completeness) + + return relationship + + +def bump_relationship_type(spdx2_relationship_type: Spdx2_RelationshipType) -> Optional[Tuple[RelationshipType, bool]]: + if spdx2_relationship_type == Spdx2_RelationshipType.DESCRIBED_BY: + return RelationshipType.DESCRIBES, True + if spdx2_relationship_type == Spdx2_RelationshipType.CONTAINED_BY: + return RelationshipType.CONTAINS, True + if spdx2_relationship_type == Spdx2_RelationshipType.DEPENDENCY_OF: + return RelationshipType.DEPENDS_ON, True + if spdx2_relationship_type == Spdx2_RelationshipType.GENERATED_FROM: + return RelationshipType.GENERATES, True + if spdx2_relationship_type == Spdx2_RelationshipType.HAS_PREREQUISITE: + return RelationshipType.PREREQUISITE, True + if spdx2_relationship_type.name.endswith("_OF"): + relationship_type = spdx2_relationship_type.name.replace("_OF", "") + return RelationshipType[relationship_type], False + if spdx2_relationship_type.name.endswith("_FOR"): + relationship_type = spdx2_relationship_type.name.replace("_FOR", "") + return RelationshipType[relationship_type], False + return RelationshipType[spdx2_relationship_type.name], False + # if spdx2_relationship_type == Spdx2_RelationshipType.PATCH_APPLIED: + # print_missing_conversion("RelationshipType.PATCH_APPLIED", 0) + # return None From 4295022aa08fd088a8caede7a35ac5154b52858e Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 16:55:41 +0100 Subject: [PATCH 144/354] [spdx3.0] delete double space in license header Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/annotation.py | 10 ++++++++++ src/spdx3/bump_from_spdx2/checksum.py | 20 +++++++++---------- .../bump_from_spdx2/creation_information.py | 20 +++++++++---------- src/spdx3/bump_from_spdx2/file.py | 20 +++++++++---------- src/spdx3/bump_from_spdx2/message.py | 20 +++++++++---------- src/spdx3/bump_from_spdx2/package.py | 20 +++++++++---------- src/spdx3/bump_from_spdx2/snippet.py | 20 +++++++++---------- 7 files changed, 70 insertions(+), 60 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py index f4d9fc401..110ad6f2b 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -1,3 +1,13 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from typing import List from spdx3.bump_from_spdx2.message import print_missing_conversion diff --git a/src/spdx3/bump_from_spdx2/checksum.py b/src/spdx3/bump_from_spdx2/checksum.py index b52f422e1..a1ce4dadf 100644 --- a/src/spdx3/bump_from_spdx2/checksum.py +++ b/src/spdx3/bump_from_spdx2/checksum.py @@ -1,13 +1,13 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from spdx.model.checksum import Checksum as Spdx2_Checksum, ChecksumAlgorithm from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.hash import HashAlgorithm, Hash diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index 9a37892f6..8c3696473 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -1,13 +1,13 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from datetime import datetime from semantic_version import Version diff --git a/src/spdx3/bump_from_spdx2/file.py b/src/spdx3/bump_from_spdx2/file.py index da2dceb1b..7282e83d6 100644 --- a/src/spdx3/bump_from_spdx2/file.py +++ b/src/spdx3/bump_from_spdx2/file.py @@ -1,13 +1,13 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from spdx3.bump_from_spdx2.checksum import bump_checksum from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.software.file import File diff --git a/src/spdx3/bump_from_spdx2/message.py b/src/spdx3/bump_from_spdx2/message.py index fda13845c..65a797d1a 100644 --- a/src/spdx3/bump_from_spdx2/message.py +++ b/src/spdx3/bump_from_spdx2/message.py @@ -1,13 +1,13 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. MISSING_CONVERSION_REASONS = {0: "missing conversion rule", 1: "missing implementation"} diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index e74c68381..30488ee5b 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -1,13 +1,13 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from spdx3.bump_from_spdx2.checksum import bump_checksum from spdx3.model.creation_information import CreationInformation diff --git a/src/spdx3/bump_from_spdx2/snippet.py b/src/spdx3/bump_from_spdx2/snippet.py index 589aaa4a5..28fa7c33e 100644 --- a/src/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx3/bump_from_spdx2/snippet.py @@ -1,13 +1,13 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.software.snippet import Snippet From b1b6c2ffb49ca7147caf53c8d56f690865e0c55b Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 17:05:29 +0100 Subject: [PATCH 145/354] [spdx-3.0, writer] add indent for nested elements Signed-off-by: Meret Behrens --- src/spdx3/writer/console/console.py | 4 +++- .../writer/console/creation_information_writer.py | 10 +++++----- src/spdx3/writer/console/element_writer.py | 2 +- src/spdx3/writer/console/hash_writer.py | 8 ++++---- src/spdx3/writer/console/integrity_method_writer.py | 4 ++-- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/spdx3/writer/console/console.py b/src/spdx3/writer/console/console.py index 5ea74e3e0..1138a1731 100644 --- a/src/spdx3/writer/console/console.py +++ b/src/spdx3/writer/console/console.py @@ -12,10 +12,12 @@ from typing import TextIO, Union, Optional -def write_value(tag: str, value: Optional[Union[bool, str]], out: TextIO): +def write_value(tag: str, value: Optional[Union[bool, str]], out: TextIO, indent: bool = False): """ This function is duplicated from spdx.writer.tagvalue.tag_value_writer_helper_functions and slightly adapted to make indentation of output possible.""" if not value: return + if indent: + out.write(f"\t{tag}: {value}\n") else: out.write(f"{tag}: {value}\n") diff --git a/src/spdx3/writer/console/creation_information_writer.py b/src/spdx3/writer/console/creation_information_writer.py index 1f1139073..9e9c2eb5f 100644 --- a/src/spdx3/writer/console/creation_information_writer.py +++ b/src/spdx3/writer/console/creation_information_writer.py @@ -15,10 +15,10 @@ from spdx3.writer.console.console import write_value -def write_creation_info(creation_info: CreationInformation, text_output: TextIO): +def write_creation_info(creation_info: CreationInformation, text_output: TextIO, indent: bool = True): text_output.write("# Creation Information\n") - write_value("specVersion", str(creation_info.spec_version), text_output) - write_value("created", datetime_to_iso_string(creation_info.created), text_output) + write_value("specVersion", str(creation_info.spec_version), text_output, indent) + write_value("created", datetime_to_iso_string(creation_info.created), text_output, indent) # write_value("Created By", creation_info.created_by, text_output) not implemented yet - write_value("profile", ", ".join(creation_info.profile), text_output) - write_value("data license", creation_info.data_license, text_output) + write_value("profile", ", ".join(creation_info.profile), text_output, indent) + write_value("data license", creation_info.data_license, text_output, indent) diff --git a/src/spdx3/writer/console/element_writer.py b/src/spdx3/writer/console/element_writer.py index f1b533ee9..ce6e5e82a 100644 --- a/src/spdx3/writer/console/element_writer.py +++ b/src/spdx3/writer/console/element_writer.py @@ -21,7 +21,7 @@ def write_element_properties(element: Element, text_output: TextIO): write_value("SPDXID", element.spdx_id, text_output) write_value("name", element.name, text_output) - write_creation_info(element.creation_info, text_output) + write_creation_info(element.creation_info, text_output, True) write_value("summary", element.summary, text_output) write_value("description", element.description, text_output) write_value("comment", element.comment, text_output) diff --git a/src/spdx3/writer/console/hash_writer.py b/src/spdx3/writer/console/hash_writer.py index cee4bee53..ff3969311 100644 --- a/src/spdx3/writer/console/hash_writer.py +++ b/src/spdx3/writer/console/hash_writer.py @@ -15,9 +15,9 @@ from spdx3.writer.console.integrity_method_writer import write_integrity_method -def write_hash(hash_object: Hash, text_output: TextIO, heading: bool): +def write_hash(hash_object: Hash, text_output: TextIO, heading: bool, indent: bool = True): if heading: text_output.write("## Hash\n") - write_value("algorithm", hash_object.algorithm.name, text_output) - write_value("hash_value", hash_object.hash_value, text_output) - write_integrity_method(hash_object, text_output) + write_value("algorithm", hash_object.algorithm.name, text_output, indent) + write_value("hash_value", hash_object.hash_value, text_output, indent) + write_integrity_method(hash_object, text_output, indent) diff --git a/src/spdx3/writer/console/integrity_method_writer.py b/src/spdx3/writer/console/integrity_method_writer.py index d42f14505..566ddda46 100644 --- a/src/spdx3/writer/console/integrity_method_writer.py +++ b/src/spdx3/writer/console/integrity_method_writer.py @@ -14,5 +14,5 @@ from spdx3.writer.console.console import write_value -def write_integrity_method(integrity_method: IntegrityMethod, text_output: TextIO): - write_value("comment", integrity_method.comment, text_output) +def write_integrity_method(integrity_method: IntegrityMethod, text_output: TextIO, indent: bool = True): + write_value("comment", integrity_method.comment, text_output, indent) From 3601002db612d1c0f3710745d9c7699ec42ec709 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 17:06:52 +0100 Subject: [PATCH 146/354] [spdx-3.0] bump_checksum: fix type hint Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/checksum.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/checksum.py b/src/spdx3/bump_from_spdx2/checksum.py index a1ce4dadf..e583d0f50 100644 --- a/src/spdx3/bump_from_spdx2/checksum.py +++ b/src/spdx3/bump_from_spdx2/checksum.py @@ -9,11 +9,10 @@ # See the License for the specific language governing permissions and # limitations under the License. from spdx.model.checksum import Checksum as Spdx2_Checksum, ChecksumAlgorithm -from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.hash import HashAlgorithm, Hash -def bump_checksum(spdx2_checksum: Spdx2_Checksum) -> IntegrityMethod: +def bump_checksum(spdx2_checksum: Spdx2_Checksum) -> Hash: algorithm: HashAlgorithm = convert_checksum_algorithm_to_hash_algorithm(spdx2_checksum.algorithm) value: str = spdx2_checksum.value From 881975fcab20a43e11a3e46368bd8b93775ae77a Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 17:08:01 +0100 Subject: [PATCH 147/354] [spdx-3.0] add ExternalDocumentRef bump Signed-off-by: Meret Behrens --- .../bump_from_spdx2/creation_information.py | 6 ++--- .../bump_from_spdx2/external_document_ref.py | 24 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 src/spdx3/bump_from_spdx2/external_document_ref.py diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index 8c3696473..321d2adfd 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -12,6 +12,7 @@ from semantic_version import Version +from spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.spdx_document import SpdxDocument @@ -37,14 +38,13 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo) -> SpdxDo print_missing_conversion("creation_info.creator_comment", 0) data_license = spdx2_creation_info.data_license # creation_info.external_document_refs -> spdx_document.imports - imports = spdx2_creation_info.external_document_refs - print_missing_conversion("creation_info.external_document_refs", 0, "ExternalDocumentRef -> ExternalMap") + imports = [bump_external_document_ref(external_document_ref) for external_document_ref in spdx2_creation_info.external_document_refs] # creation_info.license_list_version -> ? print_missing_conversion("creation_info.license_list_version", 0) # creation_info.document_comment -> spdx_document.comment document_comment = spdx2_creation_info.document_comment creation_information = CreationInformation(Version("3.0.0"), created, None, ["core", "software", "licensing"], data_license) spdx_document = SpdxDocument(spdx_id=spdx_id, creation_info=creation_information, name=name, - comment=document_comment, elements=[], root_elements=[]) + comment=document_comment, elements=[], root_elements=[], imports=imports) return spdx_document diff --git a/src/spdx3/bump_from_spdx2/external_document_ref.py b/src/spdx3/bump_from_spdx2/external_document_ref.py new file mode 100644 index 000000000..4a7f4b2df --- /dev/null +++ b/src/spdx3/bump_from_spdx2/external_document_ref.py @@ -0,0 +1,24 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import List + +from spdx.model.external_document_ref import ExternalDocumentRef +from spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx3.model.external_map import ExternalMap +from spdx3.model.hash import Hash + + +def bump_external_document_ref(external_document_ref: ExternalDocumentRef) -> ExternalMap: + external_id: str = external_document_ref.document_ref_id + verified_using: List[Hash] = [bump_checksum(external_document_ref.checksum)] + location_hint: str = external_document_ref.document_uri + + return ExternalMap(external_id, verified_using, location_hint) From f67cf5f92fc95195ab44a6593c87662dd80848d8 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 17:08:14 +0100 Subject: [PATCH 148/354] [spdx-3.0, writer] fix output Signed-off-by: Meret Behrens --- src/spdx3/writer/console/external_map_writer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx3/writer/console/external_map_writer.py b/src/spdx3/writer/console/external_map_writer.py index fc9456a7a..a0c53f72a 100644 --- a/src/spdx3/writer/console/external_map_writer.py +++ b/src/spdx3/writer/console/external_map_writer.py @@ -18,7 +18,7 @@ def write_external_map(external_map: ExternalMap, text_output: TextIO): write_value("external_id", external_map.external_id, text_output) - write_optional_heading(external_map.verified_using, "# Verified using", text_output) + write_optional_heading(external_map.verified_using, "verified using\n", text_output) for integrity_method in external_map.verified_using: # for now Hash is the only child class of the abstract class IntegrityMethod, as soon as there are more inherited # classes we need to implement a logic that determines the correct write function for the "integrity_method" object From 67965cbfbaa6881833c4be9c7ae9e82629183c7e Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 19 Jan 2023 17:08:42 +0100 Subject: [PATCH 149/354] [spdx-3.0, bump] fix test Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/spdx_document.py | 4 +++- tests/spdx3/bump/test_spdx_document_bump.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx3/bump_from_spdx2/spdx_document.py index 44eb2c8bd..fd7afa768 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -28,6 +28,8 @@ def bump_spdx_document(document: Spdx2_Document) -> SpdxIdMap: spdx_document: SpdxDocument = bump_creation_information(document.creation_info) creation_info: CreationInformation = spdx_document.creation_info + spdx_id_map.add_element(spdx_document) + for spdx2_package in document.packages: package = bump_package(spdx2_package, creation_info) spdx_id_map.add_element(package) @@ -53,7 +55,7 @@ def bump_spdx_document(document: Spdx2_Document) -> SpdxIdMap: spdx_id_map.add_element(annotation) spdx_document.elements.append(annotation.spdx_id) - spdx_id_map.add_element(spdx_document) + print("\n") return spdx_id_map diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index bdde7fcc2..6dae21dad 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -27,4 +27,4 @@ def test_bump_spdx_document(): assert "SPDXRef-Package" in list(spdx_id_map.get_full_map().keys()) assert len( - spdx_id_map.get_full_map().values()) == 4 # document_fixture has exactly one package, one file and one snippet which are added to the elements list during bump_from_spdx2 + spdx_id_map.get_full_map().values()) == 6 From 74e98c3f7e77efe374b3471290cfeb0c4d38e020 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 23 Jan 2023 10:40:09 +0100 Subject: [PATCH 150/354] [spdx-3.0] transform SpdxNoAssertion to None Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/bump_utils.py | 24 ++++++++++++++++++++++ src/spdx3/bump_from_spdx2/package.py | 3 ++- tests/spdx3/bump/test_bump_utils.py | 27 +++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/spdx3/bump_from_spdx2/bump_utils.py create mode 100644 tests/spdx3/bump/test_bump_utils.py diff --git a/src/spdx3/bump_from_spdx2/bump_utils.py b/src/spdx3/bump_from_spdx2/bump_utils.py new file mode 100644 index 000000000..103789c90 --- /dev/null +++ b/src/spdx3/bump_from_spdx2/bump_utils.py @@ -0,0 +1,24 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional, Union + +from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx.model.spdx_none import SpdxNone + + +def handle_no_assertion_or_none(field: Union[SpdxNone, SpdxNoAssertion, str], field_name: str) -> Optional[str]: + if isinstance(field, SpdxNone): + print(f"{field_name}: Missing conversion for SpdxNone.") + return None + if isinstance(field, SpdxNoAssertion): + return None + if isinstance(field, str): + return field diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index 30488ee5b..5dafac12b 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -8,6 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none from spdx3.bump_from_spdx2.checksum import bump_checksum from spdx3.model.creation_information import CreationInformation @@ -21,7 +22,7 @@ def bump_package(spdx2_package: Spdx2_Package, creation_information: CreationInformation) -> Package: spdx_id = spdx2_package.spdx_id name = spdx2_package.name - download_location = spdx2_package.download_location + download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") # package2.version -> ? print("\n") print_missing_conversion("package2.version", 0) diff --git a/tests/spdx3/bump/test_bump_utils.py b/tests/spdx3/bump/test_bump_utils.py new file mode 100644 index 000000000..dc32e63c2 --- /dev/null +++ b/tests/spdx3/bump/test_bump_utils.py @@ -0,0 +1,27 @@ +# Copyright (c) 2022 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import pytest + +from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx.model.spdx_none import SpdxNone +from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none + + +@pytest.mark.parametrize("input_argument,expected_value,expected_stdout", + [(SpdxNone(), None, "test_field: Missing conversion for SpdxNone.\n"), + (SpdxNoAssertion(), None, ""), ("test_string", "test_string", "")]) +def test_handle_no_assertion_or_none(input_argument, expected_value, expected_stdout, capsys): + value = handle_no_assertion_or_none(input_argument, "test_field") + + captured = capsys.readouterr() + + assert value == expected_value + assert captured.out == expected_stdout From 03e4da185829fedc4bb3a71ff9ea99f8d9382373 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Mon, 23 Jan 2023 10:40:49 +0100 Subject: [PATCH 151/354] [spdx-3.0] add cli tool to parse spdx2.x files and bump the input to the prototype of spdx 3.0 Signed-off-by: Meret Behrens --- pyproject.toml | 1 + src/spdx3/clitools/__init__.py | 0 src/spdx3/clitools/pyspdxtools3.py | 62 ++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 src/spdx3/clitools/__init__.py create mode 100644 src/spdx3/clitools/pyspdxtools3.py diff --git a/pyproject.toml b/pyproject.toml index d4380535c..ed52dd970 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,7 @@ development = ["black", "flake8", "isort", "networkx", "pytest"] [project.scripts] pyspdxtools = "spdx_tools.spdx.clitools.pyspdxtools:main" +pyspdxtools3 = "spdx3.clitools.pyspdxtools3:main" [tool.setuptools] zip-safe = false # because of the uses of __file__: https://github.com/spdx/tools-python/issues/257 diff --git a/src/spdx3/clitools/__init__.py b/src/spdx3/clitools/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx3/clitools/pyspdxtools3.py b/src/spdx3/clitools/pyspdxtools3.py new file mode 100644 index 000000000..4609a32c7 --- /dev/null +++ b/src/spdx3/clitools/pyspdxtools3.py @@ -0,0 +1,62 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import sys +from typing import List + +import click +from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document + +from spdx.model.document import Document +from spdx.parser.parse_anything import parse_file +from spdx.validation.document_validator import validate_full_spdx_document +from spdx.validation.validation_message import ValidationMessage +from spdx3.spdx_id_map import SpdxIdMap +from spdx3.writer.console.spdx_id_map_writer import write_spdx_id_map + + +@click.command() +@click.option("--infile", "-i", prompt="input file path", + help="The file containing the document to be validated or converted.") +@click.option("--outfile", "-o", + help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion).") +@click.option("--version", help='The SPDX version to be used during parsing and validation (format "SPDX-2.3").', + default="SPDX-2.3") +@click.option("--novalidation", is_flag=True, help="Don't validate the provided document.") +def main(infile: str, outfile: str, version: str, novalidation: bool): + """ + CLI-tool to parse and validate a SPDX 2.x document and migrate it into the prototype of SPDX 3.0. As there is no + definition for a serialization yet output can only be written to stdout. + To use, run: 'pyspdxtools3 --infile -o -' + """ + try: + document: Document = parse_file(infile) + + if not novalidation: + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document, version) + if validation_messages: + print("The document is invalid. The following issues have been found:") + for message in validation_messages: + print(message.validation_message) + sys.exit(1) + else: + print("The document is valid.") + + if outfile == "-": + spdx_id_map: SpdxIdMap = bump_spdx_document(document) + write_spdx_id_map(spdx_id_map, sys.stdout) + + except NotImplementedError as err: + print(err.args[0]) + sys.exit(1) + + +if __name__ == "__main__": + main() From 0cfdc4af4596aaa513632e2e9fb33c5363d07df1 Mon Sep 17 00:00:00 2001 From: Maximilian Huber Date: Tue, 24 Jan 2023 17:42:56 +0100 Subject: [PATCH 152/354] do some cleanup Signed-off-by: Maximilian Huber --- src/spdx3/bump_from_spdx2/annotation.py | 1 - src/spdx3/bump_from_spdx2/creation_information.py | 1 - src/spdx3/bump_from_spdx2/file.py | 1 - src/spdx3/bump_from_spdx2/message.py | 5 ++++- src/spdx3/bump_from_spdx2/package.py | 1 - src/spdx3/bump_from_spdx2/snippet.py | 1 - src/spdx3/bump_from_spdx2/spdx_document.py | 1 - src/spdx3/clitools/pyspdxtools3.py | 6 +++--- 8 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py index 110ad6f2b..75e7483e2 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -22,7 +22,6 @@ def bump_annotation(spdx2_annotation: Spdx2_Annotation, creation_info: CreationI spdx_id: str = f"SPDXRef-Annotation-{counter}" creation_info.created = spdx2_annotation.annotation_date # creation_info.created_by = bump_actor(spdx2_annotation.annotator) waiting for entity implementation - print("\n") print_missing_conversion("annotation.annotator", 1, "of Entity") annotation_type: AnnotationType = AnnotationType[spdx2_annotation.annotation_type.name] subject: List[str] = [spdx2_annotation.spdx_id] diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index 321d2adfd..dcd3794bf 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -29,7 +29,6 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo) -> SpdxDo name = spdx2_creation_info.name # creation_info.document_namespace -> ? - print("\n") print_missing_conversion("creation_info.document_namespace", 0) # creation_info.creators -> creation_information.creators (not implemented yet) print_missing_conversion("creation_info.creators", 1, "of creators") diff --git a/src/spdx3/bump_from_spdx2/file.py b/src/spdx3/bump_from_spdx2/file.py index 7282e83d6..80e905915 100644 --- a/src/spdx3/bump_from_spdx2/file.py +++ b/src/spdx3/bump_from_spdx2/file.py @@ -22,7 +22,6 @@ def bump_file(spdx2_file: Spdx2_File, creation_information: CreationInformation) spdx_id = spdx2_file.spdx_id integrity_methods = [bump_checksum(checksum) for checksum in spdx2_file.checksums] # file.checksums -> file.verifiedUsing - print("\n") # file.file_types -> file.content_type (MediaType with Cardinality 1) print_missing_conversion("file.file_type", 0, "different cardinalities") print_missing_conversion( diff --git a/src/spdx3/bump_from_spdx2/message.py b/src/spdx3/bump_from_spdx2/message.py index 65a797d1a..1c929d937 100644 --- a/src/spdx3/bump_from_spdx2/message.py +++ b/src/spdx3/bump_from_spdx2/message.py @@ -9,8 +9,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +import sys + + MISSING_CONVERSION_REASONS = {0: "missing conversion rule", 1: "missing implementation"} def print_missing_conversion(field: str, reason, additional_information: str= ""): - print(f"{field} not converted: {MISSING_CONVERSION_REASONS[reason]} {additional_information}") + print(f"{field} not converted: {MISSING_CONVERSION_REASONS[reason]} {additional_information}", file=sys.stderr) diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index 5dafac12b..f23fefbbc 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -24,7 +24,6 @@ def bump_package(spdx2_package: Spdx2_Package, creation_information: CreationInf name = spdx2_package.name download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") # package2.version -> ? - print("\n") print_missing_conversion("package2.version", 0) # package.file_name -> ? print_missing_conversion("package2.file_name", 0) diff --git a/src/spdx3/bump_from_spdx2/snippet.py b/src/spdx3/bump_from_spdx2/snippet.py index 28fa7c33e..e4121b62a 100644 --- a/src/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx3/bump_from_spdx2/snippet.py @@ -18,7 +18,6 @@ def bump_snippet(spdx2_snippet: Spdx2_Snippet, creation_information: CreationInformation) -> Snippet: spdx_id = spdx2_snippet.spdx_id - print("\n") print_missing_conversion("snippet.file_spdx_id", 0) byte_range = spdx2_snippet.byte_range line_range = spdx2_snippet.line_range diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx3/bump_from_spdx2/spdx_document.py index fd7afa768..aa440fe00 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -57,6 +57,5 @@ def bump_spdx_document(document: Spdx2_Document) -> SpdxIdMap: - print("\n") return spdx_id_map diff --git a/src/spdx3/clitools/pyspdxtools3.py b/src/spdx3/clitools/pyspdxtools3.py index 4609a32c7..5e57bc66b 100644 --- a/src/spdx3/clitools/pyspdxtools3.py +++ b/src/spdx3/clitools/pyspdxtools3.py @@ -42,12 +42,12 @@ def main(infile: str, outfile: str, version: str, novalidation: bool): if not novalidation: validation_messages: List[ValidationMessage] = validate_full_spdx_document(document, version) if validation_messages: - print("The document is invalid. The following issues have been found:") + print("The document is invalid. The following issues have been found:", file=sys.stderr) for message in validation_messages: - print(message.validation_message) + print(message.validation_message, file=sys.stderr) sys.exit(1) else: - print("The document is valid.") + print("The document is valid.", file=sys.stderr) if outfile == "-": spdx_id_map: SpdxIdMap = bump_spdx_document(document) From c7236ab32d7cc285c884ed8cf0cc5dccd204833f Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 10 Feb 2023 08:34:27 +0100 Subject: [PATCH 153/354] [spdx-3.0] allow only one subject per annotation Signed-off-by: Meret Behrens --- src/spdx3/bump_from_spdx2/annotation.py | 2 +- src/spdx3/model/annotation.py | 4 ++-- src/spdx3/writer/console/annotation_writer.py | 2 +- tests/spdx3/model/test_annotation.py | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py index 75e7483e2..202ba2055 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -24,7 +24,7 @@ def bump_annotation(spdx2_annotation: Spdx2_Annotation, creation_info: CreationI # creation_info.created_by = bump_actor(spdx2_annotation.annotator) waiting for entity implementation print_missing_conversion("annotation.annotator", 1, "of Entity") annotation_type: AnnotationType = AnnotationType[spdx2_annotation.annotation_type.name] - subject: List[str] = [spdx2_annotation.spdx_id] + subject: str = spdx2_annotation.spdx_id statement: str = spdx2_annotation.annotation_comment return Annotation(spdx_id, creation_info, annotation_type, subject, statement=statement) diff --git a/src/spdx3/model/annotation.py b/src/spdx3/model/annotation.py index ae3db1d50..847859147 100644 --- a/src/spdx3/model/annotation.py +++ b/src/spdx3/model/annotation.py @@ -32,12 +32,12 @@ class AnnotationType(Enum): @dataclass_with_properties class Annotation(Element): annotation_type: AnnotationType = None - subject: List[str] = field(default_factory=list) + subject: str = None content_type: Optional[str] = None # placeholder for MediaType statement: Optional[str] = None def __init__(self, spdx_id: str, creation_info: CreationInformation, annotation_type: AnnotationType, - subject: List[str], name: Optional[str] = None, summary: Optional[str] = None, + subject: str, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, diff --git a/src/spdx3/writer/console/annotation_writer.py b/src/spdx3/writer/console/annotation_writer.py index 95dacfcc6..66504f1ae 100644 --- a/src/spdx3/writer/console/annotation_writer.py +++ b/src/spdx3/writer/console/annotation_writer.py @@ -20,6 +20,6 @@ def write_annotation(annotation: Annotation, text_output: TextIO): text_output.write("## Annotation\n") write_element_properties(annotation, text_output) write_value("annotation_type", annotation.annotation_type.name, text_output) - text_output.write(f"subjects: {', '.join(annotation.subject)}\n") + write_value("subject", annotation.subject, text_output) write_value("content_type", annotation.content_type, text_output) write_value("statement", annotation.statement, text_output) diff --git a/tests/spdx3/model/test_annotation.py b/tests/spdx3/model/test_annotation.py index 97c618767..061c69ace 100644 --- a/tests/spdx3/model/test_annotation.py +++ b/tests/spdx3/model/test_annotation.py @@ -17,13 +17,13 @@ @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): - annotation = Annotation("SPDXRef-Annotation", creation_information, AnnotationType.OTHER, ["spdx_id1"], + annotation = Annotation("SPDXRef-Annotation", creation_information, AnnotationType.OTHER, "spdx_id1", content_type="mediaType", statement="This is a statement") assert annotation.spdx_id == "SPDXRef-Annotation" assert annotation.creation_info == creation_information assert annotation.annotation_type == AnnotationType.OTHER - assert annotation.subject == ["spdx_id1"] + assert annotation.subject == "spdx_id1" assert annotation.content_type == "mediaType" assert annotation.statement == "This is a statement" @@ -36,7 +36,7 @@ def test_invalid_initialization(creation_information): assert err.value.args[0] == ['SetterError Annotation: type of argument "annotation_type" must be ' 'spdx3.model.annotation.AnnotationType; got str instead: REVIEW', - 'SetterError Annotation: type of argument "subject" must be a list; got dict ' + 'SetterError Annotation: type of argument "subject" must be str; got dict ' "instead: {'element': 1}", 'SetterError Annotation: type of argument "content_type" must be one of (str, ' 'NoneType); got int instead: 4', From b92b1b6c825f5dad9e72c9db1f12976ae0121096 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 10 Feb 2023 08:58:10 +0100 Subject: [PATCH 154/354] [spdx-3.0] add ExternalIdentifier Signed-off-by: Meret Behrens --- src/spdx3/model/annotation.py | 7 ++-- src/spdx3/model/bom.py | 7 ++-- src/spdx3/model/bundle.py | 7 ++-- src/spdx3/model/element.py | 3 +- src/spdx3/model/external_identifier.py | 16 +++++++++ src/spdx3/model/relationship.py | 7 ++-- src/spdx3/model/software/file.py | 7 ++-- src/spdx3/model/software/package.py | 7 ++-- src/spdx3/model/software/sbom.py | 7 ++-- src/spdx3/model/software/snippet.py | 7 ++-- src/spdx3/model/spdx_document.py | 5 ++- src/spdx3/writer/console/element_writer.py | 4 +++ .../console/external_identifier_writer.py | 21 ++++++++++++ tests/spdx3/model/test_external_identifier.py | 34 +++++++++++++++++++ 14 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 src/spdx3/writer/console/external_identifier_writer.py create mode 100644 tests/spdx3/model/test_external_identifier.py diff --git a/src/spdx3/model/annotation.py b/src/spdx3/model/annotation.py index 847859147..d613c7fe3 100644 --- a/src/spdx3/model/annotation.py +++ b/src/spdx3/model/annotation.py @@ -12,6 +12,7 @@ from enum import Enum, auto from typing import Optional, List +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_reference import ExternalReference from common.typing.dataclass_with_properties import dataclass_with_properties @@ -40,8 +41,10 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, annotation_ subject: str, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, - extension: None = None, content_type: Optional[str] = None, statement: Optional[str] = None): + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, + content_type: Optional[str] = None, statement: Optional[str] = None): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/bom.py b/src/spdx3/model/bom.py index a5eacfb63..c6fb05f02 100644 --- a/src/spdx3/model/bom.py +++ b/src/spdx3/model/bom.py @@ -10,6 +10,7 @@ # limitations under the License. from typing import List, Optional +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_reference import ExternalReference from common.typing.dataclass_with_properties import dataclass_with_properties @@ -30,11 +31,13 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: L root_elements: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, - extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/bundle.py b/src/spdx3/model/bundle.py index b11e35e0e..a035507c0 100644 --- a/src/spdx3/model/bundle.py +++ b/src/spdx3/model/bundle.py @@ -10,6 +10,7 @@ # limitations under the License. from typing import Optional, List +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_reference import ExternalReference from common.typing.dataclass_with_properties import dataclass_with_properties @@ -30,11 +31,13 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: L root_elements: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, - extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index 489fe7490..4281cee81 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -12,6 +12,7 @@ from dataclasses import field from typing import Optional, List +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_reference import ExternalReference from common.typing.dataclass_with_properties import dataclass_with_properties @@ -30,7 +31,7 @@ class Element(ABC): comment: Optional[str] = None verified_using: Optional[List[IntegrityMethod]] = field(default_factory=list) external_references: Optional[List[ExternalReference]] = field(default_factory=list) - external_identifier: None = None # placeholder for ExternalIdentifier + external_identifier: Optional[List[ExternalIdentifier]] = field(default_factory=list) extension: None = None # placeholder for extension @abstractmethod diff --git a/src/spdx3/model/external_identifier.py b/src/spdx3/model/external_identifier.py index 8993a9d93..2818af29d 100644 --- a/src/spdx3/model/external_identifier.py +++ b/src/spdx3/model/external_identifier.py @@ -9,6 +9,11 @@ # See the License for the specific language governing permissions and # limitations under the License. from enum import Enum, auto +from typing import Optional + +from common.typing.type_checks import check_types_and_set_values + +from common.typing.dataclass_with_properties import dataclass_with_properties class ExternalIdentifierType(Enum): @@ -19,3 +24,14 @@ class ExternalIdentifierType(Enum): PKG_URL = auto() SWHID = auto() SWID = auto() + + +@dataclass_with_properties +class ExternalIdentifier: + external_identifier_type: ExternalIdentifierType + identifier: str + comment: Optional[str] = None + + def __init__(self, external_identifier_type: ExternalIdentifierType, identifier: str, + comment: Optional[str] = None): + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/relationship.py b/src/spdx3/model/relationship.py index 98c773889..eaabbf6d9 100644 --- a/src/spdx3/model/relationship.py +++ b/src/spdx3/model/relationship.py @@ -11,6 +11,7 @@ from enum import Enum, auto from typing import List, Optional +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_reference import ExternalReference from common.typing.type_checks import check_types_and_set_values @@ -84,8 +85,10 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, from_elemen relationship_type: RelationshipType, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, - extension: None = None, completeness: Optional[RelationshipCompleteness] = None): + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, + completeness: Optional[RelationshipCompleteness] = None): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index 1705024b5..c80ce7df9 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -10,6 +10,7 @@ # limitations under the License. from typing import Optional, List +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_reference import ExternalReference from common.typing.type_checks import check_types_and_set_values @@ -31,10 +32,12 @@ class File(Artifact): def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, - extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, + originated_by: None = None, content_identifier: Optional[str] = None, file_purpose: Optional[List[SoftwarePurpose]] = None, content_type: Optional[str] = None): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier file_purpose = [] if file_purpose is None else file_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 7263a9817..7962cf7ea 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -10,6 +10,7 @@ # limitations under the License. from typing import Optional, List +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_reference import ExternalReference from spdx3.model.creation_information import CreationInformation @@ -33,11 +34,13 @@ class Package(Artifact): def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, - extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, + originated_by: None = None, content_identifier: Optional[str] = None, package_purpose: Optional[List[SoftwarePurpose]] = None, download_location: Optional[str] = None, package_uri: Optional[str] = None, homepage: Optional[str] = None): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier package_purpose = [] if package_purpose is None else package_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index 1bb4657fa..9d0cf300d 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -10,6 +10,7 @@ # limitations under the License. from typing import Optional, List +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_reference import ExternalReference from common.typing.type_checks import check_types_and_set_values @@ -31,11 +32,13 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: L root_elements: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, - extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, + namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index da902bb5e..307127fce 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -10,6 +10,7 @@ # limitations under the License. from typing import Optional, Tuple, List +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_reference import ExternalReference from common.typing.type_checks import check_types_and_set_values @@ -32,11 +33,13 @@ class Snippet(Artifact): def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, - extension: None = None, originated_by: None = None, content_identifier: Optional[str] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, + originated_by: None = None, content_identifier: Optional[str] = None, snippet_purpose: Optional[List[SoftwarePurpose]] = None, byte_range: Optional[Tuple[int, int]] = None, line_range: Optional[Tuple[int, int]] = None): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier snippet_purpose = [] if snippet_purpose is None else snippet_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index 1394f3ed2..cf03de04c 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -10,6 +10,7 @@ # limitations under the License. from typing import Optional, List +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_reference import ExternalReference from common.typing.type_checks import check_types_and_set_values @@ -31,11 +32,13 @@ class SpdxDocument(Bundle): def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, elements: List[str], root_elements: List[str], summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, external_identifier: None = None, extension: None = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports check_types_and_set_values(self, locals()) diff --git a/src/spdx3/writer/console/element_writer.py b/src/spdx3/writer/console/element_writer.py index ce6e5e82a..618e03246 100644 --- a/src/spdx3/writer/console/element_writer.py +++ b/src/spdx3/writer/console/element_writer.py @@ -14,6 +14,7 @@ from spdx3.model.element import Element from spdx3.writer.console.console import write_value from spdx3.writer.console.creation_information_writer import write_creation_info +from spdx3.writer.console.external_identifier_writer import write_external_identifier from spdx3.writer.console.external_reference_writer import write_external_reference from spdx3.writer.console.hash_writer import write_hash @@ -33,6 +34,9 @@ def write_element_properties(element: Element, text_output: TextIO): write_optional_heading(element.external_references, "External References", text_output) for external_reference in element.external_references: write_external_reference(external_reference, text_output) + write_optional_heading(element.external_identifier, "External Identifier", text_output) + for external_identifier in element.external_identifier: + write_external_identifier(external_identifier, text_output) diff --git a/src/spdx3/writer/console/external_identifier_writer.py b/src/spdx3/writer/console/external_identifier_writer.py new file mode 100644 index 000000000..33fc4fe6e --- /dev/null +++ b/src/spdx3/writer/console/external_identifier_writer.py @@ -0,0 +1,21 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.writer.console.console import write_value + +from spdx3.model.external_identifier import ExternalIdentifier + + +def write_external_identifier(external_identifier: ExternalIdentifier, text_output: TextIO): + write_value("type", external_identifier.external_identifier_type.name, text_output) + write_value("identifier", external_identifier.identifier, text_output) + write_value("comment", external_identifier.comment, text_output) diff --git a/tests/spdx3/model/test_external_identifier.py b/tests/spdx3/model/test_external_identifier.py new file mode 100644 index 000000000..ff85e2c8d --- /dev/null +++ b/tests/spdx3/model/test_external_identifier.py @@ -0,0 +1,34 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import pytest + +from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType + + +def test_correct_initialization(): + external_identifier = ExternalIdentifier(ExternalIdentifierType.CPE22, "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", + "This is a comment") + assert external_identifier.external_identifier_type == ExternalIdentifierType.CPE22 + assert external_identifier.identifier == "cpe:/o:canonical:ubuntu_linux:10.04:-:lts" + assert external_identifier.comment == "This is a comment" + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + ExternalIdentifier("CPE22", ["identifier", "another_identifier"], 34) + + assert err.value.args[0] == ['SetterError ExternalIdentifier: type of argument "external_identifier_type" ' + 'must be spdx3.model.external_identifier.ExternalIdentifierType; got str ' + 'instead: CPE22', + 'SetterError ExternalIdentifier: type of argument "identifier" must be str; ' + "got list instead: ['identifier', 'another_identifier']", + 'SetterError ExternalIdentifier: type of argument "comment" must be one of ' + '(str, NoneType); got int instead: 34'] From 658b2de27dc3638019fce14f3e9d66c8d7cee107 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 10 Feb 2023 09:00:21 +0100 Subject: [PATCH 155/354] [spdx-3.0] update README.md Signed-off-by: Meret Behrens --- src/spdx3/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx3/README.md b/src/spdx3/README.md index 0fed300d0..5e4c044ba 100644 --- a/src/spdx3/README.md +++ b/src/spdx3/README.md @@ -1,2 +1,2 @@ -This implementation is mainly based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: d1d333acb93f8f1c7889dd156ffe5ee59b468d62). +This implementation is mainly based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 4e7086133a4ec9b7385ce1757a01a33c22711c02). From 48173f18d9571c416dd2ae8252948b640bcb2d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 13 Mar 2023 09:30:25 +0100 Subject: [PATCH 156/354] auto-format spdx3 modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/annotation.py | 5 +---- src/spdx3/bump_from_spdx2/checksum.py | 2 +- .../bump_from_spdx2/creation_information.py | 12 ++++++------ src/spdx3/bump_from_spdx2/file.py | 6 ++---- src/spdx3/bump_from_spdx2/message.py | 3 +-- src/spdx3/bump_from_spdx2/package.py | 10 ++++------ src/spdx3/bump_from_spdx2/relationship.py | 19 ++++++++----------- src/spdx3/bump_from_spdx2/snippet.py | 6 ++---- src/spdx3/bump_from_spdx2/spdx_document.py | 8 +++----- src/spdx3/clitools/pyspdxtools3.py | 2 +- src/spdx3/model/annotation.py | 11 +++-------- src/spdx3/model/bom.py | 8 +++----- src/spdx3/model/bundle.py | 8 +++----- src/spdx3/model/creation_information.py | 4 ++-- src/spdx3/model/element.py | 6 ++---- src/spdx3/model/external_identifier.py | 3 +-- src/spdx3/model/external_map.py | 5 +++-- src/spdx3/model/external_reference.py | 3 +-- src/spdx3/model/namespace_map.py | 7 ++++--- src/spdx3/model/relationship.py | 10 +++------- src/spdx3/model/software/file.py | 11 ++++------- src/spdx3/model/software/package.py | 11 ++++------- src/spdx3/model/software/sbom.py | 12 ++++-------- src/spdx3/model/software/snippet.py | 11 ++++------- src/spdx3/model/software/software_purpose.py | 2 +- src/spdx3/model/spdx_collection.py | 1 - src/spdx3/model/spdx_document.py | 12 ++++-------- src/spdx3/writer/console/annotation_writer.py | 3 +-- src/spdx3/writer/console/artifact_writer.py | 3 +-- src/spdx3/writer/console/element_writer.py | 4 ---- .../console/external_identifier_writer.py | 3 +-- .../console/external_reference_writer.py | 1 - .../writer/console/spdx_id_map_writer.py | 7 +++---- 33 files changed, 81 insertions(+), 138 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py index 202ba2055..efd4947eb 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -8,13 +8,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import List +from spdx.model.annotation import Annotation as Spdx2_Annotation from spdx3.bump_from_spdx2.message import print_missing_conversion - from spdx3.model.annotation import Annotation, AnnotationType - -from spdx.model.annotation import Annotation as Spdx2_Annotation from spdx3.model.creation_information import CreationInformation diff --git a/src/spdx3/bump_from_spdx2/checksum.py b/src/spdx3/bump_from_spdx2/checksum.py index e583d0f50..5ec72e048 100644 --- a/src/spdx3/bump_from_spdx2/checksum.py +++ b/src/spdx3/bump_from_spdx2/checksum.py @@ -21,7 +21,7 @@ def bump_checksum(spdx2_checksum: Spdx2_Checksum) -> Hash: def convert_checksum_algorithm_to_hash_algorithm(checksum_algorithm: ChecksumAlgorithm) -> HashAlgorithm: if checksum_algorithm.name.startswith("BLAKE"): - return HashAlgorithm[checksum_algorithm.name.replace("_","")] + return HashAlgorithm[checksum_algorithm.name.replace("_", "")] if checksum_algorithm == ChecksumAlgorithm.ADLER32: return HashAlgorithm.OTHER return HashAlgorithm[checksum_algorithm.name] diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index dcd3794bf..b24926c6a 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -12,13 +12,11 @@ from semantic_version import Version +from spdx.model.document import CreationInfo as Spdx2_CreationInfo from spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref from spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx3.model.spdx_document import SpdxDocument - from spdx3.model.creation_information import CreationInformation - -from spdx.model.document import CreationInfo as Spdx2_CreationInfo +from spdx3.model.spdx_document import SpdxDocument def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo) -> SpdxDocument: @@ -37,12 +35,14 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo) -> SpdxDo print_missing_conversion("creation_info.creator_comment", 0) data_license = spdx2_creation_info.data_license # creation_info.external_document_refs -> spdx_document.imports - imports = [bump_external_document_ref(external_document_ref) for external_document_ref in spdx2_creation_info.external_document_refs] + imports = [bump_external_document_ref(external_document_ref) for external_document_ref in + spdx2_creation_info.external_document_refs] # creation_info.license_list_version -> ? print_missing_conversion("creation_info.license_list_version", 0) # creation_info.document_comment -> spdx_document.comment document_comment = spdx2_creation_info.document_comment - creation_information = CreationInformation(Version("3.0.0"), created, None, ["core", "software", "licensing"], data_license) + creation_information = CreationInformation(Version("3.0.0"), created, None, ["core", "software", "licensing"], + data_license) spdx_document = SpdxDocument(spdx_id=spdx_id, creation_info=creation_information, name=name, comment=document_comment, elements=[], root_elements=[], imports=imports) diff --git a/src/spdx3/bump_from_spdx2/file.py b/src/spdx3/bump_from_spdx2/file.py index 80e905915..fb8dbbe53 100644 --- a/src/spdx3/bump_from_spdx2/file.py +++ b/src/spdx3/bump_from_spdx2/file.py @@ -8,13 +8,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from spdx.model.file import File as Spdx2_File from spdx3.bump_from_spdx2.checksum import bump_checksum from spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx3.model.software.file import File - from spdx3.model.creation_information import CreationInformation - -from spdx.model.file import File as Spdx2_File +from spdx3.model.software.file import File def bump_file(spdx2_file: Spdx2_File, creation_information: CreationInformation) -> File: diff --git a/src/spdx3/bump_from_spdx2/message.py b/src/spdx3/bump_from_spdx2/message.py index 1c929d937..4551742f3 100644 --- a/src/spdx3/bump_from_spdx2/message.py +++ b/src/spdx3/bump_from_spdx2/message.py @@ -11,9 +11,8 @@ import sys - MISSING_CONVERSION_REASONS = {0: "missing conversion rule", 1: "missing implementation"} -def print_missing_conversion(field: str, reason, additional_information: str= ""): +def print_missing_conversion(field: str, reason, additional_information: str = ""): print(f"{field} not converted: {MISSING_CONVERSION_REASONS[reason]} {additional_information}", file=sys.stderr) diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index f23fefbbc..40dd1643a 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -8,15 +8,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from spdx.model.package import Package as Spdx2_Package from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none from spdx3.bump_from_spdx2.checksum import bump_checksum -from spdx3.model.creation_information import CreationInformation - from spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx3.model.software.software_purpose import SoftwarePurpose - -from spdx.model.package import Package as Spdx2_Package +from spdx3.model.creation_information import CreationInformation from spdx3.model.software.package import Package +from spdx3.model.software.software_purpose import SoftwarePurpose def bump_package(spdx2_package: Spdx2_Package, creation_information: CreationInformation) -> Package: @@ -48,7 +46,7 @@ def bump_package(spdx2_package: Spdx2_Package, creation_information: CreationInf print_missing_conversion("package2.external_references", 1, "of ExternalReferences / ExternalIdentifiers") print_missing_conversion("package2.attribution_texts", 0) package_purpose = [SoftwarePurpose[ - spdx2_package.primary_package_purpose.name]] if spdx2_package.primary_package_purpose else [] + spdx2_package.primary_package_purpose.name]] if spdx2_package.primary_package_purpose else [] print_missing_conversion("package2.release_date, package2.built_date, package2.valid_until_date", 0) package = Package(spdx_id, creation_information, name, verified_using=integrity_methods, diff --git a/src/spdx3/bump_from_spdx2/relationship.py b/src/spdx3/bump_from_spdx2/relationship.py index f4b60135c..b3907339c 100644 --- a/src/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx3/bump_from_spdx2/relationship.py @@ -10,23 +10,20 @@ # limitations under the License. from typing import Tuple, Optional -from spdx.model.spdx_none import SpdxNone - -from spdx.model.spdx_no_assertion import SpdxNoAssertion - -from spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness -from spdx3.model.creation_information import CreationInformation - from spdx.model.relationship import Relationship as Spdx2_Relationship from spdx.model.relationship import RelationshipType as Spdx2_RelationshipType +from spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx.model.spdx_none import SpdxNone +from spdx3.model.creation_information import CreationInformation +from spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness def bump_relationship(spdx2_relationship: Spdx2_Relationship, creation_information: CreationInformation, counter: int) -> Relationship: relationship_type, swap_direction = bump_relationship_type(spdx2_relationship.relationship_type) - if isinstance(spdx2_relationship.related_spdx_element_id, SpdxNoAssertion): # how to translate none/ no assertion to element? + if isinstance(spdx2_relationship.related_spdx_element_id, + SpdxNoAssertion): # how to translate none/ no assertion to element? completeness = RelationshipCompleteness.UNKNOWN elif isinstance(spdx2_relationship.related_spdx_element_id, SpdxNone): completeness = RelationshipCompleteness.KNOWN @@ -41,8 +38,8 @@ def bump_relationship(spdx2_relationship: Spdx2_Relationship, to = [spdx2_relationship.related_spdx_element_id] comment = spdx2_relationship.comment - relationship = Relationship(f"SPDXRef-Relationship-{counter}", creation_information, from_element, to, relationship_type, - comment=comment, completeness=completeness) + relationship = Relationship(f"SPDXRef-Relationship-{counter}", creation_information, from_element, to, + relationship_type, comment=comment, completeness=completeness) return relationship diff --git a/src/spdx3/bump_from_spdx2/snippet.py b/src/spdx3/bump_from_spdx2/snippet.py index e4121b62a..030893fad 100644 --- a/src/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx3/bump_from_spdx2/snippet.py @@ -8,12 +8,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from spdx.model.snippet import Snippet as Spdx2_Snippet from spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx3.model.software.snippet import Snippet - from spdx3.model.creation_information import CreationInformation - -from spdx.model.snippet import Snippet as Spdx2_Snippet +from spdx3.model.software.snippet import Snippet def bump_snippet(spdx2_snippet: Spdx2_Snippet, creation_information: CreationInformation) -> Snippet: diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx3/bump_from_spdx2/spdx_document.py index aa440fe00..bd94fba84 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -8,6 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from spdx.model.document import Document as Spdx2_Document from spdx3.bump_from_spdx2.annotation import bump_annotation from spdx3.bump_from_spdx2.creation_information import bump_creation_information from spdx3.bump_from_spdx2.file import bump_file @@ -16,13 +17,13 @@ from spdx3.bump_from_spdx2.snippet import bump_snippet from spdx3.model.creation_information import CreationInformation from spdx3.model.spdx_document import SpdxDocument - -from spdx.model.document import Document as Spdx2_Document from spdx3.spdx_id_map import SpdxIdMap """ We want to implement a bump_from_spdx2 from the data model in src.spdx to the data model in src.spdx3. As there are many fundamental differences between these version we want each bump_from_spdx2 method to take the object from src.spdx and return all objects that the input is translated to.""" + + def bump_spdx_document(document: Spdx2_Document) -> SpdxIdMap: spdx_id_map = SpdxIdMap() spdx_document: SpdxDocument = bump_creation_information(document.creation_info) @@ -55,7 +56,4 @@ def bump_spdx_document(document: Spdx2_Document) -> SpdxIdMap: spdx_id_map.add_element(annotation) spdx_document.elements.append(annotation.spdx_id) - - return spdx_id_map - diff --git a/src/spdx3/clitools/pyspdxtools3.py b/src/spdx3/clitools/pyspdxtools3.py index 5e57bc66b..f54c31f73 100644 --- a/src/spdx3/clitools/pyspdxtools3.py +++ b/src/spdx3/clitools/pyspdxtools3.py @@ -12,12 +12,12 @@ from typing import List import click -from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document from spdx.model.document import Document from spdx.parser.parse_anything import parse_file from spdx.validation.document_validator import validate_full_spdx_document from spdx.validation.validation_message import ValidationMessage +from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document from spdx3.spdx_id_map import SpdxIdMap from spdx3.writer.console.spdx_id_map_writer import write_spdx_id_map diff --git a/src/spdx3/model/annotation.py b/src/spdx3/model/annotation.py index d613c7fe3..daabf0b79 100644 --- a/src/spdx3/model/annotation.py +++ b/src/spdx3/model/annotation.py @@ -8,21 +8,16 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from dataclasses import field from enum import Enum, auto from typing import Optional, List -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference - from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values - -from spdx3.model.integrity_method import IntegrityMethod - from spdx3.model.creation_information import CreationInformation - from spdx3.model.element import Element +from spdx3.model.external_identifier import ExternalIdentifier +from spdx3.model.external_reference import ExternalReference +from spdx3.model.integrity_method import IntegrityMethod class AnnotationType(Enum): diff --git a/src/spdx3/model/bom.py b/src/spdx3/model/bom.py index c6fb05f02..8e4a52bec 100644 --- a/src/spdx3/model/bom.py +++ b/src/spdx3/model/bom.py @@ -10,15 +10,13 @@ # limitations under the License. from typing import List, Optional -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference - from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values -from spdx3.model.creation_information import CreationInformation -from spdx3.model.element import Element from spdx3.model.bundle import Bundle +from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_map import ExternalMap +from spdx3.model.external_reference import ExternalReference from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.namespace_map import NamespaceMap diff --git a/src/spdx3/model/bundle.py b/src/spdx3/model/bundle.py index a035507c0..fe269a786 100644 --- a/src/spdx3/model/bundle.py +++ b/src/spdx3/model/bundle.py @@ -10,17 +10,15 @@ # limitations under the License. from typing import Optional, List -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference - from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values from spdx3.model.creation_information import CreationInformation -from spdx3.model.element import Element -from spdx3.model.spdx_collection import SpdxCollection +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_map import ExternalMap +from spdx3.model.external_reference import ExternalReference from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.namespace_map import NamespaceMap +from spdx3.model.spdx_collection import SpdxCollection @dataclass_with_properties diff --git a/src/spdx3/model/creation_information.py b/src/spdx3/model/creation_information.py index 9044d4b02..a3f5729a2 100644 --- a/src/spdx3/model/creation_information.py +++ b/src/spdx3/model/creation_information.py @@ -10,11 +10,11 @@ # limitations under the License. from datetime import datetime from typing import List -from semantic_version import Version -from common.typing.type_checks import check_types_and_set_values +from semantic_version import Version from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values @dataclass_with_properties diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index 4281cee81..8d1218479 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -12,12 +12,10 @@ from dataclasses import field from typing import Optional, List -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference - from common.typing.dataclass_with_properties import dataclass_with_properties - from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier +from spdx3.model.external_reference import ExternalReference from spdx3.model.integrity_method import IntegrityMethod diff --git a/src/spdx3/model/external_identifier.py b/src/spdx3/model/external_identifier.py index 2818af29d..ada3f6c4b 100644 --- a/src/spdx3/model/external_identifier.py +++ b/src/spdx3/model/external_identifier.py @@ -11,9 +11,8 @@ from enum import Enum, auto from typing import Optional -from common.typing.type_checks import check_types_and_set_values - from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values class ExternalIdentifierType(Enum): diff --git a/src/spdx3/model/external_map.py b/src/spdx3/model/external_map.py index 128df5aa2..22d91e470 100644 --- a/src/spdx3/model/external_map.py +++ b/src/spdx3/model/external_map.py @@ -10,9 +10,9 @@ # limitations under the License. from dataclasses import field from typing import Optional, List -from common.typing.type_checks import check_types_and_set_values from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values from spdx3.model.integrity_method import IntegrityMethod @@ -22,6 +22,7 @@ class ExternalMap: verified_using: Optional[List[IntegrityMethod]] = field(default_factory=list) location_hint: Optional[str] = None # anyURI - def __init__(self, external_id: str, verified_using: Optional[List[IntegrityMethod]]= None, location_hint: Optional[str] = None): + def __init__(self, external_id: str, verified_using: Optional[List[IntegrityMethod]] = None, + location_hint: Optional[str] = None): verified_using = [] if verified_using is None else verified_using check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/external_reference.py b/src/spdx3/model/external_reference.py index bcfdfb171..083a95cc7 100644 --- a/src/spdx3/model/external_reference.py +++ b/src/spdx3/model/external_reference.py @@ -12,9 +12,8 @@ from enum import Enum, auto from typing import Optional, List -from common.typing.type_checks import check_types_and_set_values - from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values class ExternalReferenceType(Enum): diff --git a/src/spdx3/model/namespace_map.py b/src/spdx3/model/namespace_map.py index eb06f28a6..498a3de83 100644 --- a/src/spdx3/model/namespace_map.py +++ b/src/spdx3/model/namespace_map.py @@ -9,14 +9,15 @@ # See the License for the specific language governing permissions and # limitations under the License. from typing import Optional -from common.typing.type_checks import check_types_and_set_values from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values + @dataclass_with_properties class NamespaceMap: - prefix: Optional[str] = None - namespace: Optional[str] = None # anyURI + prefix: Optional[str] = None + namespace: Optional[str] = None # anyURI def __init__(self, prefix: Optional[str] = None, namespace: Optional[str] = None): check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/relationship.py b/src/spdx3/model/relationship.py index eaabbf6d9..986efb7b8 100644 --- a/src/spdx3/model/relationship.py +++ b/src/spdx3/model/relationship.py @@ -11,16 +11,12 @@ from enum import Enum, auto from typing import List, Optional -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference - +from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values - from spdx3.model.creation_information import CreationInformation - from spdx3.model.element import Element - -from common.typing.dataclass_with_properties import dataclass_with_properties +from spdx3.model.external_identifier import ExternalIdentifier +from spdx3.model.external_reference import ExternalReference from spdx3.model.integrity_method import IntegrityMethod diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index c80ce7df9..eb43a5f76 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -10,15 +10,12 @@ # limitations under the License. from typing import Optional, List -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference - -from common.typing.type_checks import check_types_and_set_values - -from spdx3.model.creation_information import CreationInformation - from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values from spdx3.model.artifact import Artifact +from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier +from spdx3.model.external_reference import ExternalReference from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.software.software_purpose import SoftwarePurpose diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 7962cf7ea..6aefc358e 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -10,15 +10,12 @@ # limitations under the License. from typing import Optional, List -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference - -from spdx3.model.creation_information import CreationInformation - -from common.typing.type_checks import check_types_and_set_values - from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values from spdx3.model.artifact import Artifact +from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier +from spdx3.model.external_reference import ExternalReference from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.software.software_purpose import SoftwarePurpose diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index 9d0cf300d..79aa354ea 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -10,17 +10,13 @@ # limitations under the License. from typing import Optional, List -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference - -from common.typing.type_checks import check_types_and_set_values - -from spdx3.model.creation_information import CreationInformation - from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.element import Element +from common.typing.type_checks import check_types_and_set_values from spdx3.model.bom import Bom +from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_map import ExternalMap +from spdx3.model.external_reference import ExternalReference from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.namespace_map import NamespaceMap diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index 307127fce..5aa134405 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -10,17 +10,14 @@ # limitations under the License. from typing import Optional, Tuple, List -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference - +from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values - +from spdx3.model.artifact import Artifact from spdx3.model.creation_information import CreationInformation - -from common.typing.dataclass_with_properties import dataclass_with_properties +from spdx3.model.external_identifier import ExternalIdentifier +from spdx3.model.external_reference import ExternalReference from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.software.software_purpose import SoftwarePurpose -from spdx3.model.artifact import Artifact @dataclass_with_properties diff --git a/src/spdx3/model/software/software_purpose.py b/src/spdx3/model/software/software_purpose.py index d35e12036..53ef9f77b 100644 --- a/src/spdx3/model/software/software_purpose.py +++ b/src/spdx3/model/software/software_purpose.py @@ -28,6 +28,6 @@ class SoftwarePurpose(Enum): LIBRARY = auto() MODULE = auto() OPERATING_SYSTEM = auto() - OTHER= auto() + OTHER = auto() PATCH = auto() SOURCE = auto() diff --git a/src/spdx3/model/spdx_collection.py b/src/spdx3/model/spdx_collection.py index caaf497fb..e912df0e9 100644 --- a/src/spdx3/model/spdx_collection.py +++ b/src/spdx3/model/spdx_collection.py @@ -13,7 +13,6 @@ from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties - from spdx3.model.element import Element from spdx3.model.external_map import ExternalMap from spdx3.model.namespace_map import NamespaceMap diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index cf03de04c..95f41bd4d 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -10,17 +10,13 @@ # limitations under the License. from typing import Optional, List -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference - -from common.typing.type_checks import check_types_and_set_values - -from spdx3.model.creation_information import CreationInformation - from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.element import Element +from common.typing.type_checks import check_types_and_set_values from spdx3.model.bundle import Bundle +from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier from spdx3.model.external_map import ExternalMap +from spdx3.model.external_reference import ExternalReference from spdx3.model.integrity_method import IntegrityMethod from spdx3.model.namespace_map import NamespaceMap diff --git a/src/spdx3/writer/console/annotation_writer.py b/src/spdx3/writer/console/annotation_writer.py index 66504f1ae..ab5cb3acb 100644 --- a/src/spdx3/writer/console/annotation_writer.py +++ b/src/spdx3/writer/console/annotation_writer.py @@ -10,11 +10,10 @@ # limitations under the License. from typing import TextIO +from spdx3.model.annotation import Annotation from spdx3.writer.console.console import write_value from spdx3.writer.console.element_writer import write_element_properties -from spdx3.model.annotation import Annotation - def write_annotation(annotation: Annotation, text_output: TextIO): text_output.write("## Annotation\n") diff --git a/src/spdx3/writer/console/artifact_writer.py b/src/spdx3/writer/console/artifact_writer.py index a0bd27f76..54ec52805 100644 --- a/src/spdx3/writer/console/artifact_writer.py +++ b/src/spdx3/writer/console/artifact_writer.py @@ -10,9 +10,8 @@ # limitations under the License. from typing import TextIO -from spdx3.writer.console.element_writer import write_element_properties - from spdx3.model.artifact import Artifact +from spdx3.writer.console.element_writer import write_element_properties def write_artifact_properties(artifact: Artifact, text_output: TextIO): diff --git a/src/spdx3/writer/console/element_writer.py b/src/spdx3/writer/console/element_writer.py index 618e03246..2258ed626 100644 --- a/src/spdx3/writer/console/element_writer.py +++ b/src/spdx3/writer/console/element_writer.py @@ -37,7 +37,3 @@ def write_element_properties(element: Element, text_output: TextIO): write_optional_heading(element.external_identifier, "External Identifier", text_output) for external_identifier in element.external_identifier: write_external_identifier(external_identifier, text_output) - - - - diff --git a/src/spdx3/writer/console/external_identifier_writer.py b/src/spdx3/writer/console/external_identifier_writer.py index 33fc4fe6e..9ef665fcb 100644 --- a/src/spdx3/writer/console/external_identifier_writer.py +++ b/src/spdx3/writer/console/external_identifier_writer.py @@ -10,9 +10,8 @@ # limitations under the License. from typing import TextIO -from spdx3.writer.console.console import write_value - from spdx3.model.external_identifier import ExternalIdentifier +from spdx3.writer.console.console import write_value def write_external_identifier(external_identifier: ExternalIdentifier, text_output: TextIO): diff --git a/src/spdx3/writer/console/external_reference_writer.py b/src/spdx3/writer/console/external_reference_writer.py index 2bd8cc91c..9bd853c8d 100644 --- a/src/spdx3/writer/console/external_reference_writer.py +++ b/src/spdx3/writer/console/external_reference_writer.py @@ -19,4 +19,3 @@ def write_external_reference(external_reference: ExternalReference, text_output: write_value("locator", ", ".join(external_reference.locator), text_output) write_value("content_type", external_reference.content_type, text_output) write_value("comment", external_reference.comment, text_output) - diff --git a/src/spdx3/writer/console/spdx_id_map_writer.py b/src/spdx3/writer/console/spdx_id_map_writer.py index 022be23f9..93118e437 100644 --- a/src/spdx3/writer/console/spdx_id_map_writer.py +++ b/src/spdx3/writer/console/spdx_id_map_writer.py @@ -13,15 +13,13 @@ from spdx3.model.annotation import Annotation from spdx3.model.bom import Bom from spdx3.model.bundle import Bundle - +from spdx3.model.relationship import Relationship from spdx3.model.software.file import File from spdx3.model.software.package import Package -from spdx3.model.relationship import Relationship from spdx3.model.software.sbom import Sbom from spdx3.model.software.snippet import Snippet from spdx3.model.spdx_document import SpdxDocument from spdx3.spdx_id_map import SpdxIdMap - from spdx3.writer.console.annotation_writer import write_annotation from spdx3.writer.console.bom_writer import write_bom from spdx3.writer.console.bundle_writer import write_bundle @@ -43,9 +41,10 @@ Snippet: write_snippet, Sbom: write_sbom } + + def write_spdx_id_map(spdx_id_map: SpdxIdMap, text_output: TextIO): for element in spdx_id_map.get_full_map().values(): write_method = MAP_CLASS_TO_WRITE_METHOD[type(element)] write_method(element, text_output) text_output.write("\n") - From 21fad9a868d80e58e41890e25885698b71169b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 15 Mar 2023 12:11:44 +0100 Subject: [PATCH 157/354] [issue-427] adapt bump methods to allow bumping of actors within other elements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit also change spdx_id_map to payload Signed-off-by: Armin Tänzer small change Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/annotation.py | 6 ++-- src/spdx3/bump_from_spdx2/file.py | 8 ++--- src/spdx3/bump_from_spdx2/package.py | 10 +++--- src/spdx3/bump_from_spdx2/relationship.py | 11 +++--- src/spdx3/bump_from_spdx2/snippet.py | 9 +++-- src/spdx3/bump_from_spdx2/spdx_document.py | 34 +++++++------------ src/spdx3/clitools/pyspdxtools3.py | 8 ++--- src/spdx3/{spdx_id_map.py => payload.py} | 2 +- .../writer/console/spdx_id_map_writer.py | 6 ++-- tests/spdx3/bump/test_file_bump.py | 7 ++-- tests/spdx3/bump/test_package_bump.py | 7 ++-- tests/spdx3/bump/test_snippet_bump.py | 7 ++-- tests/spdx3/bump/test_spdx_document_bump.py | 15 ++++---- 13 files changed, 65 insertions(+), 65 deletions(-) rename src/spdx3/{spdx_id_map.py => payload.py} (98%) diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py index efd4947eb..50b0c9b06 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -13,9 +13,11 @@ from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.annotation import Annotation, AnnotationType from spdx3.model.creation_information import CreationInformation +from spdx3.payload import Payload -def bump_annotation(spdx2_annotation: Spdx2_Annotation, creation_info: CreationInformation, counter: int) -> Annotation: +def bump_annotation(spdx2_annotation: Spdx2_Annotation, payload: Payload, creation_info: CreationInformation, + counter: int): spdx_id: str = f"SPDXRef-Annotation-{counter}" creation_info.created = spdx2_annotation.annotation_date # creation_info.created_by = bump_actor(spdx2_annotation.annotator) waiting for entity implementation @@ -24,4 +26,4 @@ def bump_annotation(spdx2_annotation: Spdx2_Annotation, creation_info: CreationI subject: str = spdx2_annotation.spdx_id statement: str = spdx2_annotation.annotation_comment - return Annotation(spdx_id, creation_info, annotation_type, subject, statement=statement) + payload.add_element(Annotation(spdx_id, creation_info, annotation_type, subject, statement=statement)) diff --git a/src/spdx3/bump_from_spdx2/file.py b/src/spdx3/bump_from_spdx2/file.py index fb8dbbe53..693248929 100644 --- a/src/spdx3/bump_from_spdx2/file.py +++ b/src/spdx3/bump_from_spdx2/file.py @@ -13,9 +13,10 @@ from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.creation_information import CreationInformation from spdx3.model.software.file import File +from spdx3.payload import Payload -def bump_file(spdx2_file: Spdx2_File, creation_information: CreationInformation) -> File: +def bump_file(spdx2_file: Spdx2_File, payload: Payload, creation_information: CreationInformation): name = spdx2_file.name spdx_id = spdx2_file.spdx_id integrity_methods = [bump_checksum(checksum) for checksum in spdx2_file.checksums] @@ -30,6 +31,5 @@ def bump_file(spdx2_file: Spdx2_File, creation_information: CreationInformation) print_missing_conversion("file.notice, file.contributors, file.attribution_texts", 0, "missing definition for license profile") - file = File(spdx_id, creation_info=creation_information, name=name, comment=comment, - verified_using=integrity_methods) - return file + payload.add_element(File(spdx_id, creation_info=creation_information, name=name, comment=comment, + verified_using=integrity_methods)) diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index 40dd1643a..4964b6a90 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -15,9 +15,10 @@ from spdx3.model.creation_information import CreationInformation from spdx3.model.software.package import Package from spdx3.model.software.software_purpose import SoftwarePurpose +from spdx3.payload import Payload -def bump_package(spdx2_package: Spdx2_Package, creation_information: CreationInformation) -> Package: +def bump_package(spdx2_package: Spdx2_Package, payload: Payload, creation_information: CreationInformation): spdx_id = spdx2_package.spdx_id name = spdx2_package.name download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") @@ -49,7 +50,6 @@ def bump_package(spdx2_package: Spdx2_Package, creation_information: CreationInf spdx2_package.primary_package_purpose.name]] if spdx2_package.primary_package_purpose else [] print_missing_conversion("package2.release_date, package2.built_date, package2.valid_until_date", 0) - package = Package(spdx_id, creation_information, name, verified_using=integrity_methods, - download_location=download_location, homepage=homepage, summary=summary, description=description, - comment=comment, package_purpose=package_purpose) - return package + payload.add_element(Package(spdx_id, creation_information, name, verified_using=integrity_methods, + download_location=download_location, homepage=homepage, summary=summary, + description=description, comment=comment, package_purpose=package_purpose)) diff --git a/src/spdx3/bump_from_spdx2/relationship.py b/src/spdx3/bump_from_spdx2/relationship.py index b3907339c..33260a31c 100644 --- a/src/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx3/bump_from_spdx2/relationship.py @@ -16,10 +16,11 @@ from spdx.model.spdx_none import SpdxNone from spdx3.model.creation_information import CreationInformation from spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness +from spdx3.payload import Payload -def bump_relationship(spdx2_relationship: Spdx2_Relationship, - creation_information: CreationInformation, counter: int) -> Relationship: +def bump_relationship(spdx2_relationship: Spdx2_Relationship, payload: Payload, + creation_information: CreationInformation, counter: int): relationship_type, swap_direction = bump_relationship_type(spdx2_relationship.relationship_type) if isinstance(spdx2_relationship.related_spdx_element_id, @@ -38,10 +39,8 @@ def bump_relationship(spdx2_relationship: Spdx2_Relationship, to = [spdx2_relationship.related_spdx_element_id] comment = spdx2_relationship.comment - relationship = Relationship(f"SPDXRef-Relationship-{counter}", creation_information, from_element, to, - relationship_type, comment=comment, completeness=completeness) - - return relationship + payload.add_element(Relationship(f"SPDXRef-Relationship-{counter}", creation_information, from_element, to, + relationship_type, comment=comment, completeness=completeness)) def bump_relationship_type(spdx2_relationship_type: Spdx2_RelationshipType) -> Optional[Tuple[RelationshipType, bool]]: diff --git a/src/spdx3/bump_from_spdx2/snippet.py b/src/spdx3/bump_from_spdx2/snippet.py index 030893fad..9951327a9 100644 --- a/src/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx3/bump_from_spdx2/snippet.py @@ -12,9 +12,10 @@ from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.creation_information import CreationInformation from spdx3.model.software.snippet import Snippet +from spdx3.payload import Payload -def bump_snippet(spdx2_snippet: Spdx2_Snippet, creation_information: CreationInformation) -> Snippet: +def bump_snippet(spdx2_snippet: Spdx2_Snippet, payload: Payload, creation_information: CreationInformation): spdx_id = spdx2_snippet.spdx_id print_missing_conversion("snippet.file_spdx_id", 0) byte_range = spdx2_snippet.byte_range @@ -26,7 +27,5 @@ def bump_snippet(spdx2_snippet: Spdx2_Snippet, creation_information: CreationInf print_missing_conversion("snippet.attribution_texts", 0, "missing definitions for license profile") - snippet = Snippet(spdx_id=spdx_id, creation_info=creation_information, byte_range=byte_range, line_range=line_range, - comment=comment, name=name) - - return snippet + payload.add_element(Snippet(spdx_id=spdx_id, creation_info=creation_information, byte_range=byte_range, + line_range=line_range, comment=comment, name=name)) diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx3/bump_from_spdx2/spdx_document.py index bd94fba84..668cb4a41 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -17,43 +17,35 @@ from spdx3.bump_from_spdx2.snippet import bump_snippet from spdx3.model.creation_information import CreationInformation from spdx3.model.spdx_document import SpdxDocument -from spdx3.spdx_id_map import SpdxIdMap +from spdx3.payload import Payload """ We want to implement a bump_from_spdx2 from the data model in src.spdx to the data model in src.spdx3. As there are many fundamental differences between these version we want each bump_from_spdx2 method to take - the object from src.spdx and return all objects that the input is translated to.""" + the object from src.spdx and add all objects that the input is translated to into the payload.""" -def bump_spdx_document(document: Spdx2_Document) -> SpdxIdMap: - spdx_id_map = SpdxIdMap() +def bump_spdx_document(document: Spdx2_Document) -> Payload: + payload = Payload() spdx_document: SpdxDocument = bump_creation_information(document.creation_info) creation_info: CreationInformation = spdx_document.creation_info - spdx_id_map.add_element(spdx_document) + payload.add_element(spdx_document) for spdx2_package in document.packages: - package = bump_package(spdx2_package, creation_info) - spdx_id_map.add_element(package) - spdx_document.elements.append(package.spdx_id) + bump_package(spdx2_package, payload, creation_info) for spdx2_file in document.files: - file = bump_file(spdx2_file, creation_info) - spdx_id_map.add_element(file) - spdx_document.elements.append(file.spdx_id) + bump_file(spdx2_file, payload, creation_info) for spdx2_snippet in document.snippets: - snippet = bump_snippet(spdx2_snippet, creation_info) - spdx_id_map.add_element(snippet) - spdx_document.elements.append(snippet.spdx_id) + bump_snippet(spdx2_snippet, payload, creation_info) for counter, spdx2_relationship in enumerate(document.relationships): - relationship = bump_relationship(spdx2_relationship, creation_info, counter) - spdx_id_map.add_element(relationship) - spdx_document.elements.append(relationship.spdx_id) + bump_relationship(spdx2_relationship, payload, creation_info, counter) for counter, spdx2_annotation in enumerate(document.annotations): - annotation = bump_annotation(spdx2_annotation, creation_info, counter) - spdx_id_map.add_element(annotation) - spdx_document.elements.append(annotation.spdx_id) + bump_annotation(spdx2_annotation, payload, creation_info, counter) - return spdx_id_map + spdx_document.elements = [spdx_id for spdx_id in payload.get_full_map() if spdx_id != spdx_document.spdx_id] + + return payload diff --git a/src/spdx3/clitools/pyspdxtools3.py b/src/spdx3/clitools/pyspdxtools3.py index f54c31f73..224c7c15a 100644 --- a/src/spdx3/clitools/pyspdxtools3.py +++ b/src/spdx3/clitools/pyspdxtools3.py @@ -18,8 +18,8 @@ from spdx.validation.document_validator import validate_full_spdx_document from spdx.validation.validation_message import ValidationMessage from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document -from spdx3.spdx_id_map import SpdxIdMap -from spdx3.writer.console.spdx_id_map_writer import write_spdx_id_map +from spdx3.payload import Payload +from spdx3.writer.console.spdx_id_map_writer import write_payload @click.command() @@ -50,8 +50,8 @@ def main(infile: str, outfile: str, version: str, novalidation: bool): print("The document is valid.", file=sys.stderr) if outfile == "-": - spdx_id_map: SpdxIdMap = bump_spdx_document(document) - write_spdx_id_map(spdx_id_map, sys.stdout) + payload: Payload = bump_spdx_document(document) + write_payload(payload, sys.stdout) except NotImplementedError as err: print(err.args[0]) diff --git a/src/spdx3/spdx_id_map.py b/src/spdx3/payload.py similarity index 98% rename from src/spdx3/spdx_id_map.py rename to src/spdx3/payload.py index 66e9ae9ab..a9dc970aa 100644 --- a/src/spdx3/spdx_id_map.py +++ b/src/spdx3/payload.py @@ -13,7 +13,7 @@ from spdx3.model.element import Element -class SpdxIdMap: +class Payload: _spdx_id_map: Dict[str, Element] def __init__(self, spdx_id_map: Dict[str, Element] = None): diff --git a/src/spdx3/writer/console/spdx_id_map_writer.py b/src/spdx3/writer/console/spdx_id_map_writer.py index 93118e437..35fcdffce 100644 --- a/src/spdx3/writer/console/spdx_id_map_writer.py +++ b/src/spdx3/writer/console/spdx_id_map_writer.py @@ -19,7 +19,7 @@ from spdx3.model.software.sbom import Sbom from spdx3.model.software.snippet import Snippet from spdx3.model.spdx_document import SpdxDocument -from spdx3.spdx_id_map import SpdxIdMap +from spdx3.payload import Payload from spdx3.writer.console.annotation_writer import write_annotation from spdx3.writer.console.bom_writer import write_bom from spdx3.writer.console.bundle_writer import write_bundle @@ -43,8 +43,8 @@ } -def write_spdx_id_map(spdx_id_map: SpdxIdMap, text_output: TextIO): - for element in spdx_id_map.get_full_map().values(): +def write_payload(payload: Payload, text_output: TextIO): + for element in payload.get_full_map().values(): write_method = MAP_CLASS_TO_WRITE_METHOD[type(element)] write_method(element, text_output) text_output.write("\n") diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index a7af63aa3..e4fda1eae 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -13,6 +13,7 @@ from spdx3.bump_from_spdx2.file import bump_file from spdx3.model.hash import Hash, HashAlgorithm from spdx3.model.software.file import File +from spdx3.payload import Payload from tests.spdx.fixtures import file_fixture from spdx.model.file import File as Spdx2_File @@ -22,7 +23,9 @@ def test_bump_file(creation_information): spdx2_file: Spdx2_File = file_fixture() integrity_method: Hash = Hash(HashAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c") - file: File = bump_file(spdx2_file, creation_information=creation_information) - + payload = Payload() + bump_file(spdx2_file, payload, creation_information=creation_information) + file = payload.get_element(file_fixture().spdx_id) + assert isinstance(file, File) assert file.spdx_id == "SPDXRef-File" assert file.verified_using == [integrity_method] diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index e1cdda771..5ed801c51 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -12,6 +12,7 @@ from spdx3.bump_from_spdx2.package import bump_package from spdx3.model.software.package import Package +from spdx3.payload import Payload from tests.spdx.fixtures import package_fixture from spdx.model.package import Package as Spdx2_Package @@ -21,7 +22,9 @@ def test_bump_package(creation_information): spdx2_package: Spdx2_Package = package_fixture() - package: Package = bump_package(spdx2_package, creation_information=creation_information) - + payload = Payload() + bump_package(spdx2_package, payload, creation_information=creation_information) + package = payload.get_element(package_fixture().spdx_id) + assert isinstance(package, Package) assert package.spdx_id == "SPDXRef-Package" diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index 86d231fe6..fca70d93d 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -11,6 +11,7 @@ from unittest import mock from spdx3.bump_from_spdx2.snippet import bump_snippet +from spdx3.payload import Payload from tests.spdx.fixtures import snippet_fixture from spdx.model.snippet import Snippet as Spdx2_Snippet from spdx3.model.software.snippet import Snippet @@ -20,6 +21,8 @@ def test_bump_snippet(creation_information): spdx2_snippet: Spdx2_Snippet = snippet_fixture() - snippet: Snippet = bump_snippet(spdx2_snippet, creation_information=creation_information) - + payload = Payload() + bump_snippet(spdx2_snippet, payload, creation_information=creation_information) + snippet = payload.get_element(snippet_fixture().spdx_id) + assert isinstance(snippet, Snippet) assert snippet.spdx_id == "SPDXRef-Snippet" diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index 6dae21dad..925150899 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -13,18 +13,17 @@ from spdx.model.document import Document as Spdx2_Document from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document -from spdx3.spdx_id_map import SpdxIdMap -from spdx3.writer.console.spdx_id_map_writer import write_spdx_id_map -from tests.spdx.fixtures import document_fixture +from spdx3.payload import Payload +from spdx3.writer.console.spdx_id_map_writer import write_payload +from tests.spdx.fixtures import document_fixture, creation_info_fixture, annotation_fixture def test_bump_spdx_document(): spdx2_document: Spdx2_Document = document_fixture() - spdx_id_map: SpdxIdMap = bump_spdx_document(spdx2_document) + payload: Payload = bump_spdx_document(spdx2_document) - write_spdx_id_map(spdx_id_map, sys.stdout) + write_payload(payload, sys.stdout) - assert "SPDXRef-Package" in list(spdx_id_map.get_full_map().keys()) - assert len( - spdx_id_map.get_full_map().values()) == 6 + assert "SPDXRef-Package" in payload.get_full_map() + assert len(payload.get_full_map()) == 6 From db9f08588bf5ab8add0f7eee3b48f9df2d480c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 15 Mar 2023 12:14:07 +0100 Subject: [PATCH 158/354] [issue-427] fix bump_annotation overriding creation_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/annotation.py | 2 ++ tests/spdx3/bump/test_spdx_document_bump.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py index 50b0c9b06..4cba434de 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -8,6 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from copy import deepcopy from spdx.model.annotation import Annotation as Spdx2_Annotation from spdx3.bump_from_spdx2.message import print_missing_conversion @@ -19,6 +20,7 @@ def bump_annotation(spdx2_annotation: Spdx2_Annotation, payload: Payload, creation_info: CreationInformation, counter: int): spdx_id: str = f"SPDXRef-Annotation-{counter}" + creation_info = deepcopy(creation_info) creation_info.created = spdx2_annotation.annotation_date # creation_info.created_by = bump_actor(spdx2_annotation.annotator) waiting for entity implementation print_missing_conversion("annotation.annotator", 1, "of Entity") diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index 925150899..21c86f96d 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -27,3 +27,7 @@ def test_bump_spdx_document(): assert "SPDXRef-Package" in payload.get_full_map() assert len(payload.get_full_map()) == 6 + + #this is more of a temporary test to make sure the dates don't get messed up again + assert payload.get_element("SPDXRef-DOCUMENT").creation_info.created == creation_info_fixture().created + assert payload.get_element("SPDXRef-Annotation-0").creation_info.created == annotation_fixture().annotation_date From d5c4099851fc599e4a5805f895e77483d1890453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 13 Mar 2023 09:24:23 +0100 Subject: [PATCH 159/354] [issue-426] add Tool and Agent-related classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/model/agent.py | 34 +++++++++++++++ src/spdx3/model/artifact.py | 3 +- src/spdx3/model/creation_information.py | 4 +- src/spdx3/model/organization.py | 34 +++++++++++++++ src/spdx3/model/person.py | 34 +++++++++++++++ src/spdx3/model/software/file.py | 2 +- src/spdx3/model/software/package.py | 4 +- src/spdx3/model/software/snippet.py | 2 +- src/spdx3/model/software_agent.py | 34 +++++++++++++++ src/spdx3/model/tool.py | 34 +++++++++++++++ tests/spdx3/model/software/test_snippet.py | 4 +- tests/spdx3/model/test_agent.py | 43 +++++++++++++++++++ .../spdx3/model/test_creation_information.py | 9 ++-- tests/spdx3/model/test_tool.py | 35 +++++++++++++++ 14 files changed, 263 insertions(+), 13 deletions(-) create mode 100644 src/spdx3/model/agent.py create mode 100644 src/spdx3/model/organization.py create mode 100644 src/spdx3/model/person.py create mode 100644 src/spdx3/model/software_agent.py create mode 100644 src/spdx3/model/tool.py create mode 100644 tests/spdx3/model/test_agent.py create mode 100644 tests/spdx3/model/test_tool.py diff --git a/src/spdx3/model/agent.py b/src/spdx3/model/agent.py new file mode 100644 index 000000000..86d2b9255 --- /dev/null +++ b/src/spdx3/model/agent.py @@ -0,0 +1,34 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional, List + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values +from spdx3.model.creation_information import CreationInformation +from spdx3.model.element import Element +from spdx3.model.external_identifier import ExternalIdentifier +from spdx3.model.external_reference import ExternalReference +from spdx3.model.integrity_method import IntegrityMethod + + +@dataclass_with_properties +class Agent(Element): + + def __init__(self, spdx_id: str, creation_info: CreationInformation, + name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/artifact.py b/src/spdx3/model/artifact.py index e76a41f41..7b5ce6791 100644 --- a/src/spdx3/model/artifact.py +++ b/src/spdx3/model/artifact.py @@ -9,6 +9,7 @@ # See the License for the specific language governing permissions and # limitations under the License. from abc import abstractmethod +from typing import Optional from common.typing.dataclass_with_properties import dataclass_with_properties from spdx3.model.element import Element @@ -16,7 +17,7 @@ @dataclass_with_properties class Artifact(Element): - originated_by: None = None # placeholder for Actor + originated_by: Optional[str] = None # SPDXID of the Agent/Tool @abstractmethod def __init__(self): diff --git a/src/spdx3/model/creation_information.py b/src/spdx3/model/creation_information.py index a3f5729a2..b613606cb 100644 --- a/src/spdx3/model/creation_information.py +++ b/src/spdx3/model/creation_information.py @@ -21,10 +21,10 @@ class CreationInformation: spec_version: Version created: datetime - created_by: None # placeholder for Actor + created_by: List[str] # SPDXID of Agents/Tools profile: List[str] # or create an Enum for ProfileIdentifier? data_license: str - def __init__(self, spec_version: Version, created: datetime, created_by, profile: List[str], + def __init__(self, spec_version: Version, created: datetime, created_by: List[str], profile: List[str], data_license: str = "CC0"): check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/organization.py b/src/spdx3/model/organization.py new file mode 100644 index 000000000..f48d3053c --- /dev/null +++ b/src/spdx3/model/organization.py @@ -0,0 +1,34 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional, List + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values +from spdx3.model.agent import Agent +from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier +from spdx3.model.external_reference import ExternalReference +from spdx3.model.integrity_method import IntegrityMethod + + +@dataclass_with_properties +class Organization(Agent): + + def __init__(self, spdx_id: str, creation_info: CreationInformation, + name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/person.py b/src/spdx3/model/person.py new file mode 100644 index 000000000..2b6e45719 --- /dev/null +++ b/src/spdx3/model/person.py @@ -0,0 +1,34 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional, List + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values +from spdx3.model.agent import Agent +from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier +from spdx3.model.external_reference import ExternalReference +from spdx3.model.integrity_method import IntegrityMethod + + +@dataclass_with_properties +class Person(Agent): + + def __init__(self, spdx_id: str, creation_info: CreationInformation, + name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index eb43a5f76..01c94394d 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -31,7 +31,7 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio verified_using: Optional[List[IntegrityMethod]] = None, external_references: Optional[List[ExternalReference]] = None, external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, - originated_by: None = None, content_identifier: Optional[str] = None, + originated_by: Optional[str] = None, content_identifier: Optional[str] = None, file_purpose: Optional[List[SoftwarePurpose]] = None, content_type: Optional[str] = None): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 6aefc358e..2cdaa46e7 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -10,6 +10,8 @@ # limitations under the License. from typing import Optional, List +from spdx3.model.agent import Agent + from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values from spdx3.model.artifact import Artifact @@ -33,7 +35,7 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio verified_using: Optional[List[IntegrityMethod]] = None, external_references: Optional[List[ExternalReference]] = None, external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, - originated_by: None = None, content_identifier: Optional[str] = None, + originated_by: Optional[str] = None, content_identifier: Optional[str] = None, package_purpose: Optional[List[SoftwarePurpose]] = None, download_location: Optional[str] = None, package_uri: Optional[str] = None, homepage: Optional[str] = None): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index 5aa134405..2e2b31d51 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -32,7 +32,7 @@ def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optio verified_using: Optional[List[IntegrityMethod]] = None, external_references: Optional[List[ExternalReference]] = None, external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, - originated_by: None = None, content_identifier: Optional[str] = None, + originated_by: Optional[str] = None, content_identifier: Optional[str] = None, snippet_purpose: Optional[List[SoftwarePurpose]] = None, byte_range: Optional[Tuple[int, int]] = None, line_range: Optional[Tuple[int, int]] = None): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx3/model/software_agent.py b/src/spdx3/model/software_agent.py new file mode 100644 index 000000000..44f6ee710 --- /dev/null +++ b/src/spdx3/model/software_agent.py @@ -0,0 +1,34 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional, List + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values +from spdx3.model.agent import Agent +from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier +from spdx3.model.external_reference import ExternalReference +from spdx3.model.integrity_method import IntegrityMethod + + +@dataclass_with_properties +class SoftwareAgent(Agent): + + def __init__(self, spdx_id: str, creation_info: CreationInformation, + name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/tool.py b/src/spdx3/model/tool.py new file mode 100644 index 000000000..659e2923b --- /dev/null +++ b/src/spdx3/model/tool.py @@ -0,0 +1,34 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import Optional, List + +from common.typing.dataclass_with_properties import dataclass_with_properties +from common.typing.type_checks import check_types_and_set_values +from spdx3.model.creation_information import CreationInformation +from spdx3.model.element import Element +from spdx3.model.external_identifier import ExternalIdentifier +from spdx3.model.external_reference import ExternalReference +from spdx3.model.integrity_method import IntegrityMethod + + +@dataclass_with_properties +class Tool(Element): + + def __init__(self, spdx_id: str, creation_info: CreationInformation, + name: Optional[str] = None, summary: Optional[str] = None, + description: Optional[str] = None, comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index 2b0e72fc5..b6701162f 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -37,7 +37,7 @@ def test_invalid_initialization(creation_information): assert err.value.args[0] == ['SetterError Snippet: type of argument "spdx_id" must be str; got int ' 'instead: 2', - 'SetterError Snippet: type of argument "originated_by" must be NoneType; got ' - 'int instead: 34', + 'SetterError Snippet: type of argument "originated_by" must be one of (str, ' + 'NoneType); got int instead: 34', 'SetterError Snippet: type of argument "byte_range" must be one of ' '(Tuple[int, int], NoneType); got str instead: 34:45'] diff --git a/tests/spdx3/model/test_agent.py b/tests/spdx3/model/test_agent.py new file mode 100644 index 000000000..f5004e5d1 --- /dev/null +++ b/tests/spdx3/model/test_agent.py @@ -0,0 +1,43 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from datetime import datetime + +import pytest +from semantic_version import Version + +from spdx3.model.agent import Agent +from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx3.model.organization import Organization +from spdx3.model.person import Person +from spdx3.model.software_agent import SoftwareAgent + + +@pytest.mark.parametrize("agent_class", [Agent, Person, Organization, SoftwareAgent]) +def test_correct_initialization(agent_class): + agent = agent_class("SPDXRef-Agent", + CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], ["core"], "CC0"), + external_identifier=[ExternalIdentifier(ExternalIdentifierType.EMAIL, "some@mail.com")]) + + assert agent.spdx_id == "SPDXRef-Agent" + assert agent.creation_info == CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], + ["core"], "CC0") + assert agent.external_identifier == [ExternalIdentifier(ExternalIdentifierType.EMAIL, "some@mail.com")] + + +@pytest.mark.parametrize("agent_class", [Agent, Person, Organization, SoftwareAgent]) +def test_invalid_initialization(agent_class): + with pytest.raises(TypeError) as err: + agent_class(12, 345) + + assert err.value.args[0] == [f'SetterError {agent_class.__name__}: type of argument "spdx_id" must be str; got int instead: 12', + f'SetterError {agent_class.__name__}: type of argument "creation_info" must be ' + 'spdx3.model.creation_information.CreationInformation; got int instead: 345'] diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py index 5e50cda5b..d86ad756d 100644 --- a/tests/spdx3/model/test_creation_information.py +++ b/tests/spdx3/model/test_creation_information.py @@ -9,7 +9,6 @@ # See the License for the specific language governing permissions and # limitations under the License. from datetime import datetime -from unittest import mock import pytest from semantic_version import Version @@ -18,19 +17,19 @@ def test_correct_initialization(): - creation_information = CreationInformation(Version("3.0.0"), datetime(2023, 1, 11, 16, 21), None, ["core", "software"], - "CC0") + creation_information = CreationInformation(Version("3.0.0"), datetime(2023, 1, 11, 16, 21), [], + ["core", "software"], "CC0") assert creation_information.spec_version == Version("3.0.0") assert creation_information.created == datetime(2023, 1, 11, 16, 21) - assert creation_information.created_by is None + assert creation_information.created_by == [] assert creation_information.profile == ["core", "software"] assert creation_information.data_license == "CC0" def test_invalid_initialization(): with pytest.raises(TypeError) as err: - CreationInformation("2.3", "2012-01-01", None, "core", 3) + CreationInformation("2.3", "2012-01-01", [], "core", 3) assert err.value.args[0] == ['SetterError CreationInformation: type of argument "spec_version" must be ' 'semantic_version.base.Version; got str instead: 2.3', diff --git a/tests/spdx3/model/test_tool.py b/tests/spdx3/model/test_tool.py new file mode 100644 index 000000000..b59ab2613 --- /dev/null +++ b/tests/spdx3/model/test_tool.py @@ -0,0 +1,35 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from datetime import datetime + +import pytest +from semantic_version import Version + +from spdx3.model.creation_information import CreationInformation +from spdx3.model.tool import Tool + + +def test_correct_initialization(): + agent = Tool("SPDXRef-Tool", + CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], ["core"], "CC0")) + + assert agent.spdx_id == "SPDXRef-Tool" + assert agent.creation_info == CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], + ["core"], "CC0") + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + Tool(12, 345) + + assert err.value.args[0] == ['SetterError Tool: type of argument "spdx_id" must be str; got int instead: 12', + 'SetterError Tool: type of argument "creation_info" must be ' + 'spdx3.model.creation_information.CreationInformation; got int instead: 345'] From 19f0b058caaf096e26f1c635a1eba13c1c11841b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 13 Mar 2023 15:25:04 +0100 Subject: [PATCH 160/354] [spdx-3.0] update ExternalIdentifierType from the model.png MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/model/external_identifier.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/spdx3/model/external_identifier.py b/src/spdx3/model/external_identifier.py index ada3f6c4b..93a5dcab9 100644 --- a/src/spdx3/model/external_identifier.py +++ b/src/spdx3/model/external_identifier.py @@ -18,11 +18,13 @@ class ExternalIdentifierType(Enum): CPE22 = auto() CPE23 = auto() + EMAIL = auto() GITOID = auto() - OTHER = auto() - PKG_URL = auto() + PURL = auto() SWHID = auto() SWID = auto() + URL_SCHEME = auto() + OTHER = auto() @dataclass_with_properties From 51d5f9698ea605a0824743ce710f7775447ae3eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 16 Mar 2023 12:21:34 +0100 Subject: [PATCH 161/354] [issue-427] add bumping of actors (except for supplier) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/actor.py | 56 +++++++++++++++++++ src/spdx3/bump_from_spdx2/annotation.py | 6 +- .../bump_from_spdx2/creation_information.py | 18 ++++-- src/spdx3/bump_from_spdx2/package.py | 7 ++- src/spdx3/bump_from_spdx2/spdx_document.py | 2 +- src/spdx3/model/software/package.py | 2 - tests/spdx3/bump/test_actor_bump.py | 56 +++++++++++++++++++ 7 files changed, 136 insertions(+), 11 deletions(-) create mode 100644 src/spdx3/bump_from_spdx2/actor.py create mode 100644 tests/spdx3/bump/test_actor_bump.py diff --git a/src/spdx3/bump_from_spdx2/actor.py b/src/spdx3/bump_from_spdx2/actor.py new file mode 100644 index 000000000..a36333fbe --- /dev/null +++ b/src/spdx3/bump_from_spdx2/actor.py @@ -0,0 +1,56 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import List + +from spdx.model.actor import Actor as Spdx2_Actor, ActorType +from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx3.model.organization import Organization +from spdx3.model.person import Person +from spdx3.model.software_agent import SoftwareAgent +from spdx3.model.tool import Tool +from spdx3.payload import Payload + + +def bump_actor(spdx2_actor: Spdx2_Actor, payload: Payload, creation_info: CreationInformation) -> str: + name: str = spdx2_actor.name + email: str = spdx2_actor.email + actor_type: ActorType = spdx2_actor.actor_type + + external_identifiers: List[ExternalIdentifier] = [] + name_without_whitespace = ''.join(name.split()) + if email: + external_identifiers.append(ExternalIdentifier(ExternalIdentifierType.EMAIL, email)) + spdx_id: str = f"SPDXRef-Actor-{name_without_whitespace}-{email}" + else: + spdx_id: str = f"SPDXRef-Actor-{name_without_whitespace}" + + if spdx_id in payload.get_full_map(): # the agent/tool already exists, so we don't need to create a new one + return spdx_id + + if actor_type == ActorType.PERSON: + agent_or_tool = Person( + spdx_id=spdx_id, creation_info=creation_info, name=name, external_identifier=external_identifiers) + + elif actor_type == ActorType.ORGANIZATION: + agent_or_tool = Organization( + spdx_id=spdx_id, creation_info=creation_info, name=name, external_identifier=external_identifiers) + + elif actor_type == ActorType.TOOL: + agent_or_tool = Tool( + spdx_id=spdx_id, creation_info=creation_info, name=name, external_identifier=external_identifiers) + + else: + raise ValueError(f"no conversion rule defined for ActorType {actor_type}") + + payload.add_element(agent_or_tool) + + return spdx_id diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py index 4cba434de..6d6648344 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -11,6 +11,7 @@ from copy import deepcopy from spdx.model.annotation import Annotation as Spdx2_Annotation +from spdx3.bump_from_spdx2.actor import bump_actor from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.annotation import Annotation, AnnotationType from spdx3.model.creation_information import CreationInformation @@ -22,7 +23,10 @@ def bump_annotation(spdx2_annotation: Spdx2_Annotation, payload: Payload, creati spdx_id: str = f"SPDXRef-Annotation-{counter}" creation_info = deepcopy(creation_info) creation_info.created = spdx2_annotation.annotation_date - # creation_info.created_by = bump_actor(spdx2_annotation.annotator) waiting for entity implementation + # caution: the annotator and the annotation will only share the same creation_info if the actor + # has not been previously defined + creator_id: str = bump_actor(spdx2_annotation.annotator, payload, creation_info) + creation_info.created_by = [creator_id] print_missing_conversion("annotation.annotator", 1, "of Entity") annotation_type: AnnotationType = AnnotationType[spdx2_annotation.annotation_type.name] subject: str = spdx2_annotation.spdx_id diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index b24926c6a..785471a38 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -9,17 +9,20 @@ # See the License for the specific language governing permissions and # limitations under the License. from datetime import datetime +from typing import List from semantic_version import Version +from spdx3.payload import Payload from spdx.model.document import CreationInfo as Spdx2_CreationInfo +from spdx3.bump_from_spdx2.actor import bump_actor from spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.creation_information import CreationInformation from spdx3.model.spdx_document import SpdxDocument -def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo) -> SpdxDocument: +def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload) -> SpdxDocument: # creation_info.spdx_id -> spdx_document.spdx_id spdx_id = spdx2_creation_info.spdx_id @@ -28,8 +31,7 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo) -> SpdxDo # creation_info.document_namespace -> ? print_missing_conversion("creation_info.document_namespace", 0) - # creation_info.creators -> creation_information.creators (not implemented yet) - print_missing_conversion("creation_info.creators", 1, "of creators") + created: datetime = spdx2_creation_info.created # creation_info.creator_comment -> ? print_missing_conversion("creation_info.creator_comment", 0) @@ -41,8 +43,16 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo) -> SpdxDo print_missing_conversion("creation_info.license_list_version", 0) # creation_info.document_comment -> spdx_document.comment document_comment = spdx2_creation_info.document_comment - creation_information = CreationInformation(Version("3.0.0"), created, None, ["core", "software", "licensing"], + creation_information = CreationInformation(Version("3.0.0"), created, [], ["core", "software", "licensing"], data_license) + + # due to creators having a creation_information themselves which inherits from the document's one, + # we have to add them after the creation_information has been initialized + creator_ids: List[str] = [] + for creator in spdx2_creation_info.creators: + creator_ids.append(bump_actor(creator, payload, creation_information)) + creation_information.created_by = creator_ids + spdx_document = SpdxDocument(spdx_id=spdx_id, creation_info=creation_information, name=name, comment=document_comment, elements=[], root_elements=[], imports=imports) diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index 4964b6a90..2569b3e37 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -9,6 +9,7 @@ # See the License for the specific language governing permissions and # limitations under the License. from spdx.model.package import Package as Spdx2_Package +from spdx3.bump_from_spdx2.actor import bump_actor from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none from spdx3.bump_from_spdx2.checksum import bump_checksum from spdx3.bump_from_spdx2.message import print_missing_conversion @@ -28,8 +29,7 @@ def bump_package(spdx2_package: Spdx2_Package, payload: Payload, creation_inform print_missing_conversion("package2.file_name", 0) # package.supplier -> Relationship, suppliedBy? print_missing_conversion("package2.supplier", 1, "of relationships") - # package.originator -> package.originated_by - print_missing_conversion("package2.originator", 1, "of actors") + originated_by_spdx_id = bump_actor(spdx2_package.originator, payload, creation_information) # package.files_analyzed -> ? print_missing_conversion("package2.files_analyzed", 0) # package.verification_code -> package.verified_using @@ -52,4 +52,5 @@ def bump_package(spdx2_package: Spdx2_Package, payload: Payload, creation_inform payload.add_element(Package(spdx_id, creation_information, name, verified_using=integrity_methods, download_location=download_location, homepage=homepage, summary=summary, - description=description, comment=comment, package_purpose=package_purpose)) + description=description, comment=comment, originated_by=originated_by_spdx_id, + package_purpose=package_purpose)) diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx3/bump_from_spdx2/spdx_document.py index 668cb4a41..20466ba04 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -26,7 +26,7 @@ def bump_spdx_document(document: Spdx2_Document) -> Payload: payload = Payload() - spdx_document: SpdxDocument = bump_creation_information(document.creation_info) + spdx_document: SpdxDocument = bump_creation_information(document.creation_info, payload) creation_info: CreationInformation = spdx_document.creation_info payload.add_element(spdx_document) diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 2cdaa46e7..03deb7b05 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -10,8 +10,6 @@ # limitations under the License. from typing import Optional, List -from spdx3.model.agent import Agent - from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values from spdx3.model.artifact import Artifact diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py new file mode 100644 index 000000000..bd065eb49 --- /dev/null +++ b/tests/spdx3/bump/test_actor_bump.py @@ -0,0 +1,56 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from datetime import datetime + +import pytest +from semantic_version import Version + +from spdx.model.actor import Actor, ActorType +from spdx3.bump_from_spdx2.actor import bump_actor +from spdx3.model.creation_information import CreationInformation +from spdx3.model.organization import Organization +from spdx3.model.person import Person +from spdx3.model.tool import Tool +from spdx3.payload import Payload + + +@pytest.mark.parametrize("actor_type, actor_name, actor_mail, element_type, new_spdx_id", + [(ActorType.PERSON, "person name", "person@mail.com", Person, + "SPDXRef-Actor-personname-person@mail.com"), + (ActorType.ORGANIZATION, "organization name", "organization@mail.com", Organization, + "SPDXRef-Actor-organizationname-organization@mail.com"), + (ActorType.TOOL, "tool name", None, Tool, "SPDXRef-Actor-toolname"), + ]) +def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_id): + payload = Payload() + creation_info = CreationInformation(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], ["core"]) + actor = Actor(actor_type, actor_name, actor_mail) + agent_or_tool_id = bump_actor(actor, payload, creation_info) + + agent_or_tool = payload.get_element(agent_or_tool_id) + + assert isinstance(agent_or_tool, element_type) + assert agent_or_tool.spdx_id == new_spdx_id + assert agent_or_tool.name == actor_name + + +def test_bump_actor_with_already_existing_actor(): + creation_info_old = CreationInformation(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], ["core"]) + creation_info_new = CreationInformation(Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], ["core"]) + + name = "some name" + payload = Payload({"SPDXRef-Actor-somename-some@mail.com": + Person("SPDXRef-Actor-somename-some@mail.com", creation_info_old, name)}) + + actor = Actor(ActorType.PERSON, name, "some@mail.com") + agent_spdx_id = bump_actor(actor, payload, creation_info_new) + + assert payload.get_element(agent_spdx_id).creation_info == creation_info_old From a10122977c7e068298bc9d4f2bd7390822844fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 16 Mar 2023 12:22:21 +0100 Subject: [PATCH 162/354] [issue-434] add writing of Agents/Tool (except for supplier) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/clitools/pyspdxtools3.py | 2 +- src/spdx3/writer/console/agent_writer.py | 28 +++++++++++++++++++ src/spdx3/writer/console/artifact_writer.py | 3 +- .../console/creation_information_writer.py | 3 +- ...pdx_id_map_writer.py => payload_writer.py} | 12 +++++++- src/spdx3/writer/console/tool_writer.py | 20 +++++++++++++ tests/spdx3/bump/test_spdx_document_bump.py | 7 ++--- 7 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 src/spdx3/writer/console/agent_writer.py rename src/spdx3/writer/console/{spdx_id_map_writer.py => payload_writer.py} (83%) create mode 100644 src/spdx3/writer/console/tool_writer.py diff --git a/src/spdx3/clitools/pyspdxtools3.py b/src/spdx3/clitools/pyspdxtools3.py index 224c7c15a..8a39df342 100644 --- a/src/spdx3/clitools/pyspdxtools3.py +++ b/src/spdx3/clitools/pyspdxtools3.py @@ -19,7 +19,7 @@ from spdx.validation.validation_message import ValidationMessage from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document from spdx3.payload import Payload -from spdx3.writer.console.spdx_id_map_writer import write_payload +from spdx3.writer.console.payload_writer import write_payload @click.command() diff --git a/src/spdx3/writer/console/agent_writer.py b/src/spdx3/writer/console/agent_writer.py new file mode 100644 index 000000000..b8fd1c09e --- /dev/null +++ b/src/spdx3/writer/console/agent_writer.py @@ -0,0 +1,28 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.agent import Agent +from spdx3.model.organization import Organization +from spdx3.model.person import Person +from spdx3.model.software_agent import SoftwareAgent +from spdx3.writer.console.element_writer import write_element_properties + + +def write_agent(agent: Agent, text_output: TextIO, heading: bool = True): + if heading: + if isinstance(agent, Person): + text_output.write("## Person\n") + if isinstance(agent, Organization): + text_output.write("## Organization\n") + if isinstance(agent, SoftwareAgent): + text_output.write("## SoftwareAgent\n") + write_element_properties(agent, text_output) diff --git a/src/spdx3/writer/console/artifact_writer.py b/src/spdx3/writer/console/artifact_writer.py index 54ec52805..079365c21 100644 --- a/src/spdx3/writer/console/artifact_writer.py +++ b/src/spdx3/writer/console/artifact_writer.py @@ -11,9 +11,10 @@ from typing import TextIO from spdx3.model.artifact import Artifact +from spdx3.writer.console.console import write_value from spdx3.writer.console.element_writer import write_element_properties def write_artifact_properties(artifact: Artifact, text_output: TextIO): write_element_properties(artifact, text_output) - # write_value("originated_by", artifact.originated_by) not implemented yet + write_value("originated_by", artifact.originated_by, text_output) diff --git a/src/spdx3/writer/console/creation_information_writer.py b/src/spdx3/writer/console/creation_information_writer.py index 9e9c2eb5f..4ec95d538 100644 --- a/src/spdx3/writer/console/creation_information_writer.py +++ b/src/spdx3/writer/console/creation_information_writer.py @@ -19,6 +19,7 @@ def write_creation_info(creation_info: CreationInformation, text_output: TextIO, text_output.write("# Creation Information\n") write_value("specVersion", str(creation_info.spec_version), text_output, indent) write_value("created", datetime_to_iso_string(creation_info.created), text_output, indent) - # write_value("Created By", creation_info.created_by, text_output) not implemented yet + for created_by in creation_info.created_by: + write_value("created by", created_by, text_output, indent) write_value("profile", ", ".join(creation_info.profile), text_output, indent) write_value("data license", creation_info.data_license, text_output, indent) diff --git a/src/spdx3/writer/console/spdx_id_map_writer.py b/src/spdx3/writer/console/payload_writer.py similarity index 83% rename from src/spdx3/writer/console/spdx_id_map_writer.py rename to src/spdx3/writer/console/payload_writer.py index 35fcdffce..b327fc10a 100644 --- a/src/spdx3/writer/console/spdx_id_map_writer.py +++ b/src/spdx3/writer/console/payload_writer.py @@ -13,13 +13,18 @@ from spdx3.model.annotation import Annotation from spdx3.model.bom import Bom from spdx3.model.bundle import Bundle +from spdx3.model.organization import Organization +from spdx3.model.person import Person from spdx3.model.relationship import Relationship from spdx3.model.software.file import File from spdx3.model.software.package import Package from spdx3.model.software.sbom import Sbom from spdx3.model.software.snippet import Snippet +from spdx3.model.software_agent import SoftwareAgent from spdx3.model.spdx_document import SpdxDocument +from spdx3.model.tool import Tool from spdx3.payload import Payload +from spdx3.writer.console.agent_writer import write_agent from spdx3.writer.console.annotation_writer import write_annotation from spdx3.writer.console.bom_writer import write_bom from spdx3.writer.console.bundle_writer import write_bundle @@ -29,6 +34,7 @@ from spdx3.writer.console.software.sbom_writer import write_sbom from spdx3.writer.console.software.snippet_writer import write_snippet from spdx3.writer.console.spdx_document_writer import write_spdx_document +from spdx3.writer.console.tool_writer import write_tool MAP_CLASS_TO_WRITE_METHOD = { Annotation: write_annotation, @@ -39,7 +45,11 @@ File: write_file, Package: write_package, Snippet: write_snippet, - Sbom: write_sbom + Sbom: write_sbom, + Person: write_agent, + Organization: write_agent, + SoftwareAgent: write_agent, + Tool: write_tool } diff --git a/src/spdx3/writer/console/tool_writer.py b/src/spdx3/writer/console/tool_writer.py new file mode 100644 index 000000000..4f20e4df3 --- /dev/null +++ b/src/spdx3/writer/console/tool_writer.py @@ -0,0 +1,20 @@ +# Copyright (c) 2023 spdx contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from typing import TextIO + +from spdx3.model.tool import Tool +from spdx3.writer.console.element_writer import write_element_properties + + +def write_tool(tool: Tool, text_output: TextIO, heading: bool = True): + if heading: + text_output.write("## Tool\n") + write_element_properties(tool, text_output) diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index 21c86f96d..63f59818d 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -11,10 +11,9 @@ import sys from spdx.model.document import Document as Spdx2_Document - from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document from spdx3.payload import Payload -from spdx3.writer.console.spdx_id_map_writer import write_payload +from spdx3.writer.console.payload_writer import write_payload from tests.spdx.fixtures import document_fixture, creation_info_fixture, annotation_fixture @@ -26,8 +25,8 @@ def test_bump_spdx_document(): write_payload(payload, sys.stdout) assert "SPDXRef-Package" in payload.get_full_map() - assert len(payload.get_full_map()) == 6 + assert len(payload.get_full_map()) == 9 - #this is more of a temporary test to make sure the dates don't get messed up again + # this is more of a temporary test to make sure the dates don't get messed up again assert payload.get_element("SPDXRef-DOCUMENT").creation_info.created == creation_info_fixture().created assert payload.get_element("SPDXRef-Annotation-0").creation_info.created == annotation_fixture().annotation_date From 284e322aea1c64cdea61c5d509c76bb01b61768f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 23 Mar 2023 10:58:37 +0100 Subject: [PATCH 163/354] [review] update readme with latest spdx-3 repo commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/spdx3/README.md b/src/spdx3/README.md index 5e4c044ba..0624152dd 100644 --- a/src/spdx3/README.md +++ b/src/spdx3/README.md @@ -1,2 +1 @@ -This implementation is mainly based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 4e7086133a4ec9b7385ce1757a01a33c22711c02). - +This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: 7d45c8040b2fa1f67d77ea244666c991c47c6a9d). From 01a546daa91164d6a5d2d2a33b576fb9c36bf48a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 28 Mar 2023 14:53:51 +0200 Subject: [PATCH 164/354] [spdx-3.0] add created_using to CreationInformation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/annotation.py | 14 +++++++++++--- .../bump_from_spdx2/creation_information.py | 17 +++++++++++++++-- src/spdx3/model/creation_information.py | 7 ++++--- .../console/creation_information_writer.py | 2 ++ tests/spdx3/bump/test_actor_bump.py | 6 +++--- tests/spdx3/bump/test_spdx_document_bump.py | 6 ++++-- tests/spdx3/model/test_agent.py | 4 ++-- tests/spdx3/model/test_creation_information.py | 7 ++++--- tests/spdx3/model/test_tool.py | 4 ++-- 9 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py index 6d6648344..f5a5a44b7 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -10,6 +10,8 @@ # limitations under the License. from copy import deepcopy +from spdx.model.actor import ActorType + from spdx.model.annotation import Annotation as Spdx2_Annotation from spdx3.bump_from_spdx2.actor import bump_actor from spdx3.bump_from_spdx2.message import print_missing_conversion @@ -23,11 +25,17 @@ def bump_annotation(spdx2_annotation: Spdx2_Annotation, payload: Payload, creati spdx_id: str = f"SPDXRef-Annotation-{counter}" creation_info = deepcopy(creation_info) creation_info.created = spdx2_annotation.annotation_date + # caution: the annotator and the annotation will only share the same creation_info if the actor # has not been previously defined - creator_id: str = bump_actor(spdx2_annotation.annotator, payload, creation_info) - creation_info.created_by = [creator_id] - print_missing_conversion("annotation.annotator", 1, "of Entity") + annotator = spdx2_annotation.annotator + creator_id: str = bump_actor(annotator, payload, creation_info) + if annotator.actor_type in [ActorType.PERSON, ActorType.ORGANIZATION]: + creation_info.created_by = [creator_id] + else: + raise NotImplementedError("The SPDX2 annotation is not of Type Person or Organization." + " This case leads to an invalid SPDX3 document and is currently not supported.") + annotation_type: AnnotationType = AnnotationType[spdx2_annotation.annotation_type.name] subject: str = spdx2_annotation.spdx_id statement: str = spdx2_annotation.annotation_comment diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index 785471a38..717e60ccf 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -12,6 +12,8 @@ from typing import List from semantic_version import Version +from spdx.model.actor import ActorType + from spdx3.payload import Payload from spdx.model.document import CreationInfo as Spdx2_CreationInfo @@ -43,15 +45,26 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: print_missing_conversion("creation_info.license_list_version", 0) # creation_info.document_comment -> spdx_document.comment document_comment = spdx2_creation_info.document_comment - creation_information = CreationInformation(Version("3.0.0"), created, [], ["core", "software", "licensing"], + creation_information = CreationInformation(Version("3.0.0"), created, [], [], ["core", "software", "licensing"], data_license) # due to creators having a creation_information themselves which inherits from the document's one, # we have to add them after the creation_information has been initialized creator_ids: List[str] = [] + tool_ids: List[str] = [] for creator in spdx2_creation_info.creators: - creator_ids.append(bump_actor(creator, payload, creation_information)) + bumped_actor_id = bump_actor(creator, payload, creation_information) + if creator.actor_type in [ActorType.PERSON, ActorType.ORGANIZATION]: + creator_ids.append(bumped_actor_id) + else: + tool_ids.append(bumped_actor_id) + + if not creator_ids: + raise NotImplementedError("The SPDX2 creation_info does not contain creators of Type Person or Organization." + " This case leads to an invalid SPDX3 document and is currently not supported.") + creation_information.created_by = creator_ids + creation_information.created_using = tool_ids spdx_document = SpdxDocument(spdx_id=spdx_id, creation_info=creation_information, name=name, comment=document_comment, elements=[], root_elements=[], imports=imports) diff --git a/src/spdx3/model/creation_information.py b/src/spdx3/model/creation_information.py index b613606cb..29a18fef8 100644 --- a/src/spdx3/model/creation_information.py +++ b/src/spdx3/model/creation_information.py @@ -21,10 +21,11 @@ class CreationInformation: spec_version: Version created: datetime - created_by: List[str] # SPDXID of Agents/Tools + created_by: List[str] # SPDXID of Agents + created_using: List[str] # SPDXID of Tools profile: List[str] # or create an Enum for ProfileIdentifier? data_license: str - def __init__(self, spec_version: Version, created: datetime, created_by: List[str], profile: List[str], - data_license: str = "CC0"): + def __init__(self, spec_version: Version, created: datetime, created_by: List[str], created_using: List[str], + profile: List[str], data_license: str = "CC0"): check_types_and_set_values(self, locals()) diff --git a/src/spdx3/writer/console/creation_information_writer.py b/src/spdx3/writer/console/creation_information_writer.py index 4ec95d538..cbff2f85d 100644 --- a/src/spdx3/writer/console/creation_information_writer.py +++ b/src/spdx3/writer/console/creation_information_writer.py @@ -21,5 +21,7 @@ def write_creation_info(creation_info: CreationInformation, text_output: TextIO, write_value("created", datetime_to_iso_string(creation_info.created), text_output, indent) for created_by in creation_info.created_by: write_value("created by", created_by, text_output, indent) + for created_using in creation_info.created_using: + write_value("created using", created_using, text_output, indent) write_value("profile", ", ".join(creation_info.profile), text_output, indent) write_value("data license", creation_info.data_license, text_output, indent) diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index bd065eb49..16432b5df 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -31,7 +31,7 @@ ]) def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_id): payload = Payload() - creation_info = CreationInformation(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], ["core"]) + creation_info = CreationInformation(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], ["core"]) actor = Actor(actor_type, actor_name, actor_mail) agent_or_tool_id = bump_actor(actor, payload, creation_info) @@ -43,8 +43,8 @@ def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_i def test_bump_actor_with_already_existing_actor(): - creation_info_old = CreationInformation(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], ["core"]) - creation_info_new = CreationInformation(Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], ["core"]) + creation_info_old = CreationInformation(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], ["core"]) + creation_info_new = CreationInformation(Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], [], ["core"]) name = "some name" payload = Payload({"SPDXRef-Actor-somename-some@mail.com": diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index 63f59818d..f73dd6a66 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -10,22 +10,24 @@ # limitations under the License. import sys +from spdx.model.actor import ActorType from spdx.model.document import Document as Spdx2_Document from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document from spdx3.payload import Payload from spdx3.writer.console.payload_writer import write_payload -from tests.spdx.fixtures import document_fixture, creation_info_fixture, annotation_fixture +from tests.spdx.fixtures import document_fixture, creation_info_fixture, annotation_fixture, actor_fixture def test_bump_spdx_document(): spdx2_document: Spdx2_Document = document_fixture() + spdx2_document.creation_info.creators.append(actor_fixture(ActorType.TOOL, "tool_name", None)) payload: Payload = bump_spdx_document(spdx2_document) write_payload(payload, sys.stdout) assert "SPDXRef-Package" in payload.get_full_map() - assert len(payload.get_full_map()) == 9 + assert len(payload.get_full_map()) == 10 # this is more of a temporary test to make sure the dates don't get messed up again assert payload.get_element("SPDXRef-DOCUMENT").creation_info.created == creation_info_fixture().created diff --git a/tests/spdx3/model/test_agent.py b/tests/spdx3/model/test_agent.py index f5004e5d1..aa0b352c5 100644 --- a/tests/spdx3/model/test_agent.py +++ b/tests/spdx3/model/test_agent.py @@ -24,11 +24,11 @@ @pytest.mark.parametrize("agent_class", [Agent, Person, Organization, SoftwareAgent]) def test_correct_initialization(agent_class): agent = agent_class("SPDXRef-Agent", - CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], ["core"], "CC0"), + CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0"), external_identifier=[ExternalIdentifier(ExternalIdentifierType.EMAIL, "some@mail.com")]) assert agent.spdx_id == "SPDXRef-Agent" - assert agent.creation_info == CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], + assert agent.creation_info == CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0") assert agent.external_identifier == [ExternalIdentifier(ExternalIdentifierType.EMAIL, "some@mail.com")] diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py index d86ad756d..0a80a89b0 100644 --- a/tests/spdx3/model/test_creation_information.py +++ b/tests/spdx3/model/test_creation_information.py @@ -17,19 +17,20 @@ def test_correct_initialization(): - creation_information = CreationInformation(Version("3.0.0"), datetime(2023, 1, 11, 16, 21), [], + creation_information = CreationInformation(Version("3.0.0"), datetime(2023, 1, 11, 16, 21), [], [], ["core", "software"], "CC0") assert creation_information.spec_version == Version("3.0.0") assert creation_information.created == datetime(2023, 1, 11, 16, 21) assert creation_information.created_by == [] + assert creation_information.created_using == [] assert creation_information.profile == ["core", "software"] assert creation_information.data_license == "CC0" def test_invalid_initialization(): with pytest.raises(TypeError) as err: - CreationInformation("2.3", "2012-01-01", [], "core", 3) + CreationInformation("2.3", "2012-01-01", [], [], "core", 3) assert err.value.args[0] == ['SetterError CreationInformation: type of argument "spec_version" must be ' 'semantic_version.base.Version; got str instead: 2.3', @@ -45,5 +46,5 @@ def test_incomplete_initialization(): with pytest.raises(TypeError) as err: CreationInformation("2.3") - assert "__init__() missing 3 required positional arguments: 'created', 'created_by', and 'profile'" in \ + assert "__init__() missing 4 required positional arguments: 'created', 'created_by', 'created_using', and 'profile'" in \ err.value.args[0] diff --git a/tests/spdx3/model/test_tool.py b/tests/spdx3/model/test_tool.py index b59ab2613..fbe1ef78c 100644 --- a/tests/spdx3/model/test_tool.py +++ b/tests/spdx3/model/test_tool.py @@ -19,10 +19,10 @@ def test_correct_initialization(): agent = Tool("SPDXRef-Tool", - CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], ["core"], "CC0")) + CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0")) assert agent.spdx_id == "SPDXRef-Tool" - assert agent.creation_info == CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], + assert agent.creation_info == CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0") From 10445bed66c897a4b9529947dd09c5799e8bce29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 28 Mar 2023 15:46:43 +0200 Subject: [PATCH 165/354] [review] enhance test_actor_bump.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx3/bump/test_actor_bump.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index 16432b5df..db7dd2efa 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -16,6 +16,7 @@ from spdx.model.actor import Actor, ActorType from spdx3.bump_from_spdx2.actor import bump_actor from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType from spdx3.model.organization import Organization from spdx3.model.person import Person from spdx3.model.tool import Tool @@ -40,9 +41,14 @@ def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_i assert isinstance(agent_or_tool, element_type) assert agent_or_tool.spdx_id == new_spdx_id assert agent_or_tool.name == actor_name + if actor_mail: + assert len(agent_or_tool.external_identifier) == 1 + assert agent_or_tool.external_identifier[0] == ExternalIdentifier(ExternalIdentifierType.EMAIL, actor_mail) + else: + assert len(agent_or_tool.external_identifier) == 0 -def test_bump_actor_with_already_existing_actor(): +def test_bump_actor_that_already_exists(): creation_info_old = CreationInformation(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], ["core"]) creation_info_new = CreationInformation(Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], [], ["core"]) @@ -53,4 +59,7 @@ def test_bump_actor_with_already_existing_actor(): actor = Actor(ActorType.PERSON, name, "some@mail.com") agent_spdx_id = bump_actor(actor, payload, creation_info_new) + # assert that there is only one Person in the payload + assert len([payload.get_element(person_id) for person_id in payload.get_full_map() if + isinstance(payload.get_element(person_id), Person)]) == 1 assert payload.get_element(agent_spdx_id).creation_info == creation_info_old From b04e15e153c32c884af032fca73c9353b53a706d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 29 Mar 2023 10:26:12 +0200 Subject: [PATCH 166/354] [issue-535] use document_namespace in SPDXIDs during 2->3 conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/actor.py | 7 ++++--- src/spdx3/bump_from_spdx2/annotation.py | 9 +++------ src/spdx3/bump_from_spdx2/creation_information.py | 5 +++-- src/spdx3/bump_from_spdx2/file.py | 5 +++-- src/spdx3/bump_from_spdx2/package.py | 7 ++++--- src/spdx3/bump_from_spdx2/relationship.py | 6 ++++-- src/spdx3/bump_from_spdx2/snippet.py | 5 +++-- src/spdx3/bump_from_spdx2/spdx_document.py | 11 ++++++----- tests/spdx3/bump/test_actor_bump.py | 13 ++++++++----- tests/spdx3/bump/test_file_bump.py | 9 ++++++--- tests/spdx3/bump/test_package_bump.py | 10 ++++++---- tests/spdx3/bump/test_snippet_bump.py | 9 ++++++--- tests/spdx3/bump/test_spdx_document_bump.py | 7 ++++--- 13 files changed, 60 insertions(+), 43 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/actor.py b/src/spdx3/bump_from_spdx2/actor.py index a36333fbe..b647ecd5f 100644 --- a/src/spdx3/bump_from_spdx2/actor.py +++ b/src/spdx3/bump_from_spdx2/actor.py @@ -20,7 +20,8 @@ from spdx3.payload import Payload -def bump_actor(spdx2_actor: Spdx2_Actor, payload: Payload, creation_info: CreationInformation) -> str: +def bump_actor(spdx2_actor: Spdx2_Actor, payload: Payload, creation_info: CreationInformation, + document_namespace: str) -> str: name: str = spdx2_actor.name email: str = spdx2_actor.email actor_type: ActorType = spdx2_actor.actor_type @@ -29,9 +30,9 @@ def bump_actor(spdx2_actor: Spdx2_Actor, payload: Payload, creation_info: Creati name_without_whitespace = ''.join(name.split()) if email: external_identifiers.append(ExternalIdentifier(ExternalIdentifierType.EMAIL, email)) - spdx_id: str = f"SPDXRef-Actor-{name_without_whitespace}-{email}" + spdx_id: str = "#".join([document_namespace, f"SPDXRef-Actor-{name_without_whitespace}-{email}"]) else: - spdx_id: str = f"SPDXRef-Actor-{name_without_whitespace}" + spdx_id: str = "#".join([document_namespace, f"SPDXRef-Actor-{name_without_whitespace}"]) if spdx_id in payload.get_full_map(): # the agent/tool already exists, so we don't need to create a new one return spdx_id diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py index f5a5a44b7..e2282d599 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -11,31 +11,28 @@ from copy import deepcopy from spdx.model.actor import ActorType - from spdx.model.annotation import Annotation as Spdx2_Annotation from spdx3.bump_from_spdx2.actor import bump_actor -from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.annotation import Annotation, AnnotationType from spdx3.model.creation_information import CreationInformation from spdx3.payload import Payload def bump_annotation(spdx2_annotation: Spdx2_Annotation, payload: Payload, creation_info: CreationInformation, - counter: int): - spdx_id: str = f"SPDXRef-Annotation-{counter}" + document_namespace: str, counter: int): + spdx_id: str = "#".join([document_namespace, f"SPDXRef-Annotation-{counter}"]) creation_info = deepcopy(creation_info) creation_info.created = spdx2_annotation.annotation_date # caution: the annotator and the annotation will only share the same creation_info if the actor # has not been previously defined annotator = spdx2_annotation.annotator - creator_id: str = bump_actor(annotator, payload, creation_info) + creator_id: str = bump_actor(annotator, payload, creation_info, document_namespace) if annotator.actor_type in [ActorType.PERSON, ActorType.ORGANIZATION]: creation_info.created_by = [creator_id] else: raise NotImplementedError("The SPDX2 annotation is not of Type Person or Organization." " This case leads to an invalid SPDX3 document and is currently not supported.") - annotation_type: AnnotationType = AnnotationType[spdx2_annotation.annotation_type.name] subject: str = spdx2_annotation.spdx_id statement: str = spdx2_annotation.annotation_comment diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index 717e60ccf..e5eae1cef 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -26,7 +26,8 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload) -> SpdxDocument: # creation_info.spdx_id -> spdx_document.spdx_id - spdx_id = spdx2_creation_info.spdx_id + document_namespace = spdx2_creation_info.document_namespace + spdx_id = f"{document_namespace}#{spdx2_creation_info.spdx_id}" # creation_info.name -> spdx_document.name name = spdx2_creation_info.name @@ -53,7 +54,7 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: creator_ids: List[str] = [] tool_ids: List[str] = [] for creator in spdx2_creation_info.creators: - bumped_actor_id = bump_actor(creator, payload, creation_information) + bumped_actor_id = bump_actor(creator, payload, creation_information, document_namespace) if creator.actor_type in [ActorType.PERSON, ActorType.ORGANIZATION]: creator_ids.append(bumped_actor_id) else: diff --git a/src/spdx3/bump_from_spdx2/file.py b/src/spdx3/bump_from_spdx2/file.py index 693248929..064a0622a 100644 --- a/src/spdx3/bump_from_spdx2/file.py +++ b/src/spdx3/bump_from_spdx2/file.py @@ -16,9 +16,10 @@ from spdx3.payload import Payload -def bump_file(spdx2_file: Spdx2_File, payload: Payload, creation_information: CreationInformation): +def bump_file(spdx2_file: Spdx2_File, payload: Payload, creation_information: CreationInformation, + document_namespace: str): + spdx_id = "#".join([document_namespace, spdx2_file.spdx_id]) name = spdx2_file.name - spdx_id = spdx2_file.spdx_id integrity_methods = [bump_checksum(checksum) for checksum in spdx2_file.checksums] # file.checksums -> file.verifiedUsing # file.file_types -> file.content_type (MediaType with Cardinality 1) diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index 2569b3e37..90f78fe6d 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -19,8 +19,9 @@ from spdx3.payload import Payload -def bump_package(spdx2_package: Spdx2_Package, payload: Payload, creation_information: CreationInformation): - spdx_id = spdx2_package.spdx_id +def bump_package(spdx2_package: Spdx2_Package, payload: Payload, creation_information: CreationInformation, + document_namespace: str): + spdx_id = "#".join([document_namespace, spdx2_package.spdx_id]) name = spdx2_package.name download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") # package2.version -> ? @@ -29,7 +30,7 @@ def bump_package(spdx2_package: Spdx2_Package, payload: Payload, creation_inform print_missing_conversion("package2.file_name", 0) # package.supplier -> Relationship, suppliedBy? print_missing_conversion("package2.supplier", 1, "of relationships") - originated_by_spdx_id = bump_actor(spdx2_package.originator, payload, creation_information) + originated_by_spdx_id = bump_actor(spdx2_package.originator, payload, creation_information, document_namespace) # package.files_analyzed -> ? print_missing_conversion("package2.files_analyzed", 0) # package.verification_code -> package.verified_using diff --git a/src/spdx3/bump_from_spdx2/relationship.py b/src/spdx3/bump_from_spdx2/relationship.py index 33260a31c..6d6c29fb9 100644 --- a/src/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx3/bump_from_spdx2/relationship.py @@ -20,9 +20,11 @@ def bump_relationship(spdx2_relationship: Spdx2_Relationship, payload: Payload, - creation_information: CreationInformation, counter: int): + creation_information: CreationInformation, document_namespace: str, counter: int): relationship_type, swap_direction = bump_relationship_type(spdx2_relationship.relationship_type) + spdx_id = "#".join([document_namespace, f"SPDXRef-Relationship-{counter}"]) + if isinstance(spdx2_relationship.related_spdx_element_id, SpdxNoAssertion): # how to translate none/ no assertion to element? completeness = RelationshipCompleteness.UNKNOWN @@ -39,7 +41,7 @@ def bump_relationship(spdx2_relationship: Spdx2_Relationship, payload: Payload, to = [spdx2_relationship.related_spdx_element_id] comment = spdx2_relationship.comment - payload.add_element(Relationship(f"SPDXRef-Relationship-{counter}", creation_information, from_element, to, + payload.add_element(Relationship(spdx_id, creation_information, from_element, to, relationship_type, comment=comment, completeness=completeness)) diff --git a/src/spdx3/bump_from_spdx2/snippet.py b/src/spdx3/bump_from_spdx2/snippet.py index 9951327a9..33b1dc1f6 100644 --- a/src/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx3/bump_from_spdx2/snippet.py @@ -15,8 +15,9 @@ from spdx3.payload import Payload -def bump_snippet(spdx2_snippet: Spdx2_Snippet, payload: Payload, creation_information: CreationInformation): - spdx_id = spdx2_snippet.spdx_id +def bump_snippet(spdx2_snippet: Spdx2_Snippet, payload: Payload, creation_information: CreationInformation, + document_namespace: str): + spdx_id = "#".join([document_namespace, spdx2_snippet.spdx_id]) print_missing_conversion("snippet.file_spdx_id", 0) byte_range = spdx2_snippet.byte_range line_range = spdx2_snippet.line_range diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx3/bump_from_spdx2/spdx_document.py index 20466ba04..13087a3d1 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -26,25 +26,26 @@ def bump_spdx_document(document: Spdx2_Document) -> Payload: payload = Payload() + document_namespace: str = document.creation_info.document_namespace spdx_document: SpdxDocument = bump_creation_information(document.creation_info, payload) creation_info: CreationInformation = spdx_document.creation_info payload.add_element(spdx_document) for spdx2_package in document.packages: - bump_package(spdx2_package, payload, creation_info) + bump_package(spdx2_package, payload, creation_info, document_namespace) for spdx2_file in document.files: - bump_file(spdx2_file, payload, creation_info) + bump_file(spdx2_file, payload, creation_info, document_namespace) for spdx2_snippet in document.snippets: - bump_snippet(spdx2_snippet, payload, creation_info) + bump_snippet(spdx2_snippet, payload, creation_info, document_namespace) for counter, spdx2_relationship in enumerate(document.relationships): - bump_relationship(spdx2_relationship, payload, creation_info, counter) + bump_relationship(spdx2_relationship, payload, creation_info, document_namespace, counter) for counter, spdx2_annotation in enumerate(document.annotations): - bump_annotation(spdx2_annotation, payload, creation_info, counter) + bump_annotation(spdx2_annotation, payload, creation_info, document_namespace, counter) spdx_document.elements = [spdx_id for spdx_id in payload.get_full_map() if spdx_id != spdx_document.spdx_id] diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index db7dd2efa..e78a264eb 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -32,14 +32,15 @@ ]) def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_id): payload = Payload() + document_namespace = "https://doc.namespace" creation_info = CreationInformation(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], ["core"]) actor = Actor(actor_type, actor_name, actor_mail) - agent_or_tool_id = bump_actor(actor, payload, creation_info) + agent_or_tool_id = bump_actor(actor, payload, creation_info, document_namespace) agent_or_tool = payload.get_element(agent_or_tool_id) assert isinstance(agent_or_tool, element_type) - assert agent_or_tool.spdx_id == new_spdx_id + assert agent_or_tool.spdx_id == document_namespace + "#" + new_spdx_id assert agent_or_tool.name == actor_name if actor_mail: assert len(agent_or_tool.external_identifier) == 1 @@ -53,11 +54,13 @@ def test_bump_actor_that_already_exists(): creation_info_new = CreationInformation(Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], [], ["core"]) name = "some name" - payload = Payload({"SPDXRef-Actor-somename-some@mail.com": - Person("SPDXRef-Actor-somename-some@mail.com", creation_info_old, name)}) + document_namespace = "https://doc.namespace" + payload = Payload({"https://doc.namespace#SPDXRef-Actor-somename-some@mail.com": + Person("https://doc.namespace#SPDXRef-Actor-somename-some@mail.com", creation_info_old, + name)}) actor = Actor(ActorType.PERSON, name, "some@mail.com") - agent_spdx_id = bump_actor(actor, payload, creation_info_new) + agent_spdx_id = bump_actor(actor, payload, creation_info_new, document_namespace) # assert that there is only one Person in the payload assert len([payload.get_element(person_id) for person_id in payload.get_full_map() if diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index e4fda1eae..2c6d4aa93 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -24,8 +24,11 @@ def test_bump_file(creation_information): integrity_method: Hash = Hash(HashAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c") payload = Payload() - bump_file(spdx2_file, payload, creation_information=creation_information) - file = payload.get_element(file_fixture().spdx_id) + document_namespace = "https://doc.namespace" + bump_file(spdx2_file, payload, creation_information, document_namespace) + expected_new_file_id = document_namespace + "#" + file_fixture().spdx_id + file = payload.get_element(expected_new_file_id) + assert isinstance(file, File) - assert file.spdx_id == "SPDXRef-File" + assert file.spdx_id == expected_new_file_id assert file.verified_using == [integrity_method] diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 5ed801c51..f1477dd34 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -23,8 +23,10 @@ def test_bump_package(creation_information): spdx2_package: Spdx2_Package = package_fixture() payload = Payload() - bump_package(spdx2_package, payload, creation_information=creation_information) - package = payload.get_element(package_fixture().spdx_id) - assert isinstance(package, Package) + document_namespace = "https://doc.namespace" + bump_package(spdx2_package, payload, creation_information, document_namespace) + expected_new_package_id = document_namespace + "#" + package_fixture().spdx_id + package = payload.get_element(expected_new_package_id) - assert package.spdx_id == "SPDXRef-Package" + assert isinstance(package, Package) + assert package.spdx_id == expected_new_package_id diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index fca70d93d..55857e6a3 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -22,7 +22,10 @@ def test_bump_snippet(creation_information): spdx2_snippet: Spdx2_Snippet = snippet_fixture() payload = Payload() - bump_snippet(spdx2_snippet, payload, creation_information=creation_information) - snippet = payload.get_element(snippet_fixture().spdx_id) + document_namespace = "https://doc.namespace" + bump_snippet(spdx2_snippet, payload, creation_information, document_namespace) + expected_new_snippet_id = document_namespace + "#" + snippet_fixture().spdx_id + snippet = payload.get_element(expected_new_snippet_id) + assert isinstance(snippet, Snippet) - assert snippet.spdx_id == "SPDXRef-Snippet" + assert snippet.spdx_id == expected_new_snippet_id diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index f73dd6a66..193c45dde 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -21,14 +21,15 @@ def test_bump_spdx_document(): spdx2_document: Spdx2_Document = document_fixture() spdx2_document.creation_info.creators.append(actor_fixture(ActorType.TOOL, "tool_name", None)) + document_namespace = document_fixture().creation_info.document_namespace payload: Payload = bump_spdx_document(spdx2_document) write_payload(payload, sys.stdout) - assert "SPDXRef-Package" in payload.get_full_map() + assert "#".join([document_namespace, "SPDXRef-Package"]) in payload.get_full_map() assert len(payload.get_full_map()) == 10 # this is more of a temporary test to make sure the dates don't get messed up again - assert payload.get_element("SPDXRef-DOCUMENT").creation_info.created == creation_info_fixture().created - assert payload.get_element("SPDXRef-Annotation-0").creation_info.created == annotation_fixture().annotation_date + assert payload.get_element("#".join([document_namespace, "SPDXRef-DOCUMENT"])).creation_info.created == creation_info_fixture().created + assert payload.get_element("#".join([document_namespace, "SPDXRef-Annotation-0"])).creation_info.created == annotation_fixture().annotation_date From dfad901179403bbc6b69fdb67618f9a114627e88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 30 Mar 2023 16:46:25 +0200 Subject: [PATCH 167/354] [refactor] use f-strings consistently and reformat some tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/actor.py | 4 ++-- tests/spdx3/bump/test_actor_bump.py | 4 ++-- tests/spdx3/bump/test_file_bump.py | 10 +++++----- tests/spdx3/bump/test_package_bump.py | 9 ++++----- tests/spdx3/bump/test_snippet_bump.py | 10 +++++----- tests/spdx3/bump/test_spdx_document_bump.py | 2 +- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/actor.py b/src/spdx3/bump_from_spdx2/actor.py index b647ecd5f..7e875ec84 100644 --- a/src/spdx3/bump_from_spdx2/actor.py +++ b/src/spdx3/bump_from_spdx2/actor.py @@ -30,9 +30,9 @@ def bump_actor(spdx2_actor: Spdx2_Actor, payload: Payload, creation_info: Creati name_without_whitespace = ''.join(name.split()) if email: external_identifiers.append(ExternalIdentifier(ExternalIdentifierType.EMAIL, email)) - spdx_id: str = "#".join([document_namespace, f"SPDXRef-Actor-{name_without_whitespace}-{email}"]) + spdx_id: str = f"{document_namespace}#SPDXRef-Actor-{name_without_whitespace}-{email}" else: - spdx_id: str = "#".join([document_namespace, f"SPDXRef-Actor-{name_without_whitespace}"]) + spdx_id: str = f"{document_namespace}#SPDXRef-Actor-{name_without_whitespace}" if spdx_id in payload.get_full_map(): # the agent/tool already exists, so we don't need to create a new one return spdx_id diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index e78a264eb..f793aea30 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -35,12 +35,12 @@ def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_i document_namespace = "https://doc.namespace" creation_info = CreationInformation(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], ["core"]) actor = Actor(actor_type, actor_name, actor_mail) - agent_or_tool_id = bump_actor(actor, payload, creation_info, document_namespace) + agent_or_tool_id = bump_actor(actor, payload, creation_info, document_namespace) agent_or_tool = payload.get_element(agent_or_tool_id) assert isinstance(agent_or_tool, element_type) - assert agent_or_tool.spdx_id == document_namespace + "#" + new_spdx_id + assert agent_or_tool.spdx_id == f"{document_namespace}#{new_spdx_id}" assert agent_or_tool.name == actor_name if actor_mail: assert len(agent_or_tool.external_identifier) == 1 diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index 2c6d4aa93..7405cb3bc 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -10,23 +10,23 @@ # limitations under the License. from unittest import mock +from spdx.model.file import File as Spdx2_File from spdx3.bump_from_spdx2.file import bump_file from spdx3.model.hash import Hash, HashAlgorithm from spdx3.model.software.file import File from spdx3.payload import Payload - from tests.spdx.fixtures import file_fixture -from spdx.model.file import File as Spdx2_File + @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_bump_file(creation_information): + payload = Payload() + document_namespace = "https://doc.namespace" spdx2_file: Spdx2_File = file_fixture() integrity_method: Hash = Hash(HashAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c") + expected_new_file_id = f"{document_namespace}#{spdx2_file.spdx_id}" - payload = Payload() - document_namespace = "https://doc.namespace" bump_file(spdx2_file, payload, creation_information, document_namespace) - expected_new_file_id = document_namespace + "#" + file_fixture().spdx_id file = payload.get_element(expected_new_file_id) assert isinstance(file, File) diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index f1477dd34..83bebe996 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -10,22 +10,21 @@ # limitations under the License. from unittest import mock +from spdx.model.package import Package as Spdx2_Package from spdx3.bump_from_spdx2.package import bump_package from spdx3.model.software.package import Package from spdx3.payload import Payload - from tests.spdx.fixtures import package_fixture -from spdx.model.package import Package as Spdx2_Package @mock.patch("spdx3.model.creation_information.CreationInformation") def test_bump_package(creation_information): - spdx2_package: Spdx2_Package = package_fixture() - payload = Payload() document_namespace = "https://doc.namespace" + spdx2_package: Spdx2_Package = package_fixture() + expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" + bump_package(spdx2_package, payload, creation_information, document_namespace) - expected_new_package_id = document_namespace + "#" + package_fixture().spdx_id package = payload.get_element(expected_new_package_id) assert isinstance(package, Package) diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index 55857e6a3..ed3c75948 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -10,21 +10,21 @@ # limitations under the License. from unittest import mock +from spdx.model.snippet import Snippet as Spdx2_Snippet from spdx3.bump_from_spdx2.snippet import bump_snippet +from spdx3.model.software.snippet import Snippet from spdx3.payload import Payload from tests.spdx.fixtures import snippet_fixture -from spdx.model.snippet import Snippet as Spdx2_Snippet -from spdx3.model.software.snippet import Snippet @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_bump_snippet(creation_information): - spdx2_snippet: Spdx2_Snippet = snippet_fixture() - payload = Payload() document_namespace = "https://doc.namespace" + spdx2_snippet: Spdx2_Snippet = snippet_fixture() + expected_new_snippet_id = f"{document_namespace}#{spdx2_snippet.spdx_id}" + bump_snippet(spdx2_snippet, payload, creation_information, document_namespace) - expected_new_snippet_id = document_namespace + "#" + snippet_fixture().spdx_id snippet = payload.get_element(expected_new_snippet_id) assert isinstance(snippet, Snippet) diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index 193c45dde..2c9e1c872 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -27,7 +27,7 @@ def test_bump_spdx_document(): write_payload(payload, sys.stdout) - assert "#".join([document_namespace, "SPDXRef-Package"]) in payload.get_full_map() + assert f"{document_namespace}#SPDXRef-Package" in payload.get_full_map() assert len(payload.get_full_map()) == 10 # this is more of a temporary test to make sure the dates don't get messed up again From bb7ea5c0dc0f74d9ed5c3533cda324a9d545fb4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 3 Apr 2023 10:56:11 +0200 Subject: [PATCH 168/354] [reformat] use isort, black and flake8 in the spdx3 package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/__init__.py | 1 - src/spdx3/bump_from_spdx2/actor.py | 22 ++++---- src/spdx3/bump_from_spdx2/annotation.py | 19 ++++--- src/spdx3/bump_from_spdx2/checksum.py | 5 +- .../bump_from_spdx2/creation_information.py | 35 +++++++----- .../bump_from_spdx2/external_document_ref.py | 2 +- src/spdx3/bump_from_spdx2/file.py | 23 ++++---- src/spdx3/bump_from_spdx2/package.py | 40 +++++++++----- src/spdx3/bump_from_spdx2/relationship.py | 35 ++++++++---- src/spdx3/bump_from_spdx2/snippet.py | 27 +++++++--- src/spdx3/bump_from_spdx2/spdx_document.py | 2 +- src/spdx3/clitools/pyspdxtools3.py | 25 +++++---- src/spdx3/model/__init__.py | 1 - src/spdx3/model/agent.py | 22 +++++--- src/spdx3/model/annotation.py | 26 ++++++--- src/spdx3/model/artifact.py | 2 +- src/spdx3/model/bom.py | 29 ++++++---- src/spdx3/model/bundle.py | 28 ++++++---- src/spdx3/model/creation_information.py | 11 +++- src/spdx3/model/element.py | 2 +- src/spdx3/model/external_identifier.py | 5 +- src/spdx3/model/external_map.py | 10 ++-- src/spdx3/model/external_reference.py | 11 ++-- src/spdx3/model/organization.py | 22 +++++--- src/spdx3/model/person.py | 22 +++++--- src/spdx3/model/relationship.py | 27 +++++++--- src/spdx3/model/software/file.py | 26 ++++++--- src/spdx3/model/software/package.py | 29 ++++++---- src/spdx3/model/software/sbom.py | 31 +++++++---- src/spdx3/model/software/snippet.py | 28 ++++++---- src/spdx3/model/software_agent.py | 22 +++++--- src/spdx3/model/spdx_collection.py | 3 +- src/spdx3/model/spdx_document.py | 30 +++++++---- src/spdx3/model/tool.py | 22 +++++--- src/spdx3/writer/console/console.py | 6 +-- .../console/creation_information_writer.py | 2 +- src/spdx3/writer/console/element_writer.py | 7 +-- .../writer/console/external_map_writer.py | 7 +-- src/spdx3/writer/console/payload_writer.py | 2 +- .../writer/console/software/snippet_writer.py | 2 +- .../writer/console/spdx_collection_writer.py | 2 +- tests/spdx3/bump/test_actor_bump.py | 45 +++++++++++----- tests/spdx3/bump/test_bump_utils.py | 13 +++-- tests/spdx3/bump/test_checksum_bump.py | 44 ++++++++------- tests/spdx3/bump/test_file_bump.py | 2 +- tests/spdx3/bump/test_package_bump.py | 2 +- tests/spdx3/bump/test_snippet_bump.py | 2 +- tests/spdx3/bump/test_spdx_document_bump.py | 16 ++++-- tests/spdx3/model/__init__.py | 1 - tests/spdx3/model/software/__init__.py | 1 - tests/spdx3/model/software/test_file.py | 46 ++++++++++------ tests/spdx3/model/software/test_package.py | 54 +++++++++++-------- tests/spdx3/model/software/test_sbom.py | 11 ++-- tests/spdx3/model/software/test_snippet.py | 25 +++++---- tests/spdx3/model/test_agent.py | 21 +++++--- tests/spdx3/model/test_annotation.py | 39 +++++++++----- tests/spdx3/model/test_bom.py | 13 ++--- tests/spdx3/model/test_bundle.py | 27 ++++++---- .../spdx3/model/test_creation_information.py | 27 +++++----- tests/spdx3/model/test_external_identifier.py | 21 ++++---- tests/spdx3/model/test_external_map.py | 11 ++-- tests/spdx3/model/test_external_reference.py | 24 +++++---- tests/spdx3/model/test_hash.py | 9 ++-- tests/spdx3/model/test_namespace_map.py | 9 ++-- tests/spdx3/model/test_relationship.py | 30 ++++++----- tests/spdx3/model/test_spdx_document.py | 25 +++++---- tests/spdx3/model/test_tool.py | 19 ++++--- 67 files changed, 774 insertions(+), 436 deletions(-) diff --git a/src/spdx3/__init__.py b/src/spdx3/__init__.py index 8b1378917..e69de29bb 100644 --- a/src/spdx3/__init__.py +++ b/src/spdx3/__init__.py @@ -1 +0,0 @@ - diff --git a/src/spdx3/bump_from_spdx2/actor.py b/src/spdx3/bump_from_spdx2/actor.py index 7e875ec84..7e1a72062 100644 --- a/src/spdx3/bump_from_spdx2/actor.py +++ b/src/spdx3/bump_from_spdx2/actor.py @@ -10,44 +10,48 @@ # limitations under the License. from typing import List -from spdx.model.actor import Actor as Spdx2_Actor, ActorType from spdx3.model.creation_information import CreationInformation from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType from spdx3.model.organization import Organization from spdx3.model.person import Person -from spdx3.model.software_agent import SoftwareAgent from spdx3.model.tool import Tool from spdx3.payload import Payload +from spdx.model.actor import Actor as Spdx2_Actor +from spdx.model.actor import ActorType -def bump_actor(spdx2_actor: Spdx2_Actor, payload: Payload, creation_info: CreationInformation, - document_namespace: str) -> str: +def bump_actor( + spdx2_actor: Spdx2_Actor, payload: Payload, creation_info: CreationInformation, document_namespace: str +) -> str: name: str = spdx2_actor.name email: str = spdx2_actor.email actor_type: ActorType = spdx2_actor.actor_type external_identifiers: List[ExternalIdentifier] = [] - name_without_whitespace = ''.join(name.split()) + name_without_whitespace = "".join(name.split()) if email: external_identifiers.append(ExternalIdentifier(ExternalIdentifierType.EMAIL, email)) spdx_id: str = f"{document_namespace}#SPDXRef-Actor-{name_without_whitespace}-{email}" else: spdx_id: str = f"{document_namespace}#SPDXRef-Actor-{name_without_whitespace}" - if spdx_id in payload.get_full_map(): # the agent/tool already exists, so we don't need to create a new one + if spdx_id in payload.get_full_map(): # the agent/tool already exists, so we don't need to create a new one return spdx_id if actor_type == ActorType.PERSON: agent_or_tool = Person( - spdx_id=spdx_id, creation_info=creation_info, name=name, external_identifier=external_identifiers) + spdx_id=spdx_id, creation_info=creation_info, name=name, external_identifier=external_identifiers + ) elif actor_type == ActorType.ORGANIZATION: agent_or_tool = Organization( - spdx_id=spdx_id, creation_info=creation_info, name=name, external_identifier=external_identifiers) + spdx_id=spdx_id, creation_info=creation_info, name=name, external_identifier=external_identifiers + ) elif actor_type == ActorType.TOOL: agent_or_tool = Tool( - spdx_id=spdx_id, creation_info=creation_info, name=name, external_identifier=external_identifiers) + spdx_id=spdx_id, creation_info=creation_info, name=name, external_identifier=external_identifiers + ) else: raise ValueError(f"no conversion rule defined for ActorType {actor_type}") diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py index e2282d599..61c1fdabc 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -10,16 +10,21 @@ # limitations under the License. from copy import deepcopy -from spdx.model.actor import ActorType -from spdx.model.annotation import Annotation as Spdx2_Annotation from spdx3.bump_from_spdx2.actor import bump_actor from spdx3.model.annotation import Annotation, AnnotationType from spdx3.model.creation_information import CreationInformation from spdx3.payload import Payload +from spdx.model.actor import ActorType +from spdx.model.annotation import Annotation as Spdx2_Annotation -def bump_annotation(spdx2_annotation: Spdx2_Annotation, payload: Payload, creation_info: CreationInformation, - document_namespace: str, counter: int): +def bump_annotation( + spdx2_annotation: Spdx2_Annotation, + payload: Payload, + creation_info: CreationInformation, + document_namespace: str, + counter: int, +): spdx_id: str = "#".join([document_namespace, f"SPDXRef-Annotation-{counter}"]) creation_info = deepcopy(creation_info) creation_info.created = spdx2_annotation.annotation_date @@ -31,8 +36,10 @@ def bump_annotation(spdx2_annotation: Spdx2_Annotation, payload: Payload, creati if annotator.actor_type in [ActorType.PERSON, ActorType.ORGANIZATION]: creation_info.created_by = [creator_id] else: - raise NotImplementedError("The SPDX2 annotation is not of Type Person or Organization." - " This case leads to an invalid SPDX3 document and is currently not supported.") + raise NotImplementedError( + "The SPDX2 annotation is not of Type Person or Organization." + " This case leads to an invalid SPDX3 document and is currently not supported." + ) annotation_type: AnnotationType = AnnotationType[spdx2_annotation.annotation_type.name] subject: str = spdx2_annotation.spdx_id statement: str = spdx2_annotation.annotation_comment diff --git a/src/spdx3/bump_from_spdx2/checksum.py b/src/spdx3/bump_from_spdx2/checksum.py index 5ec72e048..6bbbc208a 100644 --- a/src/spdx3/bump_from_spdx2/checksum.py +++ b/src/spdx3/bump_from_spdx2/checksum.py @@ -8,8 +8,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from spdx.model.checksum import Checksum as Spdx2_Checksum, ChecksumAlgorithm -from spdx3.model.hash import HashAlgorithm, Hash +from spdx3.model.hash import Hash, HashAlgorithm +from spdx.model.checksum import Checksum as Spdx2_Checksum +from spdx.model.checksum import ChecksumAlgorithm def bump_checksum(spdx2_checksum: Spdx2_Checksum) -> Hash: diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index e5eae1cef..fe79cf778 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -12,16 +12,15 @@ from typing import List from semantic_version import Version -from spdx.model.actor import ActorType - -from spdx3.payload import Payload -from spdx.model.document import CreationInfo as Spdx2_CreationInfo from spdx3.bump_from_spdx2.actor import bump_actor from spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.creation_information import CreationInformation from spdx3.model.spdx_document import SpdxDocument +from spdx3.payload import Payload +from spdx.model.actor import ActorType +from spdx.model.document import CreationInfo as Spdx2_CreationInfo def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload) -> SpdxDocument: @@ -40,14 +39,17 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: print_missing_conversion("creation_info.creator_comment", 0) data_license = spdx2_creation_info.data_license # creation_info.external_document_refs -> spdx_document.imports - imports = [bump_external_document_ref(external_document_ref) for external_document_ref in - spdx2_creation_info.external_document_refs] + imports = [ + bump_external_document_ref(external_document_ref) + for external_document_ref in spdx2_creation_info.external_document_refs + ] # creation_info.license_list_version -> ? print_missing_conversion("creation_info.license_list_version", 0) # creation_info.document_comment -> spdx_document.comment document_comment = spdx2_creation_info.document_comment - creation_information = CreationInformation(Version("3.0.0"), created, [], [], ["core", "software", "licensing"], - data_license) + creation_information = CreationInformation( + Version("3.0.0"), created, [], [], ["core", "software", "licensing"], data_license + ) # due to creators having a creation_information themselves which inherits from the document's one, # we have to add them after the creation_information has been initialized @@ -61,13 +63,22 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: tool_ids.append(bumped_actor_id) if not creator_ids: - raise NotImplementedError("The SPDX2 creation_info does not contain creators of Type Person or Organization." - " This case leads to an invalid SPDX3 document and is currently not supported.") + raise NotImplementedError( + "The SPDX2 creation_info does not contain creators of Type Person or Organization." + " This case leads to an invalid SPDX3 document and is currently not supported." + ) creation_information.created_by = creator_ids creation_information.created_using = tool_ids - spdx_document = SpdxDocument(spdx_id=spdx_id, creation_info=creation_information, name=name, - comment=document_comment, elements=[], root_elements=[], imports=imports) + spdx_document = SpdxDocument( + spdx_id=spdx_id, + creation_info=creation_information, + name=name, + comment=document_comment, + elements=[], + root_elements=[], + imports=imports, + ) return spdx_document diff --git a/src/spdx3/bump_from_spdx2/external_document_ref.py b/src/spdx3/bump_from_spdx2/external_document_ref.py index 4a7f4b2df..cf211b4d2 100644 --- a/src/spdx3/bump_from_spdx2/external_document_ref.py +++ b/src/spdx3/bump_from_spdx2/external_document_ref.py @@ -10,10 +10,10 @@ # limitations under the License. from typing import List -from spdx.model.external_document_ref import ExternalDocumentRef from spdx3.bump_from_spdx2.checksum import bump_checksum from spdx3.model.external_map import ExternalMap from spdx3.model.hash import Hash +from spdx.model.external_document_ref import ExternalDocumentRef def bump_external_document_ref(external_document_ref: ExternalDocumentRef) -> ExternalMap: diff --git a/src/spdx3/bump_from_spdx2/file.py b/src/spdx3/bump_from_spdx2/file.py index 064a0622a..0a70eccd5 100644 --- a/src/spdx3/bump_from_spdx2/file.py +++ b/src/spdx3/bump_from_spdx2/file.py @@ -8,16 +8,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from spdx.model.file import File as Spdx2_File from spdx3.bump_from_spdx2.checksum import bump_checksum from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.creation_information import CreationInformation from spdx3.model.software.file import File from spdx3.payload import Payload +from spdx.model.file import File as Spdx2_File -def bump_file(spdx2_file: Spdx2_File, payload: Payload, creation_information: CreationInformation, - document_namespace: str): +def bump_file( + spdx2_file: Spdx2_File, payload: Payload, creation_information: CreationInformation, document_namespace: str +): spdx_id = "#".join([document_namespace, spdx2_file.spdx_id]) name = spdx2_file.name integrity_methods = [bump_checksum(checksum) for checksum in spdx2_file.checksums] @@ -25,12 +26,16 @@ def bump_file(spdx2_file: Spdx2_File, payload: Payload, creation_information: Cr # file.file_types -> file.content_type (MediaType with Cardinality 1) print_missing_conversion("file.file_type", 0, "different cardinalities") print_missing_conversion( - "file.concluded_license, file.license_info_in_file, file.license_comment, file.copyright_text", 0, - "missing definition for license profile") + "file.concluded_license, file.license_info_in_file, file.license_comment, file.copyright_text", + 0, + "missing definition for license profile", + ) comment = spdx2_file.comment - print_missing_conversion("file.notice, file.contributors, file.attribution_texts", 0, - "missing definition for license profile") + print_missing_conversion( + "file.notice, file.contributors, file.attribution_texts", 0, "missing definition for license profile" + ) - payload.add_element(File(spdx_id, creation_info=creation_information, name=name, comment=comment, - verified_using=integrity_methods)) + payload.add_element( + File(spdx_id, creation_info=creation_information, name=name, comment=comment, verified_using=integrity_methods) + ) diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index 90f78fe6d..2c22a237e 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -8,7 +8,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from spdx.model.package import Package as Spdx2_Package from spdx3.bump_from_spdx2.actor import bump_actor from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none from spdx3.bump_from_spdx2.checksum import bump_checksum @@ -17,10 +16,12 @@ from spdx3.model.software.package import Package from spdx3.model.software.software_purpose import SoftwarePurpose from spdx3.payload import Payload +from spdx.model.package import Package as Spdx2_Package -def bump_package(spdx2_package: Spdx2_Package, payload: Payload, creation_information: CreationInformation, - document_namespace: str): +def bump_package( + spdx2_package: Spdx2_Package, payload: Payload, creation_information: CreationInformation, document_namespace: str +): spdx_id = "#".join([document_namespace, spdx2_package.spdx_id]) name = spdx2_package.name download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") @@ -39,19 +40,34 @@ def bump_package(spdx2_package: Spdx2_Package, payload: Payload, creation_inform integrity_methods = [bump_checksum(checksum) for checksum in spdx2_package.checksums] homepage = spdx2_package.homepage print_missing_conversion("package2.source_info", 0) - print_missing_conversion("package2.license_concluded, package2.license_info_from_files, package2.license_declared, " - "package2.license_comment, package2.copyright_text", 0, - "and missing definition of license profile") + print_missing_conversion( + "package2.license_concluded, package2.license_info_from_files, package2.license_declared, " + "package2.license_comment, package2.copyright_text", + 0, + "and missing definition of license profile", + ) summary = spdx2_package.summary description = spdx2_package.description comment = spdx2_package.comment print_missing_conversion("package2.external_references", 1, "of ExternalReferences / ExternalIdentifiers") print_missing_conversion("package2.attribution_texts", 0) - package_purpose = [SoftwarePurpose[ - spdx2_package.primary_package_purpose.name]] if spdx2_package.primary_package_purpose else [] + package_purpose = ( + [SoftwarePurpose[spdx2_package.primary_package_purpose.name]] if spdx2_package.primary_package_purpose else [] + ) print_missing_conversion("package2.release_date, package2.built_date, package2.valid_until_date", 0) - payload.add_element(Package(spdx_id, creation_information, name, verified_using=integrity_methods, - download_location=download_location, homepage=homepage, summary=summary, - description=description, comment=comment, originated_by=originated_by_spdx_id, - package_purpose=package_purpose)) + payload.add_element( + Package( + spdx_id, + creation_information, + name, + verified_using=integrity_methods, + download_location=download_location, + homepage=homepage, + summary=summary, + description=description, + comment=comment, + originated_by=originated_by_spdx_id, + package_purpose=package_purpose, + ) + ) diff --git a/src/spdx3/bump_from_spdx2/relationship.py b/src/spdx3/bump_from_spdx2/relationship.py index 6d6c29fb9..daa1db148 100644 --- a/src/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx3/bump_from_spdx2/relationship.py @@ -8,25 +8,31 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Tuple, Optional +from typing import Optional, Tuple +from spdx3.model.creation_information import CreationInformation +from spdx3.model.relationship import Relationship, RelationshipCompleteness, RelationshipType +from spdx3.payload import Payload from spdx.model.relationship import Relationship as Spdx2_Relationship from spdx.model.relationship import RelationshipType as Spdx2_RelationshipType from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone -from spdx3.model.creation_information import CreationInformation -from spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness -from spdx3.payload import Payload -def bump_relationship(spdx2_relationship: Spdx2_Relationship, payload: Payload, - creation_information: CreationInformation, document_namespace: str, counter: int): +def bump_relationship( + spdx2_relationship: Spdx2_Relationship, + payload: Payload, + creation_information: CreationInformation, + document_namespace: str, + counter: int, +): relationship_type, swap_direction = bump_relationship_type(spdx2_relationship.relationship_type) spdx_id = "#".join([document_namespace, f"SPDXRef-Relationship-{counter}"]) - if isinstance(spdx2_relationship.related_spdx_element_id, - SpdxNoAssertion): # how to translate none/ no assertion to element? + if isinstance( + spdx2_relationship.related_spdx_element_id, SpdxNoAssertion + ): # how to translate none/ no assertion to element? completeness = RelationshipCompleteness.UNKNOWN elif isinstance(spdx2_relationship.related_spdx_element_id, SpdxNone): completeness = RelationshipCompleteness.KNOWN @@ -41,8 +47,17 @@ def bump_relationship(spdx2_relationship: Spdx2_Relationship, payload: Payload, to = [spdx2_relationship.related_spdx_element_id] comment = spdx2_relationship.comment - payload.add_element(Relationship(spdx_id, creation_information, from_element, to, - relationship_type, comment=comment, completeness=completeness)) + payload.add_element( + Relationship( + spdx_id, + creation_information, + from_element, + to, + relationship_type, + comment=comment, + completeness=completeness, + ) + ) def bump_relationship_type(spdx2_relationship_type: Spdx2_RelationshipType) -> Optional[Tuple[RelationshipType, bool]]: diff --git a/src/spdx3/bump_from_spdx2/snippet.py b/src/spdx3/bump_from_spdx2/snippet.py index 33b1dc1f6..574bf0288 100644 --- a/src/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx3/bump_from_spdx2/snippet.py @@ -8,25 +8,38 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from spdx.model.snippet import Snippet as Spdx2_Snippet from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.creation_information import CreationInformation from spdx3.model.software.snippet import Snippet from spdx3.payload import Payload +from spdx.model.snippet import Snippet as Spdx2_Snippet -def bump_snippet(spdx2_snippet: Spdx2_Snippet, payload: Payload, creation_information: CreationInformation, - document_namespace: str): +def bump_snippet( + spdx2_snippet: Spdx2_Snippet, payload: Payload, creation_information: CreationInformation, document_namespace: str +): spdx_id = "#".join([document_namespace, spdx2_snippet.spdx_id]) print_missing_conversion("snippet.file_spdx_id", 0) byte_range = spdx2_snippet.byte_range line_range = spdx2_snippet.line_range - print_missing_conversion("snippet.concluded_license, snippet.license_info_in_snippet, snippet.license_comment," - "snippet.copyright_text", 0, "missing definitions for license profile") + print_missing_conversion( + "snippet.concluded_license, snippet.license_info_in_snippet, snippet.license_comment," + "snippet.copyright_text", + 0, + "missing definitions for license profile", + ) comment = spdx2_snippet.comment name = spdx2_snippet.name print_missing_conversion("snippet.attribution_texts", 0, "missing definitions for license profile") - payload.add_element(Snippet(spdx_id=spdx_id, creation_info=creation_information, byte_range=byte_range, - line_range=line_range, comment=comment, name=name)) + payload.add_element( + Snippet( + spdx_id=spdx_id, + creation_info=creation_information, + byte_range=byte_range, + line_range=line_range, + comment=comment, + name=name, + ) + ) diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx3/bump_from_spdx2/spdx_document.py index 13087a3d1..67407e33c 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -8,7 +8,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from spdx.model.document import Document as Spdx2_Document from spdx3.bump_from_spdx2.annotation import bump_annotation from spdx3.bump_from_spdx2.creation_information import bump_creation_information from spdx3.bump_from_spdx2.file import bump_file @@ -18,6 +17,7 @@ from spdx3.model.creation_information import CreationInformation from spdx3.model.spdx_document import SpdxDocument from spdx3.payload import Payload +from spdx.model.document import Document as Spdx2_Document """ We want to implement a bump_from_spdx2 from the data model in src.spdx to the data model in src.spdx3. As there are many fundamental differences between these version we want each bump_from_spdx2 method to take diff --git a/src/spdx3/clitools/pyspdxtools3.py b/src/spdx3/clitools/pyspdxtools3.py index 8a39df342..5c612bda6 100644 --- a/src/spdx3/clitools/pyspdxtools3.py +++ b/src/spdx3/clitools/pyspdxtools3.py @@ -13,22 +13,29 @@ import click +from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document +from spdx3.payload import Payload +from spdx3.writer.console.payload_writer import write_payload from spdx.model.document import Document from spdx.parser.parse_anything import parse_file from spdx.validation.document_validator import validate_full_spdx_document from spdx.validation.validation_message import ValidationMessage -from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document -from spdx3.payload import Payload -from spdx3.writer.console.payload_writer import write_payload @click.command() -@click.option("--infile", "-i", prompt="input file path", - help="The file containing the document to be validated or converted.") -@click.option("--outfile", "-o", - help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion).") -@click.option("--version", help='The SPDX version to be used during parsing and validation (format "SPDX-2.3").', - default="SPDX-2.3") +@click.option( + "--infile", "-i", prompt="input file path", help="The file containing the document to be validated or converted." +) +@click.option( + "--outfile", + "-o", + help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion).", +) +@click.option( + "--version", + help='The SPDX version to be used during parsing and validation (format "SPDX-2.3").', + default="SPDX-2.3", +) @click.option("--novalidation", is_flag=True, help="Don't validate the provided document.") def main(infile: str, outfile: str, version: str, novalidation: bool): """ diff --git a/src/spdx3/model/__init__.py b/src/spdx3/model/__init__.py index 8b1378917..e69de29bb 100644 --- a/src/spdx3/model/__init__.py +++ b/src/spdx3/model/__init__.py @@ -1 +0,0 @@ - diff --git a/src/spdx3/model/agent.py b/src/spdx3/model/agent.py index 86d2b9255..b1019d821 100644 --- a/src/spdx3/model/agent.py +++ b/src/spdx3/model/agent.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -21,13 +21,19 @@ @dataclass_with_properties class Agent(Element): - - def __init__(self, spdx_id: str, creation_info: CreationInformation, - name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/annotation.py b/src/spdx3/model/annotation.py index daabf0b79..75784bad4 100644 --- a/src/spdx3/model/annotation.py +++ b/src/spdx3/model/annotation.py @@ -9,7 +9,7 @@ # See the License for the specific language governing permissions and # limitations under the License. from enum import Enum, auto -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -32,13 +32,23 @@ class Annotation(Element): content_type: Optional[str] = None # placeholder for MediaType statement: Optional[str] = None - def __init__(self, spdx_id: str, creation_info: CreationInformation, annotation_type: AnnotationType, - subject: str, name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, - content_type: Optional[str] = None, statement: Optional[str] = None): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + annotation_type: AnnotationType, + subject: str, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + content_type: Optional[str] = None, + statement: Optional[str] = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/artifact.py b/src/spdx3/model/artifact.py index 7b5ce6791..2cc3c548d 100644 --- a/src/spdx3/model/artifact.py +++ b/src/spdx3/model/artifact.py @@ -17,7 +17,7 @@ @dataclass_with_properties class Artifact(Element): - originated_by: Optional[str] = None # SPDXID of the Agent/Tool + originated_by: Optional[str] = None # SPDXID of the Agent/Tool @abstractmethod def __init__(self): diff --git a/src/spdx3/model/bom.py b/src/spdx3/model/bom.py index 8e4a52bec..fc62da46c 100644 --- a/src/spdx3/model/bom.py +++ b/src/spdx3/model/bom.py @@ -23,16 +23,27 @@ @dataclass_with_properties class Bom(Bundle): - # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). + # We overwrite the super-__init__ as check_types_and_set_values() + # takes care of all fields (including inherited ones). - def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[str], - root_elements: List[str], name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, - imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + elements: List[str], + root_elements: List[str], + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + namespaces: Optional[List[NamespaceMap]] = None, + imports: Optional[List[ExternalMap]] = None, + context: Optional[str] = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/bundle.py b/src/spdx3/model/bundle.py index fe269a786..d6928ba76 100644 --- a/src/spdx3/model/bundle.py +++ b/src/spdx3/model/bundle.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -25,14 +25,24 @@ class Bundle(SpdxCollection): context: Optional[str] = None - def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[str], - root_elements: List[str], name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, - imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + elements: List[str], + root_elements: List[str], + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + namespaces: Optional[List[NamespaceMap]] = None, + imports: Optional[List[ExternalMap]] = None, + context: Optional[str] = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/creation_information.py b/src/spdx3/model/creation_information.py index 29a18fef8..19dced748 100644 --- a/src/spdx3/model/creation_information.py +++ b/src/spdx3/model/creation_information.py @@ -26,6 +26,13 @@ class CreationInformation: profile: List[str] # or create an Enum for ProfileIdentifier? data_license: str - def __init__(self, spec_version: Version, created: datetime, created_by: List[str], created_using: List[str], - profile: List[str], data_license: str = "CC0"): + def __init__( + self, + spec_version: Version, + created: datetime, + created_by: List[str], + created_using: List[str], + profile: List[str], + data_license: str = "CC0", + ): check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index 8d1218479..ca57390ef 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -10,7 +10,7 @@ # limitations under the License. from abc import ABC, abstractmethod from dataclasses import field -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from spdx3.model.creation_information import CreationInformation diff --git a/src/spdx3/model/external_identifier.py b/src/spdx3/model/external_identifier.py index 93a5dcab9..a65959c94 100644 --- a/src/spdx3/model/external_identifier.py +++ b/src/spdx3/model/external_identifier.py @@ -33,6 +33,7 @@ class ExternalIdentifier: identifier: str comment: Optional[str] = None - def __init__(self, external_identifier_type: ExternalIdentifierType, identifier: str, - comment: Optional[str] = None): + def __init__( + self, external_identifier_type: ExternalIdentifierType, identifier: str, comment: Optional[str] = None + ): check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/external_map.py b/src/spdx3/model/external_map.py index 22d91e470..1cdbf21f6 100644 --- a/src/spdx3/model/external_map.py +++ b/src/spdx3/model/external_map.py @@ -9,7 +9,7 @@ # See the License for the specific language governing permissions and # limitations under the License. from dataclasses import field -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -22,7 +22,11 @@ class ExternalMap: verified_using: Optional[List[IntegrityMethod]] = field(default_factory=list) location_hint: Optional[str] = None # anyURI - def __init__(self, external_id: str, verified_using: Optional[List[IntegrityMethod]] = None, - location_hint: Optional[str] = None): + def __init__( + self, + external_id: str, + verified_using: Optional[List[IntegrityMethod]] = None, + location_hint: Optional[str] = None, + ): verified_using = [] if verified_using is None else verified_using check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/external_reference.py b/src/spdx3/model/external_reference.py index 083a95cc7..44009f875 100644 --- a/src/spdx3/model/external_reference.py +++ b/src/spdx3/model/external_reference.py @@ -10,7 +10,7 @@ # limitations under the License. from dataclasses import field from enum import Enum, auto -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -32,7 +32,12 @@ class ExternalReference: content_type: Optional[str] = None # placeholder for MediaType comment: Optional[str] = None - def __init__(self, external_reference_type: Optional[ExternalReferenceType] = None, locator: List[str] = None, - content_type: Optional[str] = None, comment: Optional[str] = None): + def __init__( + self, + external_reference_type: Optional[ExternalReferenceType] = None, + locator: List[str] = None, + content_type: Optional[str] = None, + comment: Optional[str] = None, + ): locator = [] if locator is None else locator check_types_and_set_values(self, locals()) diff --git a/src/spdx3/model/organization.py b/src/spdx3/model/organization.py index f48d3053c..bce54b55b 100644 --- a/src/spdx3/model/organization.py +++ b/src/spdx3/model/organization.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -21,13 +21,19 @@ @dataclass_with_properties class Organization(Agent): - - def __init__(self, spdx_id: str, creation_info: CreationInformation, - name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/person.py b/src/spdx3/model/person.py index 2b6e45719..6b7c004b8 100644 --- a/src/spdx3/model/person.py +++ b/src/spdx3/model/person.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -21,13 +21,19 @@ @dataclass_with_properties class Person(Agent): - - def __init__(self, spdx_id: str, creation_info: CreationInformation, - name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/relationship.py b/src/spdx3/model/relationship.py index 986efb7b8..85c58f33a 100644 --- a/src/spdx3/model/relationship.py +++ b/src/spdx3/model/relationship.py @@ -71,19 +71,30 @@ class RelationshipCompleteness(Enum): @dataclass_with_properties class Relationship(Element): - # due to the inheritance we need to make all fields non-default in the __annotation__, the __init__ method still raises an error if required fields are not set + # due to the inheritance we need to make all fields non-default in the __annotation__, + # the __init__ method still raises an error if required fields are not set from_element: str = None to: List[str] = None relationship_type: RelationshipType = None completeness: Optional[RelationshipCompleteness] = None - def __init__(self, spdx_id: str, creation_info: CreationInformation, from_element: str, to: List[str], - relationship_type: RelationshipType, name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, - completeness: Optional[RelationshipCompleteness] = None): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + from_element: str, + to: List[str], + relationship_type: RelationshipType, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + completeness: Optional[RelationshipCompleteness] = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index 01c94394d..0cd9e85b9 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -26,13 +26,23 @@ class File(Artifact): file_purpose: Optional[List[SoftwarePurpose]] = None content_type: Optional[str] = None # placeholder for MediaType - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, - originated_by: Optional[str] = None, content_identifier: Optional[str] = None, - file_purpose: Optional[List[SoftwarePurpose]] = None, content_type: Optional[str] = None): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + originated_by: Optional[str] = None, + content_identifier: Optional[str] = None, + file_purpose: Optional[List[SoftwarePurpose]] = None, + content_type: Optional[str] = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 03deb7b05..d8bfb1f7e 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -28,14 +28,25 @@ class Package(Artifact): package_uri: Optional[str] = None # anyURI homepage: Optional[str] = None # anyURI - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, - originated_by: Optional[str] = None, content_identifier: Optional[str] = None, - package_purpose: Optional[List[SoftwarePurpose]] = None, download_location: Optional[str] = None, - package_uri: Optional[str] = None, homepage: Optional[str] = None): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + originated_by: Optional[str] = None, + content_identifier: Optional[str] = None, + package_purpose: Optional[List[SoftwarePurpose]] = None, + download_location: Optional[str] = None, + package_uri: Optional[str] = None, + homepage: Optional[str] = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index 79aa354ea..f96af8e59 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -23,15 +23,26 @@ @dataclass_with_properties class Sbom(Bom): - # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). - def __init__(self, spdx_id: str, creation_info: CreationInformation, elements: List[str], - root_elements: List[str], name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, - imports: Optional[List[ExternalMap]] = None, context: Optional[str] = None): + # We overwrite the super-__init__ as check_types_and_set_values() + # takes care of all fields (including inherited ones). + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + elements: List[str], + root_elements: List[str], + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + namespaces: Optional[List[NamespaceMap]] = None, + imports: Optional[List[ExternalMap]] = None, + context: Optional[str] = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index 2e2b31d51..e8dc8cc33 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, Tuple, List +from typing import List, Optional, Tuple from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -27,14 +27,24 @@ class Snippet(Artifact): byte_range: Optional[Tuple[int, int]] = None line_range: Optional[Tuple[int, int]] = None - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: Optional[str] = None, - summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, - originated_by: Optional[str] = None, content_identifier: Optional[str] = None, - snippet_purpose: Optional[List[SoftwarePurpose]] = None, byte_range: Optional[Tuple[int, int]] = None, - line_range: Optional[Tuple[int, int]] = None): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + originated_by: Optional[str] = None, + content_identifier: Optional[str] = None, + snippet_purpose: Optional[List[SoftwarePurpose]] = None, + byte_range: Optional[Tuple[int, int]] = None, + line_range: Optional[Tuple[int, int]] = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/software_agent.py b/src/spdx3/model/software_agent.py index 44f6ee710..b9b6a0cca 100644 --- a/src/spdx3/model/software_agent.py +++ b/src/spdx3/model/software_agent.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -21,13 +21,19 @@ @dataclass_with_properties class SoftwareAgent(Agent): - - def __init__(self, spdx_id: str, creation_info: CreationInformation, - name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/spdx_collection.py b/src/spdx3/model/spdx_collection.py index e912df0e9..7ad0f2c6a 100644 --- a/src/spdx3/model/spdx_collection.py +++ b/src/spdx3/model/spdx_collection.py @@ -20,7 +20,8 @@ @dataclass_with_properties class SpdxCollection(Element): - # due to the inheritance we need to make all fields non-default in the __annotation__, the __init__ method still raises an error if required fields are not set + # due to the inheritance we need to make all fields non-default in the __annotation__, + # the __init__ method still raises an error if required fields are not set elements: List[str] = field(default_factory=list) root_elements: List[str] = field(default_factory=list) namespaces: Optional[List[NamespaceMap]] = field(default_factory=list) diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index 95f41bd4d..efec50e4a 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -24,14 +24,26 @@ @dataclass_with_properties class SpdxDocument(Bundle): # The inherited field "name" is required for a SpdxDocument, no longer optional. - # We overwrite the super-__init__ as check_types_and_set_values() takes care of all fields (including inherited ones). - def __init__(self, spdx_id: str, creation_info: CreationInformation, name: str, elements: List[str], - root_elements: List[str], summary: Optional[str] = None, description: Optional[str] = None, - comment: Optional[str] = None, verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, imports: Optional[List[ExternalMap]] = None, - context: Optional[str] = None): + # We overwrite the super-__init__ as check_types_and_set_values() + # takes care of all fields (including inherited ones). + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: str, + elements: List[str], + root_elements: List[str], + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + namespaces: Optional[List[NamespaceMap]] = None, + imports: Optional[List[ExternalMap]] = None, + context: Optional[str] = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/model/tool.py b/src/spdx3/model/tool.py index 659e2923b..40fcb9e03 100644 --- a/src/spdx3/model/tool.py +++ b/src/spdx3/model/tool.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional, List +from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties from common.typing.type_checks import check_types_and_set_values @@ -21,13 +21,19 @@ @dataclass_with_properties class Tool(Element): - - def __init__(self, spdx_id: str, creation_info: CreationInformation, - name: Optional[str] = None, summary: Optional[str] = None, - description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: Optional[List[IntegrityMethod]] = None, + external_references: Optional[List[ExternalReference]] = None, + external_identifier: Optional[List[ExternalIdentifier]] = None, + extension: None = None, + ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx3/writer/console/console.py b/src/spdx3/writer/console/console.py index 1138a1731..d2cc07ae7 100644 --- a/src/spdx3/writer/console/console.py +++ b/src/spdx3/writer/console/console.py @@ -9,12 +9,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import TextIO, Union, Optional +from typing import Optional, TextIO, Union def write_value(tag: str, value: Optional[Union[bool, str]], out: TextIO, indent: bool = False): - """ This function is duplicated from spdx.writer.tagvalue.tag_value_writer_helper_functions and slightly adapted to - make indentation of output possible.""" + """This function is duplicated from spdx.writer.tagvalue.tag_value_writer_helper_functions and slightly adapted to + make indentation of output possible.""" if not value: return if indent: diff --git a/src/spdx3/writer/console/creation_information_writer.py b/src/spdx3/writer/console/creation_information_writer.py index cbff2f85d..13078ee59 100644 --- a/src/spdx3/writer/console/creation_information_writer.py +++ b/src/spdx3/writer/console/creation_information_writer.py @@ -10,9 +10,9 @@ # limitations under the License. from typing import TextIO -from spdx.datetime_conversions import datetime_to_iso_string from spdx3.model.creation_information import CreationInformation from spdx3.writer.console.console import write_value +from spdx.datetime_conversions import datetime_to_iso_string def write_creation_info(creation_info: CreationInformation, text_output: TextIO, indent: bool = True): diff --git a/src/spdx3/writer/console/element_writer.py b/src/spdx3/writer/console/element_writer.py index 2258ed626..b55fc70f4 100644 --- a/src/spdx3/writer/console/element_writer.py +++ b/src/spdx3/writer/console/element_writer.py @@ -10,13 +10,13 @@ # limitations under the License. from typing import TextIO -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading from spdx3.model.element import Element from spdx3.writer.console.console import write_value from spdx3.writer.console.creation_information_writer import write_creation_info from spdx3.writer.console.external_identifier_writer import write_external_identifier from spdx3.writer.console.external_reference_writer import write_external_reference from spdx3.writer.console.hash_writer import write_hash +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading def write_element_properties(element: Element, text_output: TextIO): @@ -28,8 +28,9 @@ def write_element_properties(element: Element, text_output: TextIO): write_value("comment", element.comment, text_output) write_optional_heading(element.verified_using, "verified using:\n", text_output) for integrity_method in element.verified_using: - # for now Hash is the only child class of the abstract class IntegrityMethod, as soon as there are more inherited - # classes we need to implement a logic that determines the correct write function for the "integrity_method" object + # for now Hash is the only child class of the abstract class IntegrityMethod, + # as soon as there are more inherited classes we need to implement a logic + # that determines the correct write function for the "integrity_method" object write_hash(integrity_method, text_output, heading=False) write_optional_heading(element.external_references, "External References", text_output) for external_reference in element.external_references: diff --git a/src/spdx3/writer/console/external_map_writer.py b/src/spdx3/writer/console/external_map_writer.py index a0c53f72a..119fcc3c9 100644 --- a/src/spdx3/writer/console/external_map_writer.py +++ b/src/spdx3/writer/console/external_map_writer.py @@ -10,17 +10,18 @@ # limitations under the License. from typing import TextIO -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading from spdx3.model.external_map import ExternalMap from spdx3.writer.console.console import write_value from spdx3.writer.console.hash_writer import write_hash +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading def write_external_map(external_map: ExternalMap, text_output: TextIO): write_value("external_id", external_map.external_id, text_output) write_optional_heading(external_map.verified_using, "verified using\n", text_output) for integrity_method in external_map.verified_using: - # for now Hash is the only child class of the abstract class IntegrityMethod, as soon as there are more inherited - # classes we need to implement a logic that determines the correct write function for the "integrity_method" object + # for now Hash is the only child class of the abstract class IntegrityMethod, + # as soon as there are more inherited classes we need to implement a logic + # that determines the correct write function for the "integrity_method" object write_hash(integrity_method, text_output, heading=False) write_value("location_hint", external_map.location_hint, text_output) diff --git a/src/spdx3/writer/console/payload_writer.py b/src/spdx3/writer/console/payload_writer.py index b327fc10a..a7786972d 100644 --- a/src/spdx3/writer/console/payload_writer.py +++ b/src/spdx3/writer/console/payload_writer.py @@ -49,7 +49,7 @@ Person: write_agent, Organization: write_agent, SoftwareAgent: write_agent, - Tool: write_tool + Tool: write_tool, } diff --git a/src/spdx3/writer/console/software/snippet_writer.py b/src/spdx3/writer/console/software/snippet_writer.py index 44191aaf9..cfb077de4 100644 --- a/src/spdx3/writer/console/software/snippet_writer.py +++ b/src/spdx3/writer/console/software/snippet_writer.py @@ -10,10 +10,10 @@ # limitations under the License. from typing import TextIO -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range from spdx3.model.software.snippet import Snippet from spdx3.writer.console.artifact_writer import write_artifact_properties from spdx3.writer.console.console import write_value +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range def write_snippet(snippet: Snippet, text_output: TextIO): diff --git a/src/spdx3/writer/console/spdx_collection_writer.py b/src/spdx3/writer/console/spdx_collection_writer.py index 1a0f2c4db..009e16dd8 100644 --- a/src/spdx3/writer/console/spdx_collection_writer.py +++ b/src/spdx3/writer/console/spdx_collection_writer.py @@ -10,11 +10,11 @@ # limitations under the License. from typing import TextIO -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading from spdx3.model.spdx_collection import SpdxCollection from spdx3.writer.console.element_writer import write_element_properties from spdx3.writer.console.external_map_writer import write_external_map from spdx3.writer.console.namespace_map_writer import write_namespace_map +from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading def write_collection(collection: SpdxCollection, text_output: TextIO): diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index f793aea30..0b9dc2387 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -13,7 +13,6 @@ import pytest from semantic_version import Version -from spdx.model.actor import Actor, ActorType from spdx3.bump_from_spdx2.actor import bump_actor from spdx3.model.creation_information import CreationInformation from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType @@ -21,15 +20,23 @@ from spdx3.model.person import Person from spdx3.model.tool import Tool from spdx3.payload import Payload +from spdx.model.actor import Actor, ActorType -@pytest.mark.parametrize("actor_type, actor_name, actor_mail, element_type, new_spdx_id", - [(ActorType.PERSON, "person name", "person@mail.com", Person, - "SPDXRef-Actor-personname-person@mail.com"), - (ActorType.ORGANIZATION, "organization name", "organization@mail.com", Organization, - "SPDXRef-Actor-organizationname-organization@mail.com"), - (ActorType.TOOL, "tool name", None, Tool, "SPDXRef-Actor-toolname"), - ]) +@pytest.mark.parametrize( + "actor_type, actor_name, actor_mail, element_type, new_spdx_id", + [ + (ActorType.PERSON, "person name", "person@mail.com", Person, "SPDXRef-Actor-personname-person@mail.com"), + ( + ActorType.ORGANIZATION, + "organization name", + "organization@mail.com", + Organization, + "SPDXRef-Actor-organizationname-organization@mail.com", + ), + (ActorType.TOOL, "tool name", None, Tool, "SPDXRef-Actor-toolname"), + ], +) def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_id): payload = Payload() document_namespace = "https://doc.namespace" @@ -55,14 +62,26 @@ def test_bump_actor_that_already_exists(): name = "some name" document_namespace = "https://doc.namespace" - payload = Payload({"https://doc.namespace#SPDXRef-Actor-somename-some@mail.com": - Person("https://doc.namespace#SPDXRef-Actor-somename-some@mail.com", creation_info_old, - name)}) + payload = Payload( + { + "https://doc.namespace#SPDXRef-Actor-somename-some@mail.com": Person( + "https://doc.namespace#SPDXRef-Actor-somename-some@mail.com", creation_info_old, name + ) + } + ) actor = Actor(ActorType.PERSON, name, "some@mail.com") agent_spdx_id = bump_actor(actor, payload, creation_info_new, document_namespace) # assert that there is only one Person in the payload - assert len([payload.get_element(person_id) for person_id in payload.get_full_map() if - isinstance(payload.get_element(person_id), Person)]) == 1 + assert ( + len( + [ + payload.get_element(person_id) + for person_id in payload.get_full_map() + if isinstance(payload.get_element(person_id), Person) + ] + ) + == 1 + ) assert payload.get_element(agent_spdx_id).creation_info == creation_info_old diff --git a/tests/spdx3/bump/test_bump_utils.py b/tests/spdx3/bump/test_bump_utils.py index dc32e63c2..0251e2a15 100644 --- a/tests/spdx3/bump/test_bump_utils.py +++ b/tests/spdx3/bump/test_bump_utils.py @@ -10,14 +10,19 @@ # limitations under the License. import pytest +from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none from spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx.model.spdx_none import SpdxNone -from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none -@pytest.mark.parametrize("input_argument,expected_value,expected_stdout", - [(SpdxNone(), None, "test_field: Missing conversion for SpdxNone.\n"), - (SpdxNoAssertion(), None, ""), ("test_string", "test_string", "")]) +@pytest.mark.parametrize( + "input_argument,expected_value,expected_stdout", + [ + (SpdxNone(), None, "test_field: Missing conversion for SpdxNone.\n"), + (SpdxNoAssertion(), None, ""), + ("test_string", "test_string", ""), + ], +) def test_handle_no_assertion_or_none(input_argument, expected_value, expected_stdout, capsys): value = handle_no_assertion_or_none(input_argument, "test_field") diff --git a/tests/spdx3/bump/test_checksum_bump.py b/tests/spdx3/bump/test_checksum_bump.py index 6391110b5..35a2291a7 100644 --- a/tests/spdx3/bump/test_checksum_bump.py +++ b/tests/spdx3/bump/test_checksum_bump.py @@ -10,10 +10,10 @@ # limitations under the License. import pytest -from tests.spdx.fixtures import checksum_fixture -from spdx.model.checksum import ChecksumAlgorithm from spdx3.bump_from_spdx2.checksum import bump_checksum, convert_checksum_algorithm_to_hash_algorithm from spdx3.model.hash import HashAlgorithm +from spdx.model.checksum import ChecksumAlgorithm +from tests.spdx.fixtures import checksum_fixture def test_bump_checksum(): @@ -24,24 +24,28 @@ def test_bump_checksum(): assert hash.hash_value == "71c4025dd9897b364f3ebbb42c484ff43d00791c" -@pytest.mark.parametrize("checksum_algorithm,expected_hash_algorithm", - [(ChecksumAlgorithm.SHA1, HashAlgorithm.SHA1), - (ChecksumAlgorithm.SHA224, HashAlgorithm.SHA224), - (ChecksumAlgorithm.SHA256, HashAlgorithm.SHA256), - (ChecksumAlgorithm.SHA384, HashAlgorithm.SHA384), - (ChecksumAlgorithm.SHA512, HashAlgorithm.SHA512), - (ChecksumAlgorithm.SHA3_256, HashAlgorithm.SHA3_256), - (ChecksumAlgorithm.SHA3_384, HashAlgorithm.SHA3_384), - (ChecksumAlgorithm.SHA3_512, HashAlgorithm.SHA3_512), - (ChecksumAlgorithm.BLAKE2B_256, HashAlgorithm.BLAKE2B256), - (ChecksumAlgorithm.BLAKE2B_384, HashAlgorithm.BLAKE2B384), - (ChecksumAlgorithm.BLAKE2B_512, HashAlgorithm.BLAKE2B512), - (ChecksumAlgorithm.BLAKE3, HashAlgorithm.BLAKE3), - (ChecksumAlgorithm.MD2, HashAlgorithm.MD2), - (ChecksumAlgorithm.MD4, HashAlgorithm.MD4), - (ChecksumAlgorithm.MD5, HashAlgorithm.MD5), - (ChecksumAlgorithm.MD6, HashAlgorithm.MD6), - (ChecksumAlgorithm.ADLER32, HashAlgorithm.OTHER)]) +@pytest.mark.parametrize( + "checksum_algorithm,expected_hash_algorithm", + [ + (ChecksumAlgorithm.SHA1, HashAlgorithm.SHA1), + (ChecksumAlgorithm.SHA224, HashAlgorithm.SHA224), + (ChecksumAlgorithm.SHA256, HashAlgorithm.SHA256), + (ChecksumAlgorithm.SHA384, HashAlgorithm.SHA384), + (ChecksumAlgorithm.SHA512, HashAlgorithm.SHA512), + (ChecksumAlgorithm.SHA3_256, HashAlgorithm.SHA3_256), + (ChecksumAlgorithm.SHA3_384, HashAlgorithm.SHA3_384), + (ChecksumAlgorithm.SHA3_512, HashAlgorithm.SHA3_512), + (ChecksumAlgorithm.BLAKE2B_256, HashAlgorithm.BLAKE2B256), + (ChecksumAlgorithm.BLAKE2B_384, HashAlgorithm.BLAKE2B384), + (ChecksumAlgorithm.BLAKE2B_512, HashAlgorithm.BLAKE2B512), + (ChecksumAlgorithm.BLAKE3, HashAlgorithm.BLAKE3), + (ChecksumAlgorithm.MD2, HashAlgorithm.MD2), + (ChecksumAlgorithm.MD4, HashAlgorithm.MD4), + (ChecksumAlgorithm.MD5, HashAlgorithm.MD5), + (ChecksumAlgorithm.MD6, HashAlgorithm.MD6), + (ChecksumAlgorithm.ADLER32, HashAlgorithm.OTHER), + ], +) def test_bump_checksum_algorithm(checksum_algorithm, expected_hash_algorithm): hash_algorithm = convert_checksum_algorithm_to_hash_algorithm(checksum_algorithm) diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index 7405cb3bc..9c5e71a25 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -10,11 +10,11 @@ # limitations under the License. from unittest import mock -from spdx.model.file import File as Spdx2_File from spdx3.bump_from_spdx2.file import bump_file from spdx3.model.hash import Hash, HashAlgorithm from spdx3.model.software.file import File from spdx3.payload import Payload +from spdx.model.file import File as Spdx2_File from tests.spdx.fixtures import file_fixture diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 83bebe996..cfe8c1014 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -10,10 +10,10 @@ # limitations under the License. from unittest import mock -from spdx.model.package import Package as Spdx2_Package from spdx3.bump_from_spdx2.package import bump_package from spdx3.model.software.package import Package from spdx3.payload import Payload +from spdx.model.package import Package as Spdx2_Package from tests.spdx.fixtures import package_fixture diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index ed3c75948..ef9d61d88 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -10,10 +10,10 @@ # limitations under the License. from unittest import mock -from spdx.model.snippet import Snippet as Spdx2_Snippet from spdx3.bump_from_spdx2.snippet import bump_snippet from spdx3.model.software.snippet import Snippet from spdx3.payload import Payload +from spdx.model.snippet import Snippet as Spdx2_Snippet from tests.spdx.fixtures import snippet_fixture diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index 2c9e1c872..ab2f463cf 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -10,12 +10,12 @@ # limitations under the License. import sys -from spdx.model.actor import ActorType -from spdx.model.document import Document as Spdx2_Document from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document from spdx3.payload import Payload from spdx3.writer.console.payload_writer import write_payload -from tests.spdx.fixtures import document_fixture, creation_info_fixture, annotation_fixture, actor_fixture +from spdx.model.actor import ActorType +from spdx.model.document import Document as Spdx2_Document +from tests.spdx.fixtures import actor_fixture, annotation_fixture, creation_info_fixture, document_fixture def test_bump_spdx_document(): @@ -31,5 +31,11 @@ def test_bump_spdx_document(): assert len(payload.get_full_map()) == 10 # this is more of a temporary test to make sure the dates don't get messed up again - assert payload.get_element("#".join([document_namespace, "SPDXRef-DOCUMENT"])).creation_info.created == creation_info_fixture().created - assert payload.get_element("#".join([document_namespace, "SPDXRef-Annotation-0"])).creation_info.created == annotation_fixture().annotation_date + assert ( + payload.get_element("#".join([document_namespace, "SPDXRef-DOCUMENT"])).creation_info.created + == creation_info_fixture().created + ) + assert ( + payload.get_element("#".join([document_namespace, "SPDXRef-Annotation-0"])).creation_info.created + == annotation_fixture().annotation_date + ) diff --git a/tests/spdx3/model/__init__.py b/tests/spdx3/model/__init__.py index 8b1378917..e69de29bb 100644 --- a/tests/spdx3/model/__init__.py +++ b/tests/spdx3/model/__init__.py @@ -1 +0,0 @@ - diff --git a/tests/spdx3/model/software/__init__.py b/tests/spdx3/model/software/__init__.py index 8b1378917..e69de29bb 100644 --- a/tests/spdx3/model/software/__init__.py +++ b/tests/spdx3/model/software/__init__.py @@ -1 +0,0 @@ - diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index 77bf568eb..3de745e33 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -12,15 +12,20 @@ import pytest -from spdx3.model.software.software_purpose import SoftwarePurpose - from spdx3.model.software.file import File +from spdx3.model.software.software_purpose import SoftwarePurpose @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): - file = File("SPDXRef-File", creation_information, verified_using=None, content_identifier="https://any.uri", - file_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE], content_type="MediaType") + file = File( + "SPDXRef-File", + creation_information, + verified_using=None, + content_identifier="https://any.uri", + file_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE], + content_type="MediaType", + ) assert file.spdx_id == "SPDXRef-File" assert file.creation_info == creation_information @@ -32,16 +37,23 @@ def test_correct_initialization(creation_information): @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: - File(1, creation_information, content_identifier=3, file_purpose=SoftwarePurpose.FILE, - content_type=SoftwarePurpose.ARCHIVE) - - assert err.value.args[0] == ['SetterError File: type of argument "spdx_id" must be str; got int instead: 1', - 'SetterError File: type of argument "content_identifier" must be one of (str, ' - 'NoneType); got int instead: 3', - 'SetterError File: type of argument "file_purpose" must be one of ' - '(List[spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got ' - 'spdx3.model.software.software_purpose.SoftwarePurpose instead: ' - 'SoftwarePurpose.FILE', - 'SetterError File: type of argument "content_type" must be one of (str, ' - 'NoneType); got spdx3.model.software.software_purpose.SoftwarePurpose ' - 'instead: SoftwarePurpose.ARCHIVE'] + File( + 1, + creation_information, + content_identifier=3, + file_purpose=SoftwarePurpose.FILE, + content_type=SoftwarePurpose.ARCHIVE, + ) + + assert err.value.args[0] == [ + 'SetterError File: type of argument "spdx_id" must be str; got int instead: 1', + 'SetterError File: type of argument "content_identifier" must be one of (str, ' + "NoneType); got int instead: 3", + 'SetterError File: type of argument "file_purpose" must be one of ' + "(List[spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got " + "spdx3.model.software.software_purpose.SoftwarePurpose instead: " + "SoftwarePurpose.FILE", + 'SetterError File: type of argument "content_type" must be one of (str, ' + "NoneType); got spdx3.model.software.software_purpose.SoftwarePurpose " + "instead: SoftwarePurpose.ARCHIVE", + ] diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 2933085f3..0b4f034d9 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -12,17 +12,21 @@ import pytest -from spdx3.model.software.software_purpose import SoftwarePurpose - from spdx3.model.software.package import Package +from spdx3.model.software.software_purpose import SoftwarePurpose @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): - package = Package("SPDXRef-Package", creation_information, content_identifier="https://any.uri", - package_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH], - download_location="https://downloadlocation", package_uri="https://package.uri", - homepage="https://homepage") + package = Package( + "SPDXRef-Package", + creation_information, + content_identifier="https://any.uri", + package_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH], + download_location="https://downloadlocation", + package_uri="https://package.uri", + homepage="https://homepage", + ) assert package.spdx_id == "SPDXRef-Package" assert package.creation_info == creation_information @@ -36,18 +40,26 @@ def test_correct_initialization(creation_information): @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: - Package("SPDXRef-Package", creation_information, content_identifier=3, package_purpose=SoftwarePurpose.FILE, - download_location=4, package_uri=["uris"], homepage=True) - - assert err.value.args[0] == ['SetterError Package: type of argument "content_identifier" must be one of ' - '(str, NoneType); got int instead: 3', - 'SetterError Package: type of argument "package_purpose" must be one of ' - '(List[spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got ' - 'spdx3.model.software.software_purpose.SoftwarePurpose instead: ' - 'SoftwarePurpose.FILE', - 'SetterError Package: type of argument "download_location" must be one of ' - '(str, NoneType); got int instead: 4', - 'SetterError Package: type of argument "package_uri" must be one of (str, ' - "NoneType); got list instead: ['uris']", - 'SetterError Package: type of argument "homepage" must be one of (str, ' - 'NoneType); got bool instead: True'] + Package( + "SPDXRef-Package", + creation_information, + content_identifier=3, + package_purpose=SoftwarePurpose.FILE, + download_location=4, + package_uri=["uris"], + homepage=True, + ) + + assert err.value.args[0] == [ + 'SetterError Package: type of argument "content_identifier" must be one of ' + "(str, NoneType); got int instead: 3", + 'SetterError Package: type of argument "package_purpose" must be one of ' + "(List[spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got " + "spdx3.model.software.software_purpose.SoftwarePurpose instead: " + "SoftwarePurpose.FILE", + 'SetterError Package: type of argument "download_location" must be one of ' + "(str, NoneType); got int instead: 4", + 'SetterError Package: type of argument "package_uri" must be one of (str, ' + "NoneType); got list instead: ['uris']", + 'SetterError Package: type of argument "homepage" must be one of (str, ' "NoneType); got bool instead: True", + ] diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index f3d64a4a2..ee8f99690 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -24,11 +24,14 @@ def test_correct_initialization(creation_information): assert sbom.elements == ["spdx_id1", "spdx_id2"] assert sbom.root_elements == ["spdx_id3"] + def test_invalid_initialization(): with pytest.raises(TypeError) as err: Sbom(2, {"creation_info": [3, 4, 5]}, elements=[], root_elements=[]) - assert err.value.args[0] == ['SetterError Sbom: type of argument "spdx_id" must be str; got int instead: 2', - 'SetterError Sbom: type of argument "creation_info" must be ' - 'spdx3.model.creation_information.CreationInformation; got dict instead: ' - "{'creation_info': [3, 4, 5]}"] + assert err.value.args[0] == [ + 'SetterError Sbom: type of argument "spdx_id" must be str; got int instead: 2', + 'SetterError Sbom: type of argument "creation_info" must be ' + "spdx3.model.creation_information.CreationInformation; got dict instead: " + "{'creation_info': [3, 4, 5]}", + ] diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index b6701162f..143ca6dc1 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -12,15 +12,20 @@ import pytest -from spdx3.model.software.software_purpose import SoftwarePurpose - from spdx3.model.software.snippet import Snippet +from spdx3.model.software.software_purpose import SoftwarePurpose @mock.patch("spdx3.model.software.snippet.Snippet", autospec=True) def test_correct_initialization(creation_information): - snippet = Snippet("SPDXRef-Snippet", creation_information, content_identifier="https://content.identifier", - snippet_purpose=[SoftwarePurpose.SOURCE], byte_range=(3, 4), line_range=(346, 456)) + snippet = Snippet( + "SPDXRef-Snippet", + creation_information, + content_identifier="https://content.identifier", + snippet_purpose=[SoftwarePurpose.SOURCE], + byte_range=(3, 4), + line_range=(346, 456), + ) assert snippet.spdx_id == "SPDXRef-Snippet" assert snippet.creation_info == creation_information @@ -35,9 +40,9 @@ def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Snippet(2, creation_information, originated_by=34, byte_range="34:45") - assert err.value.args[0] == ['SetterError Snippet: type of argument "spdx_id" must be str; got int ' - 'instead: 2', - 'SetterError Snippet: type of argument "originated_by" must be one of (str, ' - 'NoneType); got int instead: 34', - 'SetterError Snippet: type of argument "byte_range" must be one of ' - '(Tuple[int, int], NoneType); got str instead: 34:45'] + assert err.value.args[0] == [ + 'SetterError Snippet: type of argument "spdx_id" must be str; got int ' "instead: 2", + 'SetterError Snippet: type of argument "originated_by" must be one of (str, ' "NoneType); got int instead: 34", + 'SetterError Snippet: type of argument "byte_range" must be one of ' + "(Tuple[int, int], NoneType); got str instead: 34:45", + ] diff --git a/tests/spdx3/model/test_agent.py b/tests/spdx3/model/test_agent.py index aa0b352c5..f1e6cdb1c 100644 --- a/tests/spdx3/model/test_agent.py +++ b/tests/spdx3/model/test_agent.py @@ -23,13 +23,16 @@ @pytest.mark.parametrize("agent_class", [Agent, Person, Organization, SoftwareAgent]) def test_correct_initialization(agent_class): - agent = agent_class("SPDXRef-Agent", - CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0"), - external_identifier=[ExternalIdentifier(ExternalIdentifierType.EMAIL, "some@mail.com")]) + agent = agent_class( + "SPDXRef-Agent", + CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0"), + external_identifier=[ExternalIdentifier(ExternalIdentifierType.EMAIL, "some@mail.com")], + ) assert agent.spdx_id == "SPDXRef-Agent" - assert agent.creation_info == CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], - ["core"], "CC0") + assert agent.creation_info == CreationInformation( + Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0" + ) assert agent.external_identifier == [ExternalIdentifier(ExternalIdentifierType.EMAIL, "some@mail.com")] @@ -38,6 +41,8 @@ def test_invalid_initialization(agent_class): with pytest.raises(TypeError) as err: agent_class(12, 345) - assert err.value.args[0] == [f'SetterError {agent_class.__name__}: type of argument "spdx_id" must be str; got int instead: 12', - f'SetterError {agent_class.__name__}: type of argument "creation_info" must be ' - 'spdx3.model.creation_information.CreationInformation; got int instead: 345'] + assert err.value.args[0] == [ + f'SetterError {agent_class.__name__}: type of argument "spdx_id" must be str; got int instead: 12', + f'SetterError {agent_class.__name__}: type of argument "creation_info" must be ' + "spdx3.model.creation_information.CreationInformation; got int instead: 345", + ] diff --git a/tests/spdx3/model/test_annotation.py b/tests/spdx3/model/test_annotation.py index 061c69ace..4da76571a 100644 --- a/tests/spdx3/model/test_annotation.py +++ b/tests/spdx3/model/test_annotation.py @@ -17,8 +17,14 @@ @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): - annotation = Annotation("SPDXRef-Annotation", creation_information, AnnotationType.OTHER, "spdx_id1", - content_type="mediaType", statement="This is a statement") + annotation = Annotation( + "SPDXRef-Annotation", + creation_information, + AnnotationType.OTHER, + "spdx_id1", + content_type="mediaType", + statement="This is a statement", + ) assert annotation.spdx_id == "SPDXRef-Annotation" assert annotation.creation_info == creation_information @@ -31,14 +37,21 @@ def test_correct_initialization(creation_information): @mock.patch("spdx3.model.creation_information.CreationInformation") def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: - Annotation("SPDXRef-Annotation", creation_information, "REVIEW", {"element": 1}, content_type=4, - statement=["some statements"]) - - assert err.value.args[0] == ['SetterError Annotation: type of argument "annotation_type" must be ' - 'spdx3.model.annotation.AnnotationType; got str instead: REVIEW', - 'SetterError Annotation: type of argument "subject" must be str; got dict ' - "instead: {'element': 1}", - 'SetterError Annotation: type of argument "content_type" must be one of (str, ' - 'NoneType); got int instead: 4', - 'SetterError Annotation: type of argument "statement" must be one of (str, ' - "NoneType); got list instead: ['some statements']"] + Annotation( + "SPDXRef-Annotation", + creation_information, + "REVIEW", + {"element": 1}, + content_type=4, + statement=["some statements"], + ) + + assert err.value.args[0] == [ + 'SetterError Annotation: type of argument "annotation_type" must be ' + "spdx3.model.annotation.AnnotationType; got str instead: REVIEW", + 'SetterError Annotation: type of argument "subject" must be str; got dict ' "instead: {'element': 1}", + 'SetterError Annotation: type of argument "content_type" must be one of (str, ' + "NoneType); got int instead: 4", + 'SetterError Annotation: type of argument "statement" must be one of (str, ' + "NoneType); got list instead: ['some statements']", + ] diff --git a/tests/spdx3/model/test_bom.py b/tests/spdx3/model/test_bom.py index e3b38448a..168ba5dd4 100644 --- a/tests/spdx3/model/test_bom.py +++ b/tests/spdx3/model/test_bom.py @@ -30,9 +30,10 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: Bom(1, "Creation Information", elements=[5], root_elements=[]) - assert err.value.args[0] == ['SetterError Bom: type of argument "spdx_id" must be str; got int instead: 1', - 'SetterError Bom: type of argument "creation_info" must be ' - 'spdx3.model.creation_information.CreationInformation; got str instead: ' - 'Creation Information', - 'SetterError Bom: type of argument "elements"[0] must be ' - 'str; got int instead: [5]'] + assert err.value.args[0] == [ + 'SetterError Bom: type of argument "spdx_id" must be str; got int instead: 1', + 'SetterError Bom: type of argument "creation_info" must be ' + "spdx3.model.creation_information.CreationInformation; got str instead: " + "Creation Information", + 'SetterError Bom: type of argument "elements"[0] must be ' "str; got int instead: [5]", + ] diff --git a/tests/spdx3/model/test_bundle.py b/tests/spdx3/model/test_bundle.py index ec33d2627..541dc15b6 100644 --- a/tests/spdx3/model/test_bundle.py +++ b/tests/spdx3/model/test_bundle.py @@ -18,8 +18,14 @@ @mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information, namespace): - bundle = Bundle("SPDXRef-Bundle", creation_information, elements=["spdx_id1"], root_elements=["spdx_id2"], - namespaces=[namespace], context="context") + bundle = Bundle( + "SPDXRef-Bundle", + creation_information, + elements=["spdx_id1"], + root_elements=["spdx_id2"], + namespaces=[namespace], + context="context", + ) assert bundle.spdx_id == "SPDXRef-Bundle" assert bundle.creation_info == creation_information @@ -34,12 +40,11 @@ def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Bundle(4, creation_information, elements="spdx_id1", root_elements=[42], namespaces=True, context=["yes"]) - assert err.value.args[0] == ['SetterError Bundle: type of argument "spdx_id" must be str; got int instead: 4', - 'SetterError Bundle: type of argument "elements" must be a list; got str ' - 'instead: spdx_id1', - 'SetterError Bundle: type of argument "root_elements"[0] must be str; got int ' - 'instead: [42]', - 'SetterError Bundle: type of argument "namespaces" must be one of ' - '(List[spdx3.model.namespace_map.NamespaceMap], NoneType); got bool instead: True', - 'SetterError Bundle: type of argument "context" must be one of (str, ' - "NoneType); got list instead: ['yes']"] + assert err.value.args[0] == [ + 'SetterError Bundle: type of argument "spdx_id" must be str; got int instead: 4', + 'SetterError Bundle: type of argument "elements" must be a list; got str ' "instead: spdx_id1", + 'SetterError Bundle: type of argument "root_elements"[0] must be str; got int ' "instead: [42]", + 'SetterError Bundle: type of argument "namespaces" must be one of ' + "(List[spdx3.model.namespace_map.NamespaceMap], NoneType); got bool instead: True", + 'SetterError Bundle: type of argument "context" must be one of (str, ' "NoneType); got list instead: ['yes']", + ] diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py index 0a80a89b0..f64ad2f9a 100644 --- a/tests/spdx3/model/test_creation_information.py +++ b/tests/spdx3/model/test_creation_information.py @@ -17,8 +17,9 @@ def test_correct_initialization(): - creation_information = CreationInformation(Version("3.0.0"), datetime(2023, 1, 11, 16, 21), [], [], - ["core", "software"], "CC0") + creation_information = CreationInformation( + Version("3.0.0"), datetime(2023, 1, 11, 16, 21), [], [], ["core", "software"], "CC0" + ) assert creation_information.spec_version == Version("3.0.0") assert creation_information.created == datetime(2023, 1, 11, 16, 21) @@ -32,19 +33,21 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: CreationInformation("2.3", "2012-01-01", [], [], "core", 3) - assert err.value.args[0] == ['SetterError CreationInformation: type of argument "spec_version" must be ' - 'semantic_version.base.Version; got str instead: 2.3', - 'SetterError CreationInformation: type of argument "created" must be ' - 'datetime.datetime; got str instead: 2012-01-01', - 'SetterError CreationInformation: type of argument "profile" must be a list; ' - 'got str instead: core', - 'SetterError CreationInformation: type of argument "data_license" must be ' - 'str; got int instead: 3'] + assert err.value.args[0] == [ + 'SetterError CreationInformation: type of argument "spec_version" must be ' + "semantic_version.base.Version; got str instead: 2.3", + 'SetterError CreationInformation: type of argument "created" must be ' + "datetime.datetime; got str instead: 2012-01-01", + 'SetterError CreationInformation: type of argument "profile" must be a list; ' "got str instead: core", + 'SetterError CreationInformation: type of argument "data_license" must be ' "str; got int instead: 3", + ] def test_incomplete_initialization(): with pytest.raises(TypeError) as err: CreationInformation("2.3") - assert "__init__() missing 4 required positional arguments: 'created', 'created_by', 'created_using', and 'profile'" in \ - err.value.args[0] + assert ( + "__init__() missing 4 required positional arguments: 'created', 'created_by', 'created_using', and 'profile'" + in err.value.args[0] + ) diff --git a/tests/spdx3/model/test_external_identifier.py b/tests/spdx3/model/test_external_identifier.py index ff85e2c8d..8e29f2d50 100644 --- a/tests/spdx3/model/test_external_identifier.py +++ b/tests/spdx3/model/test_external_identifier.py @@ -14,8 +14,9 @@ def test_correct_initialization(): - external_identifier = ExternalIdentifier(ExternalIdentifierType.CPE22, "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", - "This is a comment") + external_identifier = ExternalIdentifier( + ExternalIdentifierType.CPE22, "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", "This is a comment" + ) assert external_identifier.external_identifier_type == ExternalIdentifierType.CPE22 assert external_identifier.identifier == "cpe:/o:canonical:ubuntu_linux:10.04:-:lts" assert external_identifier.comment == "This is a comment" @@ -25,10 +26,12 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: ExternalIdentifier("CPE22", ["identifier", "another_identifier"], 34) - assert err.value.args[0] == ['SetterError ExternalIdentifier: type of argument "external_identifier_type" ' - 'must be spdx3.model.external_identifier.ExternalIdentifierType; got str ' - 'instead: CPE22', - 'SetterError ExternalIdentifier: type of argument "identifier" must be str; ' - "got list instead: ['identifier', 'another_identifier']", - 'SetterError ExternalIdentifier: type of argument "comment" must be one of ' - '(str, NoneType); got int instead: 34'] + assert err.value.args[0] == [ + 'SetterError ExternalIdentifier: type of argument "external_identifier_type" ' + "must be spdx3.model.external_identifier.ExternalIdentifierType; got str " + "instead: CPE22", + 'SetterError ExternalIdentifier: type of argument "identifier" must be str; ' + "got list instead: ['identifier', 'another_identifier']", + 'SetterError ExternalIdentifier: type of argument "comment" must be one of ' + "(str, NoneType); got int instead: 34", + ] diff --git a/tests/spdx3/model/test_external_map.py b/tests/spdx3/model/test_external_map.py index 34ef6be66..81cfb1fe3 100644 --- a/tests/spdx3/model/test_external_map.py +++ b/tests/spdx3/model/test_external_map.py @@ -9,10 +9,12 @@ # See the License for the specific language governing permissions and # limitations under the License. from unittest import mock + import pytest from spdx3.model.external_map import ExternalMap + @mock.patch("spdx3.model.integrity_method.IntegrityMethod", autospec=True) def test_correct_initialization(integrity_method): external_map = ExternalMap("https://external.id", [integrity_method], "https://location.hint") @@ -26,7 +28,8 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: ExternalMap(234, None, ["location hints"]) - assert err.value.args[0] == ['SetterError ExternalMap: type of argument "external_id" must be str; got int ' - 'instead: 234', - 'SetterError ExternalMap: type of argument "location_hint" must be one of ' - "(str, NoneType); got list instead: ['location hints']"] + assert err.value.args[0] == [ + 'SetterError ExternalMap: type of argument "external_id" must be str; got int ' "instead: 234", + 'SetterError ExternalMap: type of argument "location_hint" must be one of ' + "(str, NoneType); got list instead: ['location hints']", + ] diff --git a/tests/spdx3/model/test_external_reference.py b/tests/spdx3/model/test_external_reference.py index 1ab731ca9..adb33a0ce 100644 --- a/tests/spdx3/model/test_external_reference.py +++ b/tests/spdx3/model/test_external_reference.py @@ -14,8 +14,9 @@ def test_correct_initialization(): - external_reference = ExternalReference(ExternalReferenceType.SECURITY_ADVISORY, ["https://anyURI"], "MediaType", - "This is a comment") + external_reference = ExternalReference( + ExternalReferenceType.SECURITY_ADVISORY, ["https://anyURI"], "MediaType", "This is a comment" + ) assert external_reference.external_reference_type == ExternalReferenceType.SECURITY_ADVISORY assert external_reference.locator == ["https://anyURI"] assert external_reference.content_type == "MediaType" @@ -26,12 +27,13 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: ExternalReference("OTHER", "a URI", 34, True) - assert err.value.args[0] == ['SetterError ExternalReference: type of argument "external_reference_type" ' - 'must be one of (spdx3.model.external_reference.ExternalReferenceType, ' - 'NoneType); got str instead: OTHER', - 'SetterError ExternalReference: type of argument "locator" must be a list; ' - 'got str instead: a URI', - 'SetterError ExternalReference: type of argument "content_type" must be one ' - 'of (str, NoneType); got int instead: 34', - 'SetterError ExternalReference: type of argument "comment" must be one of ' - '(str, NoneType); got bool instead: True'] + assert err.value.args[0] == [ + 'SetterError ExternalReference: type of argument "external_reference_type" ' + "must be one of (spdx3.model.external_reference.ExternalReferenceType, " + "NoneType); got str instead: OTHER", + 'SetterError ExternalReference: type of argument "locator" must be a list; ' "got str instead: a URI", + 'SetterError ExternalReference: type of argument "content_type" must be one ' + "of (str, NoneType); got int instead: 34", + 'SetterError ExternalReference: type of argument "comment" must be one of ' + "(str, NoneType); got bool instead: True", + ] diff --git a/tests/spdx3/model/test_hash.py b/tests/spdx3/model/test_hash.py index 6fcce2fe2..644f9fdf9 100644 --- a/tests/spdx3/model/test_hash.py +++ b/tests/spdx3/model/test_hash.py @@ -24,7 +24,8 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: Hash("SHA1", 345) - assert err.value.args[0] == ['SetterError Hash: type of argument "algorithm" must be ' - 'spdx3.model.hash.HashAlgorithm; got str instead: SHA1', - 'SetterError Hash: type of argument "hash_value" must be str; got int ' - 'instead: 345'] + assert err.value.args[0] == [ + 'SetterError Hash: type of argument "algorithm" must be ' + "spdx3.model.hash.HashAlgorithm; got str instead: SHA1", + 'SetterError Hash: type of argument "hash_value" must be str; got int ' "instead: 345", + ] diff --git a/tests/spdx3/model/test_namespace_map.py b/tests/spdx3/model/test_namespace_map.py index e856be009..48cb99981 100644 --- a/tests/spdx3/model/test_namespace_map.py +++ b/tests/spdx3/model/test_namespace_map.py @@ -24,7 +24,8 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: NamespaceMap(34, ["list of namespaces"]) - assert err.value.args[0] == ['SetterError NamespaceMap: type of argument "prefix" must be one of (str, ' - 'NoneType); got int instead: 34', - 'SetterError NamespaceMap: type of argument "namespace" must be one of (str, ' - "NoneType); got list instead: ['list of namespaces']"] + assert err.value.args[0] == [ + 'SetterError NamespaceMap: type of argument "prefix" must be one of (str, ' "NoneType); got int instead: 34", + 'SetterError NamespaceMap: type of argument "namespace" must be one of (str, ' + "NoneType); got list instead: ['list of namespaces']", + ] diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py index 5eed1bd3e..1dc110026 100644 --- a/tests/spdx3/model/test_relationship.py +++ b/tests/spdx3/model/test_relationship.py @@ -12,13 +12,19 @@ import pytest -from spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness +from spdx3.model.relationship import Relationship, RelationshipCompleteness, RelationshipType @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): - relationship = Relationship("SPDXRef-Relationship", creation_information, "spdx_id1", ["spdx_id2", "spdx_id3"], - RelationshipType.DESCRIBES, completeness=RelationshipCompleteness.UNKNOWN) + relationship = Relationship( + "SPDXRef-Relationship", + creation_information, + "spdx_id1", + ["spdx_id2", "spdx_id3"], + RelationshipType.DESCRIBES, + completeness=RelationshipCompleteness.UNKNOWN, + ) assert relationship.spdx_id == "SPDXRef-Relationship" assert relationship.creation_info == creation_information @@ -33,12 +39,12 @@ def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Relationship("SPDXRef-Relationship", creation_information, 42, 5, "Relationshiptype", completeness=True) - assert err.value.args[0] == ['SetterError Relationship: type of argument "from_element" must be ' - 'str; got int instead: 42', - 'SetterError Relationship: type of argument "to" must be a list; got int ' - 'instead: 5', - 'SetterError Relationship: type of argument "relationship_type" must be ' - 'spdx3.model.relationship.RelationshipType; got str instead: Relationshiptype', - 'SetterError Relationship: type of argument "completeness" must be one of ' - '(spdx3.model.relationship.RelationshipCompleteness, NoneType); got bool ' - 'instead: True'] + assert err.value.args[0] == [ + 'SetterError Relationship: type of argument "from_element" must be ' "str; got int instead: 42", + 'SetterError Relationship: type of argument "to" must be a list; got int ' "instead: 5", + 'SetterError Relationship: type of argument "relationship_type" must be ' + "spdx3.model.relationship.RelationshipType; got str instead: Relationshiptype", + 'SetterError Relationship: type of argument "completeness" must be one of ' + "(spdx3.model.relationship.RelationshipCompleteness, NoneType); got bool " + "instead: True", + ] diff --git a/tests/spdx3/model/test_spdx_document.py b/tests/spdx3/model/test_spdx_document.py index f4d260bf0..98f44a113 100644 --- a/tests/spdx3/model/test_spdx_document.py +++ b/tests/spdx3/model/test_spdx_document.py @@ -17,8 +17,9 @@ @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): - spdx_document = SpdxDocument("SPDXRef-DOCUMENT", creation_information, "Test document", elements=["spdx_id1"], - root_elements=["spdx_id2"]) + spdx_document = SpdxDocument( + "SPDXRef-DOCUMENT", creation_information, "Test document", elements=["spdx_id1"], root_elements=["spdx_id2"] + ) assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" assert spdx_document.creation_info == creation_information @@ -31,13 +32,13 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: SpdxDocument(1, {"info": 5}, "document name", elements=[8], root_elements=[]) - assert err.value.args[0] == ['SetterError SpdxDocument: type of argument "spdx_id" must be str; got int ' - 'instead: 1', - 'SetterError SpdxDocument: type of argument "creation_info" must be ' - 'spdx3.model.creation_information.CreationInformation; got dict instead: ' - "{'info': 5}", - 'SetterError SpdxDocument: type of argument "elements"[0] must be ' - 'str; got int instead: [8]'] + assert err.value.args[0] == [ + 'SetterError SpdxDocument: type of argument "spdx_id" must be str; got int ' "instead: 1", + 'SetterError SpdxDocument: type of argument "creation_info" must be ' + "spdx3.model.creation_information.CreationInformation; got dict instead: " + "{'info': 5}", + 'SetterError SpdxDocument: type of argument "elements"[0] must be ' "str; got int instead: [8]", + ] @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) @@ -45,5 +46,7 @@ def test_incomplete_initialization(creation_information): with pytest.raises(TypeError) as err: SpdxDocument("SPDXRef-Document", creation_information) - assert "__init__() missing 3 required positional arguments: 'name', 'elements', and 'root_elements'" in \ - err.value.args[0] + assert ( + "__init__() missing 3 required positional arguments: 'name', 'elements', and 'root_elements'" + in err.value.args[0] + ) diff --git a/tests/spdx3/model/test_tool.py b/tests/spdx3/model/test_tool.py index fbe1ef78c..baa011c43 100644 --- a/tests/spdx3/model/test_tool.py +++ b/tests/spdx3/model/test_tool.py @@ -18,18 +18,23 @@ def test_correct_initialization(): - agent = Tool("SPDXRef-Tool", - CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0")) + agent = Tool( + "SPDXRef-Tool", + CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0"), + ) assert agent.spdx_id == "SPDXRef-Tool" - assert agent.creation_info == CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], - ["core"], "CC0") + assert agent.creation_info == CreationInformation( + Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0" + ) def test_invalid_initialization(): with pytest.raises(TypeError) as err: Tool(12, 345) - assert err.value.args[0] == ['SetterError Tool: type of argument "spdx_id" must be str; got int instead: 12', - 'SetterError Tool: type of argument "creation_info" must be ' - 'spdx3.model.creation_information.CreationInformation; got int instead: 345'] + assert err.value.args[0] == [ + 'SetterError Tool: type of argument "spdx_id" must be str; got int instead: 12', + 'SetterError Tool: type of argument "creation_info" must be ' + "spdx3.model.creation_information.CreationInformation; got int instead: 345", + ] From 3bbceb7145469a93251037a2076b597cbbeb9e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 3 Apr 2023 11:12:41 +0200 Subject: [PATCH 169/354] [SPDX-3.0] change license header to use SPDX license identifier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/actor.py | 13 +++---------- src/spdx3/bump_from_spdx2/annotation.py | 13 +++---------- src/spdx3/bump_from_spdx2/bump_utils.py | 13 +++---------- src/spdx3/bump_from_spdx2/checksum.py | 13 +++---------- src/spdx3/bump_from_spdx2/creation_information.py | 13 +++---------- src/spdx3/bump_from_spdx2/external_document_ref.py | 13 +++---------- src/spdx3/bump_from_spdx2/file.py | 13 +++---------- src/spdx3/bump_from_spdx2/message.py | 13 +++---------- src/spdx3/bump_from_spdx2/package.py | 13 +++---------- src/spdx3/bump_from_spdx2/relationship.py | 13 +++---------- src/spdx3/bump_from_spdx2/snippet.py | 13 +++---------- src/spdx3/bump_from_spdx2/spdx_document.py | 13 +++---------- src/spdx3/clitools/pyspdxtools3.py | 13 +++---------- src/spdx3/model/agent.py | 13 +++---------- src/spdx3/model/annotation.py | 13 +++---------- src/spdx3/model/artifact.py | 13 +++---------- src/spdx3/model/bom.py | 13 +++---------- src/spdx3/model/bundle.py | 13 +++---------- src/spdx3/model/creation_information.py | 13 +++---------- src/spdx3/model/element.py | 13 +++---------- src/spdx3/model/external_identifier.py | 13 +++---------- src/spdx3/model/external_map.py | 13 +++---------- src/spdx3/model/external_reference.py | 13 +++---------- src/spdx3/model/hash.py | 13 +++---------- src/spdx3/model/integrity_method.py | 13 +++---------- src/spdx3/model/namespace_map.py | 13 +++---------- src/spdx3/model/organization.py | 13 +++---------- src/spdx3/model/person.py | 13 +++---------- src/spdx3/model/profile_identifier.py | 13 +++---------- src/spdx3/model/relationship.py | 13 +++---------- src/spdx3/model/software/file.py | 13 +++---------- src/spdx3/model/software/package.py | 13 +++---------- src/spdx3/model/software/sbom.py | 13 +++---------- src/spdx3/model/software/snippet.py | 13 +++---------- src/spdx3/model/software/software_purpose.py | 13 +++---------- src/spdx3/model/software_agent.py | 13 +++---------- src/spdx3/model/spdx_collection.py | 13 +++---------- src/spdx3/model/spdx_document.py | 13 +++---------- src/spdx3/model/tool.py | 13 +++---------- src/spdx3/payload.py | 13 +++---------- src/spdx3/writer/console/agent_writer.py | 13 +++---------- src/spdx3/writer/console/annotation_writer.py | 13 +++---------- src/spdx3/writer/console/artifact_writer.py | 13 +++---------- src/spdx3/writer/console/bom_writer.py | 13 +++---------- src/spdx3/writer/console/bundle_writer.py | 13 +++---------- src/spdx3/writer/console/console.py | 13 +++---------- .../writer/console/creation_information_writer.py | 13 +++---------- src/spdx3/writer/console/element_writer.py | 13 +++---------- .../writer/console/external_identifier_writer.py | 13 +++---------- src/spdx3/writer/console/external_map_writer.py | 13 +++---------- .../writer/console/external_reference_writer.py | 13 +++---------- src/spdx3/writer/console/hash_writer.py | 13 +++---------- src/spdx3/writer/console/integrity_method_writer.py | 13 +++---------- src/spdx3/writer/console/namespace_map_writer.py | 13 +++---------- src/spdx3/writer/console/payload_writer.py | 13 +++---------- src/spdx3/writer/console/relationship_writer.py | 13 +++---------- src/spdx3/writer/console/software/file_writer.py | 13 +++---------- src/spdx3/writer/console/software/package_writer.py | 13 +++---------- src/spdx3/writer/console/software/sbom_writer.py | 13 +++---------- src/spdx3/writer/console/software/snippet_writer.py | 13 +++---------- src/spdx3/writer/console/spdx_collection_writer.py | 13 +++---------- src/spdx3/writer/console/spdx_document_writer.py | 13 +++---------- tests/spdx3/bump/test_actor_bump.py | 13 +++---------- tests/spdx3/bump/test_bump_utils.py | 13 +++---------- tests/spdx3/bump/test_checksum_bump.py | 13 +++---------- tests/spdx3/bump/test_file_bump.py | 13 +++---------- tests/spdx3/bump/test_package_bump.py | 13 +++---------- tests/spdx3/bump/test_snippet_bump.py | 13 +++---------- tests/spdx3/bump/test_spdx_document_bump.py | 13 +++---------- tests/spdx3/model/software/test_file.py | 13 +++---------- tests/spdx3/model/software/test_package.py | 13 +++---------- tests/spdx3/model/software/test_sbom.py | 13 +++---------- tests/spdx3/model/software/test_snippet.py | 13 +++---------- tests/spdx3/model/test_abstract_classes.py | 13 +++---------- tests/spdx3/model/test_agent.py | 13 +++---------- tests/spdx3/model/test_annotation.py | 13 +++---------- tests/spdx3/model/test_bom.py | 13 +++---------- tests/spdx3/model/test_bundle.py | 13 +++---------- tests/spdx3/model/test_creation_information.py | 13 +++---------- tests/spdx3/model/test_external_identifier.py | 13 +++---------- tests/spdx3/model/test_external_map.py | 13 +++---------- tests/spdx3/model/test_external_reference.py | 13 +++---------- tests/spdx3/model/test_hash.py | 13 +++---------- tests/spdx3/model/test_namespace_map.py | 13 +++---------- tests/spdx3/model/test_relationship.py | 13 +++---------- tests/spdx3/model/test_spdx_document.py | 13 +++---------- tests/spdx3/model/test_tool.py | 13 +++---------- 87 files changed, 261 insertions(+), 870 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/actor.py b/src/spdx3/bump_from_spdx2/actor.py index 7e1a72062..385051d05 100644 --- a/src/spdx3/bump_from_spdx2/actor.py +++ b/src/spdx3/bump_from_spdx2/actor.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List from spdx3.model.creation_information import CreationInformation diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py index 61c1fdabc..f215d5084 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from copy import deepcopy from spdx3.bump_from_spdx2.actor import bump_actor diff --git a/src/spdx3/bump_from_spdx2/bump_utils.py b/src/spdx3/bump_from_spdx2/bump_utils.py index 103789c90..f3f8db270 100644 --- a/src/spdx3/bump_from_spdx2/bump_utils.py +++ b/src/spdx3/bump_from_spdx2/bump_utils.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Optional, Union from spdx.model.spdx_no_assertion import SpdxNoAssertion diff --git a/src/spdx3/bump_from_spdx2/checksum.py b/src/spdx3/bump_from_spdx2/checksum.py index 6bbbc208a..d62f41020 100644 --- a/src/spdx3/bump_from_spdx2/checksum.py +++ b/src/spdx3/bump_from_spdx2/checksum.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from spdx3.model.hash import Hash, HashAlgorithm from spdx.model.checksum import Checksum as Spdx2_Checksum from spdx.model.checksum import ChecksumAlgorithm diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index fe79cf778..a6a05eb90 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import List diff --git a/src/spdx3/bump_from_spdx2/external_document_ref.py b/src/spdx3/bump_from_spdx2/external_document_ref.py index cf211b4d2..ced98ce49 100644 --- a/src/spdx3/bump_from_spdx2/external_document_ref.py +++ b/src/spdx3/bump_from_spdx2/external_document_ref.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List from spdx3.bump_from_spdx2.checksum import bump_checksum diff --git a/src/spdx3/bump_from_spdx2/file.py b/src/spdx3/bump_from_spdx2/file.py index 0a70eccd5..145657ba5 100644 --- a/src/spdx3/bump_from_spdx2/file.py +++ b/src/spdx3/bump_from_spdx2/file.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from spdx3.bump_from_spdx2.checksum import bump_checksum from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.creation_information import CreationInformation diff --git a/src/spdx3/bump_from_spdx2/message.py b/src/spdx3/bump_from_spdx2/message.py index 4551742f3..f86d3c052 100644 --- a/src/spdx3/bump_from_spdx2/message.py +++ b/src/spdx3/bump_from_spdx2/message.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import sys diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index 2c22a237e..5801a88b6 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from spdx3.bump_from_spdx2.actor import bump_actor from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none from spdx3.bump_from_spdx2.checksum import bump_checksum diff --git a/src/spdx3/bump_from_spdx2/relationship.py b/src/spdx3/bump_from_spdx2/relationship.py index daa1db148..5bc3d275c 100644 --- a/src/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx3/bump_from_spdx2/relationship.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Optional, Tuple from spdx3.model.creation_information import CreationInformation diff --git a/src/spdx3/bump_from_spdx2/snippet.py b/src/spdx3/bump_from_spdx2/snippet.py index 574bf0288..2c2657137 100644 --- a/src/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx3/bump_from_spdx2/snippet.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.creation_information import CreationInformation from spdx3.model.software.snippet import Snippet diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx3/bump_from_spdx2/spdx_document.py index 67407e33c..874985125 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from spdx3.bump_from_spdx2.annotation import bump_annotation from spdx3.bump_from_spdx2.creation_information import bump_creation_information from spdx3.bump_from_spdx2.file import bump_file diff --git a/src/spdx3/clitools/pyspdxtools3.py b/src/spdx3/clitools/pyspdxtools3.py index 5c612bda6..58e4878ca 100644 --- a/src/spdx3/clitools/pyspdxtools3.py +++ b/src/spdx3/clitools/pyspdxtools3.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import sys from typing import List diff --git a/src/spdx3/model/agent.py b/src/spdx3/model/agent.py index b1019d821..91bd0d515 100644 --- a/src/spdx3/model/agent.py +++ b/src/spdx3/model/agent.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/model/annotation.py b/src/spdx3/model/annotation.py index 75784bad4..6018a0495 100644 --- a/src/spdx3/model/annotation.py +++ b/src/spdx3/model/annotation.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import List, Optional diff --git a/src/spdx3/model/artifact.py b/src/spdx3/model/artifact.py index 2cc3c548d..439881c72 100644 --- a/src/spdx3/model/artifact.py +++ b/src/spdx3/model/artifact.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod from typing import Optional diff --git a/src/spdx3/model/bom.py b/src/spdx3/model/bom.py index fc62da46c..72bcd3b10 100644 --- a/src/spdx3/model/bom.py +++ b/src/spdx3/model/bom.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/model/bundle.py b/src/spdx3/model/bundle.py index d6928ba76..1617572e4 100644 --- a/src/spdx3/model/bundle.py +++ b/src/spdx3/model/bundle.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/model/creation_information.py b/src/spdx3/model/creation_information.py index 19dced748..a60e65b2e 100644 --- a/src/spdx3/model/creation_information.py +++ b/src/spdx3/model/creation_information.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import List diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index ca57390ef..fbeb58090 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from abc import ABC, abstractmethod from dataclasses import field from typing import List, Optional diff --git a/src/spdx3/model/external_identifier.py b/src/spdx3/model/external_identifier.py index a65959c94..ba646532b 100644 --- a/src/spdx3/model/external_identifier.py +++ b/src/spdx3/model/external_identifier.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import Optional diff --git a/src/spdx3/model/external_map.py b/src/spdx3/model/external_map.py index 1cdbf21f6..03ba7c82d 100644 --- a/src/spdx3/model/external_map.py +++ b/src/spdx3/model/external_map.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from dataclasses import field from typing import List, Optional diff --git a/src/spdx3/model/external_reference.py b/src/spdx3/model/external_reference.py index 44009f875..16630f300 100644 --- a/src/spdx3/model/external_reference.py +++ b/src/spdx3/model/external_reference.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from dataclasses import field from enum import Enum, auto from typing import List, Optional diff --git a/src/spdx3/model/hash.py b/src/spdx3/model/hash.py index 0198f675f..493b287f2 100644 --- a/src/spdx3/model/hash.py +++ b/src/spdx3/model/hash.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import Optional diff --git a/src/spdx3/model/integrity_method.py b/src/spdx3/model/integrity_method.py index eb52eb623..aead03548 100644 --- a/src/spdx3/model/integrity_method.py +++ b/src/spdx3/model/integrity_method.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from abc import ABC, abstractmethod from typing import Optional diff --git a/src/spdx3/model/namespace_map.py b/src/spdx3/model/namespace_map.py index 498a3de83..2945cb924 100644 --- a/src/spdx3/model/namespace_map.py +++ b/src/spdx3/model/namespace_map.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Optional from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/model/organization.py b/src/spdx3/model/organization.py index bce54b55b..15d48d267 100644 --- a/src/spdx3/model/organization.py +++ b/src/spdx3/model/organization.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/model/person.py b/src/spdx3/model/person.py index 6b7c004b8..365dc0432 100644 --- a/src/spdx3/model/person.py +++ b/src/spdx3/model/person.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/model/profile_identifier.py b/src/spdx3/model/profile_identifier.py index 69e7c12e8..21a6e443a 100644 --- a/src/spdx3/model/profile_identifier.py +++ b/src/spdx3/model/profile_identifier.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto diff --git a/src/spdx3/model/relationship.py b/src/spdx3/model/relationship.py index 85c58f33a..55ab38290 100644 --- a/src/spdx3/model/relationship.py +++ b/src/spdx3/model/relationship.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import List, Optional diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index 0cd9e85b9..227e80998 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index d8bfb1f7e..e59376cd3 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index f96af8e59..334e5a74b 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index e8dc8cc33..af133e7e9 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional, Tuple from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/model/software/software_purpose.py b/src/spdx3/model/software/software_purpose.py index 53ef9f77b..b2674ca6d 100644 --- a/src/spdx3/model/software/software_purpose.py +++ b/src/spdx3/model/software/software_purpose.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto diff --git a/src/spdx3/model/software_agent.py b/src/spdx3/model/software_agent.py index b9b6a0cca..17be0a83d 100644 --- a/src/spdx3/model/software_agent.py +++ b/src/spdx3/model/software_agent.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/model/spdx_collection.py b/src/spdx3/model/spdx_collection.py index 7ad0f2c6a..a33298a16 100644 --- a/src/spdx3/model/spdx_collection.py +++ b/src/spdx3/model/spdx_collection.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod from dataclasses import field from typing import List, Optional diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index efec50e4a..550f9908e 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/model/tool.py b/src/spdx3/model/tool.py index 40fcb9e03..7022ce319 100644 --- a/src/spdx3/model/tool.py +++ b/src/spdx3/model/tool.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import List, Optional from common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx3/payload.py b/src/spdx3/payload.py index a9dc970aa..3ba8fc542 100644 --- a/src/spdx3/payload.py +++ b/src/spdx3/payload.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Dict from spdx3.model.element import Element diff --git a/src/spdx3/writer/console/agent_writer.py b/src/spdx3/writer/console/agent_writer.py index b8fd1c09e..c170eecc4 100644 --- a/src/spdx3/writer/console/agent_writer.py +++ b/src/spdx3/writer/console/agent_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.agent import Agent diff --git a/src/spdx3/writer/console/annotation_writer.py b/src/spdx3/writer/console/annotation_writer.py index ab5cb3acb..c707479ff 100644 --- a/src/spdx3/writer/console/annotation_writer.py +++ b/src/spdx3/writer/console/annotation_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.annotation import Annotation diff --git a/src/spdx3/writer/console/artifact_writer.py b/src/spdx3/writer/console/artifact_writer.py index 079365c21..8752b0ff1 100644 --- a/src/spdx3/writer/console/artifact_writer.py +++ b/src/spdx3/writer/console/artifact_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.artifact import Artifact diff --git a/src/spdx3/writer/console/bom_writer.py b/src/spdx3/writer/console/bom_writer.py index 4da6dcfbf..9db1f8087 100644 --- a/src/spdx3/writer/console/bom_writer.py +++ b/src/spdx3/writer/console/bom_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.bom import Bom diff --git a/src/spdx3/writer/console/bundle_writer.py b/src/spdx3/writer/console/bundle_writer.py index 35a7faf59..7c069dcf6 100644 --- a/src/spdx3/writer/console/bundle_writer.py +++ b/src/spdx3/writer/console/bundle_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.bundle import Bundle diff --git a/src/spdx3/writer/console/console.py b/src/spdx3/writer/console/console.py index d2cc07ae7..43cc97f3c 100644 --- a/src/spdx3/writer/console/console.py +++ b/src/spdx3/writer/console/console.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import Optional, TextIO, Union diff --git a/src/spdx3/writer/console/creation_information_writer.py b/src/spdx3/writer/console/creation_information_writer.py index 13078ee59..34ce1b787 100644 --- a/src/spdx3/writer/console/creation_information_writer.py +++ b/src/spdx3/writer/console/creation_information_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.creation_information import CreationInformation diff --git a/src/spdx3/writer/console/element_writer.py b/src/spdx3/writer/console/element_writer.py index b55fc70f4..55c6333d4 100644 --- a/src/spdx3/writer/console/element_writer.py +++ b/src/spdx3/writer/console/element_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.element import Element diff --git a/src/spdx3/writer/console/external_identifier_writer.py b/src/spdx3/writer/console/external_identifier_writer.py index 9ef665fcb..976bab680 100644 --- a/src/spdx3/writer/console/external_identifier_writer.py +++ b/src/spdx3/writer/console/external_identifier_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.external_identifier import ExternalIdentifier diff --git a/src/spdx3/writer/console/external_map_writer.py b/src/spdx3/writer/console/external_map_writer.py index 119fcc3c9..13fc4b5a1 100644 --- a/src/spdx3/writer/console/external_map_writer.py +++ b/src/spdx3/writer/console/external_map_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.external_map import ExternalMap diff --git a/src/spdx3/writer/console/external_reference_writer.py b/src/spdx3/writer/console/external_reference_writer.py index 9bd853c8d..a17725a9b 100644 --- a/src/spdx3/writer/console/external_reference_writer.py +++ b/src/spdx3/writer/console/external_reference_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.external_reference import ExternalReference diff --git a/src/spdx3/writer/console/hash_writer.py b/src/spdx3/writer/console/hash_writer.py index ff3969311..e6df18a91 100644 --- a/src/spdx3/writer/console/hash_writer.py +++ b/src/spdx3/writer/console/hash_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.hash import Hash diff --git a/src/spdx3/writer/console/integrity_method_writer.py b/src/spdx3/writer/console/integrity_method_writer.py index 566ddda46..966494236 100644 --- a/src/spdx3/writer/console/integrity_method_writer.py +++ b/src/spdx3/writer/console/integrity_method_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.integrity_method import IntegrityMethod diff --git a/src/spdx3/writer/console/namespace_map_writer.py b/src/spdx3/writer/console/namespace_map_writer.py index 048390008..14729cdec 100644 --- a/src/spdx3/writer/console/namespace_map_writer.py +++ b/src/spdx3/writer/console/namespace_map_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.namespace_map import NamespaceMap diff --git a/src/spdx3/writer/console/payload_writer.py b/src/spdx3/writer/console/payload_writer.py index a7786972d..a98bf2751 100644 --- a/src/spdx3/writer/console/payload_writer.py +++ b/src/spdx3/writer/console/payload_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.annotation import Annotation diff --git a/src/spdx3/writer/console/relationship_writer.py b/src/spdx3/writer/console/relationship_writer.py index 8dc76997c..bd82b4208 100644 --- a/src/spdx3/writer/console/relationship_writer.py +++ b/src/spdx3/writer/console/relationship_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.relationship import Relationship diff --git a/src/spdx3/writer/console/software/file_writer.py b/src/spdx3/writer/console/software/file_writer.py index b339edfa8..c29b0ba9e 100644 --- a/src/spdx3/writer/console/software/file_writer.py +++ b/src/spdx3/writer/console/software/file_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.software.file import File diff --git a/src/spdx3/writer/console/software/package_writer.py b/src/spdx3/writer/console/software/package_writer.py index c8606be30..3a7bb748a 100644 --- a/src/spdx3/writer/console/software/package_writer.py +++ b/src/spdx3/writer/console/software/package_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.software.package import Package diff --git a/src/spdx3/writer/console/software/sbom_writer.py b/src/spdx3/writer/console/software/sbom_writer.py index 56e3ee153..6f54afa5f 100644 --- a/src/spdx3/writer/console/software/sbom_writer.py +++ b/src/spdx3/writer/console/software/sbom_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.software.sbom import Sbom diff --git a/src/spdx3/writer/console/software/snippet_writer.py b/src/spdx3/writer/console/software/snippet_writer.py index cfb077de4..9a86128f9 100644 --- a/src/spdx3/writer/console/software/snippet_writer.py +++ b/src/spdx3/writer/console/software/snippet_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.software.snippet import Snippet diff --git a/src/spdx3/writer/console/spdx_collection_writer.py b/src/spdx3/writer/console/spdx_collection_writer.py index 009e16dd8..af2fb39f0 100644 --- a/src/spdx3/writer/console/spdx_collection_writer.py +++ b/src/spdx3/writer/console/spdx_collection_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.spdx_collection import SpdxCollection diff --git a/src/spdx3/writer/console/spdx_document_writer.py b/src/spdx3/writer/console/spdx_document_writer.py index 0848bb62b..8631122a9 100644 --- a/src/spdx3/writer/console/spdx_document_writer.py +++ b/src/spdx3/writer/console/spdx_document_writer.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from typing import TextIO from spdx3.model.spdx_document import SpdxDocument diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index 0b9dc2387..5a7a862dc 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime import pytest diff --git a/tests/spdx3/bump/test_bump_utils.py b/tests/spdx3/bump/test_bump_utils.py index 0251e2a15..6c33970bf 100644 --- a/tests/spdx3/bump/test_bump_utils.py +++ b/tests/spdx3/bump/test_bump_utils.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2022 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none diff --git a/tests/spdx3/bump/test_checksum_bump.py b/tests/spdx3/bump/test_checksum_bump.py index 35a2291a7..09f4943eb 100644 --- a/tests/spdx3/bump/test_checksum_bump.py +++ b/tests/spdx3/bump/test_checksum_bump.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx3.bump_from_spdx2.checksum import bump_checksum, convert_checksum_algorithm_to_hash_algorithm diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index 9c5e71a25..cd9007095 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock from spdx3.bump_from_spdx2.file import bump_file diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index cfe8c1014..445ceb421 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock from spdx3.bump_from_spdx2.package import bump_package diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index ef9d61d88..f4c22e706 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock from spdx3.bump_from_spdx2.snippet import bump_snippet diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index ab2f463cf..f1a78ec83 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import sys from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index 3de745e33..69b791ad8 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock import pytest diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 0b4f034d9..1d2f42956 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock import pytest diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index ee8f99690..f49736281 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock import pytest diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index 143ca6dc1..b13ef110f 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock import pytest diff --git a/tests/spdx3/model/test_abstract_classes.py b/tests/spdx3/model/test_abstract_classes.py index fcdd4027b..be1b705da 100644 --- a/tests/spdx3/model/test_abstract_classes.py +++ b/tests/spdx3/model/test_abstract_classes.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx3.model.artifact import Artifact diff --git a/tests/spdx3/model/test_agent.py b/tests/spdx3/model/test_agent.py index f1e6cdb1c..070e03272 100644 --- a/tests/spdx3/model/test_agent.py +++ b/tests/spdx3/model/test_agent.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime import pytest diff --git a/tests/spdx3/model/test_annotation.py b/tests/spdx3/model/test_annotation.py index 4da76571a..d3622d2eb 100644 --- a/tests/spdx3/model/test_annotation.py +++ b/tests/spdx3/model/test_annotation.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock import pytest diff --git a/tests/spdx3/model/test_bom.py b/tests/spdx3/model/test_bom.py index 168ba5dd4..0c66b2a01 100644 --- a/tests/spdx3/model/test_bom.py +++ b/tests/spdx3/model/test_bom.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/model/test_bundle.py b/tests/spdx3/model/test_bundle.py index 541dc15b6..340600b70 100644 --- a/tests/spdx3/model/test_bundle.py +++ b/tests/spdx3/model/test_bundle.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock import pytest diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py index f64ad2f9a..01cc8229d 100644 --- a/tests/spdx3/model/test_creation_information.py +++ b/tests/spdx3/model/test_creation_information.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime import pytest diff --git a/tests/spdx3/model/test_external_identifier.py b/tests/spdx3/model/test_external_identifier.py index 8e29f2d50..ddc314300 100644 --- a/tests/spdx3/model/test_external_identifier.py +++ b/tests/spdx3/model/test_external_identifier.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType diff --git a/tests/spdx3/model/test_external_map.py b/tests/spdx3/model/test_external_map.py index 81cfb1fe3..62a1325ad 100644 --- a/tests/spdx3/model/test_external_map.py +++ b/tests/spdx3/model/test_external_map.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock import pytest diff --git a/tests/spdx3/model/test_external_reference.py b/tests/spdx3/model/test_external_reference.py index adb33a0ce..338339acc 100644 --- a/tests/spdx3/model/test_external_reference.py +++ b/tests/spdx3/model/test_external_reference.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx3.model.external_reference import ExternalReference, ExternalReferenceType diff --git a/tests/spdx3/model/test_hash.py b/tests/spdx3/model/test_hash.py index 644f9fdf9..6fee7bd00 100644 --- a/tests/spdx3/model/test_hash.py +++ b/tests/spdx3/model/test_hash.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx3.model.hash import Hash, HashAlgorithm diff --git a/tests/spdx3/model/test_namespace_map.py b/tests/spdx3/model/test_namespace_map.py index 48cb99981..6bd1b707b 100644 --- a/tests/spdx3/model/test_namespace_map.py +++ b/tests/spdx3/model/test_namespace_map.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 import pytest from spdx3.model.namespace_map import NamespaceMap diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py index 1dc110026..0350c2c9c 100644 --- a/tests/spdx3/model/test_relationship.py +++ b/tests/spdx3/model/test_relationship.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock import pytest diff --git a/tests/spdx3/model/test_spdx_document.py b/tests/spdx3/model/test_spdx_document.py index 98f44a113..c10e6de52 100644 --- a/tests/spdx3/model/test_spdx_document.py +++ b/tests/spdx3/model/test_spdx_document.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from unittest import mock import pytest diff --git a/tests/spdx3/model/test_tool.py b/tests/spdx3/model/test_tool.py index baa011c43..5ff3617c5 100644 --- a/tests/spdx3/model/test_tool.py +++ b/tests/spdx3/model/test_tool.py @@ -1,13 +1,6 @@ -# Copyright (c) 2023 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors + +# SPDX-License-Identifier: Apache-2.0 from datetime import datetime import pytest From 3d0a93a5005cfce8eee92db1e005a7328d7875c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 3 Apr 2023 09:00:47 +0200 Subject: [PATCH 170/354] [spdx-3.0] add package_version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/README.md | 2 +- src/spdx3/bump_from_spdx2/package.py | 10 +++++----- src/spdx3/model/software/package.py | 2 ++ src/spdx3/writer/console/software/package_writer.py | 1 + tests/spdx3/bump/test_package_bump.py | 1 + tests/spdx3/model/software/test_package.py | 5 +++++ 6 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/spdx3/README.md b/src/spdx3/README.md index 0624152dd..01a227547 100644 --- a/src/spdx3/README.md +++ b/src/spdx3/README.md @@ -1 +1 @@ -This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: 7d45c8040b2fa1f67d77ea244666c991c47c6a9d). +This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: 01360996d37c1d913f3d15e2d5911ace182ed200). diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index 5801a88b6..b0c8c08a1 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -18,8 +18,7 @@ def bump_package( spdx_id = "#".join([document_namespace, spdx2_package.spdx_id]) name = spdx2_package.name download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") - # package2.version -> ? - print_missing_conversion("package2.version", 0) + package_version = spdx2_package.version # package.file_name -> ? print_missing_conversion("package2.file_name", 0) # package.supplier -> Relationship, suppliedBy? @@ -54,13 +53,14 @@ def bump_package( spdx_id, creation_information, name, - verified_using=integrity_methods, - download_location=download_location, - homepage=homepage, summary=summary, description=description, comment=comment, + verified_using=integrity_methods, originated_by=originated_by_spdx_id, package_purpose=package_purpose, + package_version=package_version, + download_location=download_location, + homepage=homepage, ) ) diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index e59376cd3..99e211f8c 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -17,6 +17,7 @@ class Package(Artifact): content_identifier: Optional[str] = None # anyURI package_purpose: Optional[List[SoftwarePurpose]] = None + package_version: Optional[str] = None download_location: Optional[str] = None # anyURI package_uri: Optional[str] = None # anyURI homepage: Optional[str] = None # anyURI @@ -36,6 +37,7 @@ def __init__( originated_by: Optional[str] = None, content_identifier: Optional[str] = None, package_purpose: Optional[List[SoftwarePurpose]] = None, + package_version: Optional[str] = None, download_location: Optional[str] = None, package_uri: Optional[str] = None, homepage: Optional[str] = None, diff --git a/src/spdx3/writer/console/software/package_writer.py b/src/spdx3/writer/console/software/package_writer.py index 3a7bb748a..189e527a4 100644 --- a/src/spdx3/writer/console/software/package_writer.py +++ b/src/spdx3/writer/console/software/package_writer.py @@ -13,6 +13,7 @@ def write_package(package: Package, text_output: TextIO): write_artifact_properties(package, text_output) write_value("content_identifier", package.content_identifier, text_output) write_value("package_purpose", ", ".join([purpose.name for purpose in package.package_purpose]), text_output) + write_value("package_version", package.package_version, text_output) write_value("download_location", package.download_location, text_output) write_value("package_uri", package.package_uri, text_output) write_value("homepage", package.homepage, text_output) diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 445ceb421..0fbeb69de 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -22,3 +22,4 @@ def test_bump_package(creation_information): assert isinstance(package, Package) assert package.spdx_id == expected_new_package_id + assert package.package_version == spdx2_package.version diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 1d2f42956..a3a017fef 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -16,6 +16,7 @@ def test_correct_initialization(creation_information): creation_information, content_identifier="https://any.uri", package_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH], + package_version="1:23a_bc", download_location="https://downloadlocation", package_uri="https://package.uri", homepage="https://homepage", @@ -25,6 +26,7 @@ def test_correct_initialization(creation_information): assert package.creation_info == creation_information assert package.content_identifier == "https://any.uri" assert package.package_purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH] + assert package.package_version == "1:23a_bc" assert package.download_location == "https://downloadlocation" assert package.package_uri == "https://package.uri" assert package.homepage == "https://homepage" @@ -38,6 +40,7 @@ def test_invalid_initialization(creation_information): creation_information, content_identifier=3, package_purpose=SoftwarePurpose.FILE, + package_version=42, download_location=4, package_uri=["uris"], homepage=True, @@ -50,6 +53,8 @@ def test_invalid_initialization(creation_information): "(List[spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got " "spdx3.model.software.software_purpose.SoftwarePurpose instead: " "SoftwarePurpose.FILE", + 'SetterError Package: type of argument "package_version" must be one of ' + "(str, NoneType); got int instead: 42", 'SetterError Package: type of argument "download_location" must be one of ' "(str, NoneType); got int instead: 4", 'SetterError Package: type of argument "package_uri" must be one of (str, ' From b74515addff3842a9eae94d8652ec17f5326dee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 3 Apr 2023 12:23:31 +0200 Subject: [PATCH 171/354] [SPDX-3.0] add creation_info comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/creation_information.py | 5 ++--- src/spdx3/model/creation_information.py | 4 +++- src/spdx3/writer/console/creation_information_writer.py | 1 + tests/spdx3/model/test_creation_information.py | 7 +++++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index a6a05eb90..7a85e9512 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -28,8 +28,7 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: print_missing_conversion("creation_info.document_namespace", 0) created: datetime = spdx2_creation_info.created - # creation_info.creator_comment -> ? - print_missing_conversion("creation_info.creator_comment", 0) + comment = spdx2_creation_info.document_comment data_license = spdx2_creation_info.data_license # creation_info.external_document_refs -> spdx_document.imports imports = [ @@ -41,7 +40,7 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: # creation_info.document_comment -> spdx_document.comment document_comment = spdx2_creation_info.document_comment creation_information = CreationInformation( - Version("3.0.0"), created, [], [], ["core", "software", "licensing"], data_license + Version("3.0.0"), created, [], [], ["core", "software", "licensing"], data_license, comment ) # due to creators having a creation_information themselves which inherits from the document's one, diff --git a/src/spdx3/model/creation_information.py b/src/spdx3/model/creation_information.py index a60e65b2e..113addc07 100644 --- a/src/spdx3/model/creation_information.py +++ b/src/spdx3/model/creation_information.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import List +from typing import List, Optional from semantic_version import Version @@ -18,6 +18,7 @@ class CreationInformation: created_using: List[str] # SPDXID of Tools profile: List[str] # or create an Enum for ProfileIdentifier? data_license: str + comment: Optional[str] = None def __init__( self, @@ -27,5 +28,6 @@ def __init__( created_using: List[str], profile: List[str], data_license: str = "CC0", + comment: Optional[str] = None, ): check_types_and_set_values(self, locals()) diff --git a/src/spdx3/writer/console/creation_information_writer.py b/src/spdx3/writer/console/creation_information_writer.py index 34ce1b787..480c4f18e 100644 --- a/src/spdx3/writer/console/creation_information_writer.py +++ b/src/spdx3/writer/console/creation_information_writer.py @@ -18,3 +18,4 @@ def write_creation_info(creation_info: CreationInformation, text_output: TextIO, write_value("created using", created_using, text_output, indent) write_value("profile", ", ".join(creation_info.profile), text_output, indent) write_value("data license", creation_info.data_license, text_output, indent) + write_value("comment", creation_info.comment, text_output, indent) diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py index 01cc8229d..5b997b7e1 100644 --- a/tests/spdx3/model/test_creation_information.py +++ b/tests/spdx3/model/test_creation_information.py @@ -11,7 +11,7 @@ def test_correct_initialization(): creation_information = CreationInformation( - Version("3.0.0"), datetime(2023, 1, 11, 16, 21), [], [], ["core", "software"], "CC0" + Version("3.0.0"), datetime(2023, 1, 11, 16, 21), [], [], ["core", "software"], "CC0", "some comment" ) assert creation_information.spec_version == Version("3.0.0") @@ -20,11 +20,12 @@ def test_correct_initialization(): assert creation_information.created_using == [] assert creation_information.profile == ["core", "software"] assert creation_information.data_license == "CC0" + assert creation_information.comment == "some comment" def test_invalid_initialization(): with pytest.raises(TypeError) as err: - CreationInformation("2.3", "2012-01-01", [], [], "core", 3) + CreationInformation("2.3", "2012-01-01", [], [], "core", 3, []) assert err.value.args[0] == [ 'SetterError CreationInformation: type of argument "spec_version" must be ' @@ -33,6 +34,8 @@ def test_invalid_initialization(): "datetime.datetime; got str instead: 2012-01-01", 'SetterError CreationInformation: type of argument "profile" must be a list; ' "got str instead: core", 'SetterError CreationInformation: type of argument "data_license" must be ' "str; got int instead: 3", + 'SetterError CreationInformation: type of argument "comment" must be' + " one of (str, NoneType); got list instead: []", ] From acd03b66555628a36bf55a38fc4b0c3714562132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 3 Apr 2023 13:48:32 +0200 Subject: [PATCH 172/354] fix license identifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/actor.py | 2 +- src/spdx3/bump_from_spdx2/annotation.py | 2 +- src/spdx3/bump_from_spdx2/bump_utils.py | 2 +- src/spdx3/bump_from_spdx2/checksum.py | 2 +- src/spdx3/bump_from_spdx2/creation_information.py | 2 +- src/spdx3/bump_from_spdx2/external_document_ref.py | 2 +- src/spdx3/bump_from_spdx2/file.py | 2 +- src/spdx3/bump_from_spdx2/message.py | 2 +- src/spdx3/bump_from_spdx2/package.py | 2 +- src/spdx3/bump_from_spdx2/relationship.py | 2 +- src/spdx3/bump_from_spdx2/snippet.py | 2 +- src/spdx3/bump_from_spdx2/spdx_document.py | 2 +- src/spdx3/clitools/pyspdxtools3.py | 2 +- src/spdx3/model/agent.py | 2 +- src/spdx3/model/annotation.py | 2 +- src/spdx3/model/artifact.py | 2 +- src/spdx3/model/bom.py | 2 +- src/spdx3/model/bundle.py | 2 +- src/spdx3/model/creation_information.py | 2 +- src/spdx3/model/element.py | 2 +- src/spdx3/model/external_identifier.py | 2 +- src/spdx3/model/external_map.py | 2 +- src/spdx3/model/external_reference.py | 2 +- src/spdx3/model/hash.py | 2 +- src/spdx3/model/integrity_method.py | 2 +- src/spdx3/model/namespace_map.py | 2 +- src/spdx3/model/organization.py | 2 +- src/spdx3/model/person.py | 2 +- src/spdx3/model/profile_identifier.py | 2 +- src/spdx3/model/relationship.py | 2 +- src/spdx3/model/software/file.py | 2 +- src/spdx3/model/software/package.py | 2 +- src/spdx3/model/software/sbom.py | 2 +- src/spdx3/model/software/snippet.py | 2 +- src/spdx3/model/software/software_purpose.py | 2 +- src/spdx3/model/software_agent.py | 2 +- src/spdx3/model/spdx_collection.py | 2 +- src/spdx3/model/spdx_document.py | 2 +- src/spdx3/model/tool.py | 2 +- src/spdx3/payload.py | 2 +- src/spdx3/writer/console/agent_writer.py | 2 +- src/spdx3/writer/console/annotation_writer.py | 2 +- src/spdx3/writer/console/artifact_writer.py | 2 +- src/spdx3/writer/console/bom_writer.py | 2 +- src/spdx3/writer/console/bundle_writer.py | 2 +- src/spdx3/writer/console/console.py | 2 +- src/spdx3/writer/console/creation_information_writer.py | 2 +- src/spdx3/writer/console/element_writer.py | 2 +- src/spdx3/writer/console/external_identifier_writer.py | 2 +- src/spdx3/writer/console/external_map_writer.py | 2 +- src/spdx3/writer/console/external_reference_writer.py | 2 +- src/spdx3/writer/console/hash_writer.py | 2 +- src/spdx3/writer/console/integrity_method_writer.py | 2 +- src/spdx3/writer/console/namespace_map_writer.py | 2 +- src/spdx3/writer/console/payload_writer.py | 2 +- src/spdx3/writer/console/relationship_writer.py | 2 +- src/spdx3/writer/console/software/file_writer.py | 2 +- src/spdx3/writer/console/software/package_writer.py | 2 +- src/spdx3/writer/console/software/sbom_writer.py | 2 +- src/spdx3/writer/console/software/snippet_writer.py | 2 +- src/spdx3/writer/console/spdx_collection_writer.py | 2 +- src/spdx3/writer/console/spdx_document_writer.py | 2 +- tests/spdx3/bump/test_actor_bump.py | 2 +- tests/spdx3/bump/test_checksum_bump.py | 2 +- tests/spdx3/bump/test_file_bump.py | 2 +- tests/spdx3/bump/test_package_bump.py | 2 +- tests/spdx3/bump/test_snippet_bump.py | 2 +- tests/spdx3/bump/test_spdx_document_bump.py | 2 +- tests/spdx3/model/software/test_file.py | 2 +- tests/spdx3/model/software/test_package.py | 2 +- tests/spdx3/model/software/test_sbom.py | 2 +- tests/spdx3/model/software/test_snippet.py | 2 +- tests/spdx3/model/test_abstract_classes.py | 2 +- tests/spdx3/model/test_agent.py | 2 +- tests/spdx3/model/test_annotation.py | 2 +- tests/spdx3/model/test_bom.py | 2 +- tests/spdx3/model/test_bundle.py | 2 +- tests/spdx3/model/test_creation_information.py | 2 +- tests/spdx3/model/test_external_identifier.py | 2 +- tests/spdx3/model/test_external_map.py | 2 +- tests/spdx3/model/test_external_reference.py | 2 +- tests/spdx3/model/test_hash.py | 2 +- tests/spdx3/model/test_namespace_map.py | 2 +- tests/spdx3/model/test_relationship.py | 2 +- tests/spdx3/model/test_spdx_document.py | 2 +- tests/spdx3/model/test_tool.py | 2 +- 86 files changed, 86 insertions(+), 86 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/actor.py b/src/spdx3/bump_from_spdx2/actor.py index 385051d05..d24bc2804 100644 --- a/src/spdx3/bump_from_spdx2/actor.py +++ b/src/spdx3/bump_from_spdx2/actor.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx3/bump_from_spdx2/annotation.py index f215d5084..a03bb619f 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx3/bump_from_spdx2/annotation.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from copy import deepcopy diff --git a/src/spdx3/bump_from_spdx2/bump_utils.py b/src/spdx3/bump_from_spdx2/bump_utils.py index f3f8db270..801ccc27e 100644 --- a/src/spdx3/bump_from_spdx2/bump_utils.py +++ b/src/spdx3/bump_from_spdx2/bump_utils.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Optional, Union diff --git a/src/spdx3/bump_from_spdx2/checksum.py b/src/spdx3/bump_from_spdx2/checksum.py index d62f41020..0f66b5221 100644 --- a/src/spdx3/bump_from_spdx2/checksum.py +++ b/src/spdx3/bump_from_spdx2/checksum.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from spdx3.model.hash import Hash, HashAlgorithm from spdx.model.checksum import Checksum as Spdx2_Checksum diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx3/bump_from_spdx2/creation_information.py index 7a85e9512..0c1fd0ec7 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx3/bump_from_spdx2/creation_information.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import List diff --git a/src/spdx3/bump_from_spdx2/external_document_ref.py b/src/spdx3/bump_from_spdx2/external_document_ref.py index ced98ce49..89dd4cecc 100644 --- a/src/spdx3/bump_from_spdx2/external_document_ref.py +++ b/src/spdx3/bump_from_spdx2/external_document_ref.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List diff --git a/src/spdx3/bump_from_spdx2/file.py b/src/spdx3/bump_from_spdx2/file.py index 145657ba5..eee707ba1 100644 --- a/src/spdx3/bump_from_spdx2/file.py +++ b/src/spdx3/bump_from_spdx2/file.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from spdx3.bump_from_spdx2.checksum import bump_checksum from spdx3.bump_from_spdx2.message import print_missing_conversion diff --git a/src/spdx3/bump_from_spdx2/message.py b/src/spdx3/bump_from_spdx2/message.py index f86d3c052..6351fce89 100644 --- a/src/spdx3/bump_from_spdx2/message.py +++ b/src/spdx3/bump_from_spdx2/message.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import sys diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index b0c8c08a1..602656af5 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from spdx3.bump_from_spdx2.actor import bump_actor from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none diff --git a/src/spdx3/bump_from_spdx2/relationship.py b/src/spdx3/bump_from_spdx2/relationship.py index 5bc3d275c..42913ee0d 100644 --- a/src/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx3/bump_from_spdx2/relationship.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Optional, Tuple diff --git a/src/spdx3/bump_from_spdx2/snippet.py b/src/spdx3/bump_from_spdx2/snippet.py index 2c2657137..e05b187da 100644 --- a/src/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx3/bump_from_spdx2/snippet.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.creation_information import CreationInformation diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx3/bump_from_spdx2/spdx_document.py index 874985125..4a4544895 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx3/bump_from_spdx2/spdx_document.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from spdx3.bump_from_spdx2.annotation import bump_annotation from spdx3.bump_from_spdx2.creation_information import bump_creation_information diff --git a/src/spdx3/clitools/pyspdxtools3.py b/src/spdx3/clitools/pyspdxtools3.py index 58e4878ca..20faeb5c4 100644 --- a/src/spdx3/clitools/pyspdxtools3.py +++ b/src/spdx3/clitools/pyspdxtools3.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import sys from typing import List diff --git a/src/spdx3/model/agent.py b/src/spdx3/model/agent.py index 91bd0d515..2eec0b1c1 100644 --- a/src/spdx3/model/agent.py +++ b/src/spdx3/model/agent.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx3/model/annotation.py b/src/spdx3/model/annotation.py index 6018a0495..0e9132395 100644 --- a/src/spdx3/model/annotation.py +++ b/src/spdx3/model/annotation.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import List, Optional diff --git a/src/spdx3/model/artifact.py b/src/spdx3/model/artifact.py index 439881c72..8e4555a0f 100644 --- a/src/spdx3/model/artifact.py +++ b/src/spdx3/model/artifact.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod from typing import Optional diff --git a/src/spdx3/model/bom.py b/src/spdx3/model/bom.py index 72bcd3b10..cf1ff35f1 100644 --- a/src/spdx3/model/bom.py +++ b/src/spdx3/model/bom.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx3/model/bundle.py b/src/spdx3/model/bundle.py index 1617572e4..ec531c9ad 100644 --- a/src/spdx3/model/bundle.py +++ b/src/spdx3/model/bundle.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx3/model/creation_information.py b/src/spdx3/model/creation_information.py index 113addc07..cdffd4b13 100644 --- a/src/spdx3/model/creation_information.py +++ b/src/spdx3/model/creation_information.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from typing import List, Optional diff --git a/src/spdx3/model/element.py b/src/spdx3/model/element.py index fbeb58090..50333d0ee 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx3/model/element.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from abc import ABC, abstractmethod from dataclasses import field diff --git a/src/spdx3/model/external_identifier.py b/src/spdx3/model/external_identifier.py index ba646532b..31b39db98 100644 --- a/src/spdx3/model/external_identifier.py +++ b/src/spdx3/model/external_identifier.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import Optional diff --git a/src/spdx3/model/external_map.py b/src/spdx3/model/external_map.py index 03ba7c82d..34b6542ca 100644 --- a/src/spdx3/model/external_map.py +++ b/src/spdx3/model/external_map.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from typing import List, Optional diff --git a/src/spdx3/model/external_reference.py b/src/spdx3/model/external_reference.py index 16630f300..9b574b30e 100644 --- a/src/spdx3/model/external_reference.py +++ b/src/spdx3/model/external_reference.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from enum import Enum, auto diff --git a/src/spdx3/model/hash.py b/src/spdx3/model/hash.py index 493b287f2..153d2b9d1 100644 --- a/src/spdx3/model/hash.py +++ b/src/spdx3/model/hash.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import Optional diff --git a/src/spdx3/model/integrity_method.py b/src/spdx3/model/integrity_method.py index aead03548..8744c9c0a 100644 --- a/src/spdx3/model/integrity_method.py +++ b/src/spdx3/model/integrity_method.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from abc import ABC, abstractmethod from typing import Optional diff --git a/src/spdx3/model/namespace_map.py b/src/spdx3/model/namespace_map.py index 2945cb924..7452d7e50 100644 --- a/src/spdx3/model/namespace_map.py +++ b/src/spdx3/model/namespace_map.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Optional diff --git a/src/spdx3/model/organization.py b/src/spdx3/model/organization.py index 15d48d267..8c2a2e2e8 100644 --- a/src/spdx3/model/organization.py +++ b/src/spdx3/model/organization.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx3/model/person.py b/src/spdx3/model/person.py index 365dc0432..00f1fda5b 100644 --- a/src/spdx3/model/person.py +++ b/src/spdx3/model/person.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx3/model/profile_identifier.py b/src/spdx3/model/profile_identifier.py index 21a6e443a..e939e791c 100644 --- a/src/spdx3/model/profile_identifier.py +++ b/src/spdx3/model/profile_identifier.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto diff --git a/src/spdx3/model/relationship.py b/src/spdx3/model/relationship.py index 55ab38290..7d103d8a6 100644 --- a/src/spdx3/model/relationship.py +++ b/src/spdx3/model/relationship.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto from typing import List, Optional diff --git a/src/spdx3/model/software/file.py b/src/spdx3/model/software/file.py index 227e80998..4dec4fb90 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx3/model/software/file.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 99e211f8c..092db5585 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx3/model/software/sbom.py b/src/spdx3/model/software/sbom.py index 334e5a74b..305c6112f 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx3/model/software/sbom.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx3/model/software/snippet.py b/src/spdx3/model/software/snippet.py index af133e7e9..6f9f3238e 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx3/model/software/snippet.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional, Tuple diff --git a/src/spdx3/model/software/software_purpose.py b/src/spdx3/model/software/software_purpose.py index b2674ca6d..282def1d5 100644 --- a/src/spdx3/model/software/software_purpose.py +++ b/src/spdx3/model/software/software_purpose.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto diff --git a/src/spdx3/model/software_agent.py b/src/spdx3/model/software_agent.py index 17be0a83d..1d6b62f7e 100644 --- a/src/spdx3/model/software_agent.py +++ b/src/spdx3/model/software_agent.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx3/model/spdx_collection.py b/src/spdx3/model/spdx_collection.py index a33298a16..d1c4676cb 100644 --- a/src/spdx3/model/spdx_collection.py +++ b/src/spdx3/model/spdx_collection.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod from dataclasses import field diff --git a/src/spdx3/model/spdx_document.py b/src/spdx3/model/spdx_document.py index 550f9908e..0562a2fb6 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx3/model/spdx_document.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx3/model/tool.py b/src/spdx3/model/tool.py index 7022ce319..d65fd1a35 100644 --- a/src/spdx3/model/tool.py +++ b/src/spdx3/model/tool.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional diff --git a/src/spdx3/payload.py b/src/spdx3/payload.py index 3ba8fc542..ff4aea6aa 100644 --- a/src/spdx3/payload.py +++ b/src/spdx3/payload.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Dict diff --git a/src/spdx3/writer/console/agent_writer.py b/src/spdx3/writer/console/agent_writer.py index c170eecc4..a906a8df5 100644 --- a/src/spdx3/writer/console/agent_writer.py +++ b/src/spdx3/writer/console/agent_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/annotation_writer.py b/src/spdx3/writer/console/annotation_writer.py index c707479ff..92d56cc67 100644 --- a/src/spdx3/writer/console/annotation_writer.py +++ b/src/spdx3/writer/console/annotation_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/artifact_writer.py b/src/spdx3/writer/console/artifact_writer.py index 8752b0ff1..7e47d587f 100644 --- a/src/spdx3/writer/console/artifact_writer.py +++ b/src/spdx3/writer/console/artifact_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/bom_writer.py b/src/spdx3/writer/console/bom_writer.py index 9db1f8087..7e019eacc 100644 --- a/src/spdx3/writer/console/bom_writer.py +++ b/src/spdx3/writer/console/bom_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/bundle_writer.py b/src/spdx3/writer/console/bundle_writer.py index 7c069dcf6..20818e40e 100644 --- a/src/spdx3/writer/console/bundle_writer.py +++ b/src/spdx3/writer/console/bundle_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/console.py b/src/spdx3/writer/console/console.py index 43cc97f3c..fd434e796 100644 --- a/src/spdx3/writer/console/console.py +++ b/src/spdx3/writer/console/console.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import Optional, TextIO, Union diff --git a/src/spdx3/writer/console/creation_information_writer.py b/src/spdx3/writer/console/creation_information_writer.py index 480c4f18e..f7790eeed 100644 --- a/src/spdx3/writer/console/creation_information_writer.py +++ b/src/spdx3/writer/console/creation_information_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/element_writer.py b/src/spdx3/writer/console/element_writer.py index 55c6333d4..afc91ccdc 100644 --- a/src/spdx3/writer/console/element_writer.py +++ b/src/spdx3/writer/console/element_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/external_identifier_writer.py b/src/spdx3/writer/console/external_identifier_writer.py index 976bab680..120b783ad 100644 --- a/src/spdx3/writer/console/external_identifier_writer.py +++ b/src/spdx3/writer/console/external_identifier_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/external_map_writer.py b/src/spdx3/writer/console/external_map_writer.py index 13fc4b5a1..c4dacc58b 100644 --- a/src/spdx3/writer/console/external_map_writer.py +++ b/src/spdx3/writer/console/external_map_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/external_reference_writer.py b/src/spdx3/writer/console/external_reference_writer.py index a17725a9b..c0fb4d93c 100644 --- a/src/spdx3/writer/console/external_reference_writer.py +++ b/src/spdx3/writer/console/external_reference_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/hash_writer.py b/src/spdx3/writer/console/hash_writer.py index e6df18a91..420d32e9f 100644 --- a/src/spdx3/writer/console/hash_writer.py +++ b/src/spdx3/writer/console/hash_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/integrity_method_writer.py b/src/spdx3/writer/console/integrity_method_writer.py index 966494236..315952898 100644 --- a/src/spdx3/writer/console/integrity_method_writer.py +++ b/src/spdx3/writer/console/integrity_method_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/namespace_map_writer.py b/src/spdx3/writer/console/namespace_map_writer.py index 14729cdec..5ff609eeb 100644 --- a/src/spdx3/writer/console/namespace_map_writer.py +++ b/src/spdx3/writer/console/namespace_map_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/payload_writer.py b/src/spdx3/writer/console/payload_writer.py index a98bf2751..5f18d7e88 100644 --- a/src/spdx3/writer/console/payload_writer.py +++ b/src/spdx3/writer/console/payload_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/relationship_writer.py b/src/spdx3/writer/console/relationship_writer.py index bd82b4208..b83aaa919 100644 --- a/src/spdx3/writer/console/relationship_writer.py +++ b/src/spdx3/writer/console/relationship_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/software/file_writer.py b/src/spdx3/writer/console/software/file_writer.py index c29b0ba9e..3e7e4937d 100644 --- a/src/spdx3/writer/console/software/file_writer.py +++ b/src/spdx3/writer/console/software/file_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/software/package_writer.py b/src/spdx3/writer/console/software/package_writer.py index 189e527a4..776357a30 100644 --- a/src/spdx3/writer/console/software/package_writer.py +++ b/src/spdx3/writer/console/software/package_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/software/sbom_writer.py b/src/spdx3/writer/console/software/sbom_writer.py index 6f54afa5f..30f42a426 100644 --- a/src/spdx3/writer/console/software/sbom_writer.py +++ b/src/spdx3/writer/console/software/sbom_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/software/snippet_writer.py b/src/spdx3/writer/console/software/snippet_writer.py index 9a86128f9..143dcd257 100644 --- a/src/spdx3/writer/console/software/snippet_writer.py +++ b/src/spdx3/writer/console/software/snippet_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/spdx_collection_writer.py b/src/spdx3/writer/console/spdx_collection_writer.py index af2fb39f0..72d763d56 100644 --- a/src/spdx3/writer/console/spdx_collection_writer.py +++ b/src/spdx3/writer/console/spdx_collection_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/src/spdx3/writer/console/spdx_document_writer.py b/src/spdx3/writer/console/spdx_document_writer.py index 8631122a9..0f408e63e 100644 --- a/src/spdx3/writer/console/spdx_document_writer.py +++ b/src/spdx3/writer/console/spdx_document_writer.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from typing import TextIO diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index 5a7a862dc..a55ecf705 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime diff --git a/tests/spdx3/bump/test_checksum_bump.py b/tests/spdx3/bump/test_checksum_bump.py index 09f4943eb..461b704b9 100644 --- a/tests/spdx3/bump/test_checksum_bump.py +++ b/tests/spdx3/bump/test_checksum_bump.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index cd9007095..5c4193ddc 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 0fbeb69de..b466cab69 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index f4c22e706..bdc98cb63 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index f1a78ec83..dc18a08b6 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import sys diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index 69b791ad8..2bed165c5 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index a3a017fef..544fe6bb6 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index f49736281..033746980 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index b13ef110f..16b116fa1 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/model/test_abstract_classes.py b/tests/spdx3/model/test_abstract_classes.py index be1b705da..5a5f72451 100644 --- a/tests/spdx3/model/test_abstract_classes.py +++ b/tests/spdx3/model/test_abstract_classes.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx3/model/test_agent.py b/tests/spdx3/model/test_agent.py index 070e03272..86097e2c9 100644 --- a/tests/spdx3/model/test_agent.py +++ b/tests/spdx3/model/test_agent.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime diff --git a/tests/spdx3/model/test_annotation.py b/tests/spdx3/model/test_annotation.py index d3622d2eb..aaf60dd71 100644 --- a/tests/spdx3/model/test_annotation.py +++ b/tests/spdx3/model/test_annotation.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/model/test_bom.py b/tests/spdx3/model/test_bom.py index 0c66b2a01..3f8cfed86 100644 --- a/tests/spdx3/model/test_bom.py +++ b/tests/spdx3/model/test_bom.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/model/test_bundle.py b/tests/spdx3/model/test_bundle.py index 340600b70..336059f27 100644 --- a/tests/spdx3/model/test_bundle.py +++ b/tests/spdx3/model/test_bundle.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py index 5b997b7e1..4aab6d25f 100644 --- a/tests/spdx3/model/test_creation_information.py +++ b/tests/spdx3/model/test_creation_information.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime diff --git a/tests/spdx3/model/test_external_identifier.py b/tests/spdx3/model/test_external_identifier.py index ddc314300..4a90d65d7 100644 --- a/tests/spdx3/model/test_external_identifier.py +++ b/tests/spdx3/model/test_external_identifier.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx3/model/test_external_map.py b/tests/spdx3/model/test_external_map.py index 62a1325ad..606257911 100644 --- a/tests/spdx3/model/test_external_map.py +++ b/tests/spdx3/model/test_external_map.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/model/test_external_reference.py b/tests/spdx3/model/test_external_reference.py index 338339acc..e882ddeb0 100644 --- a/tests/spdx3/model/test_external_reference.py +++ b/tests/spdx3/model/test_external_reference.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx3/model/test_hash.py b/tests/spdx3/model/test_hash.py index 6fee7bd00..d383adce3 100644 --- a/tests/spdx3/model/test_hash.py +++ b/tests/spdx3/model/test_hash.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx3/model/test_namespace_map.py b/tests/spdx3/model/test_namespace_map.py index 6bd1b707b..469753d32 100644 --- a/tests/spdx3/model/test_namespace_map.py +++ b/tests/spdx3/model/test_namespace_map.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 import pytest diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py index 0350c2c9c..b0869d7cc 100644 --- a/tests/spdx3/model/test_relationship.py +++ b/tests/spdx3/model/test_relationship.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/model/test_spdx_document.py b/tests/spdx3/model/test_spdx_document.py index c10e6de52..e234414df 100644 --- a/tests/spdx3/model/test_spdx_document.py +++ b/tests/spdx3/model/test_spdx_document.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from unittest import mock diff --git a/tests/spdx3/model/test_tool.py b/tests/spdx3/model/test_tool.py index 5ff3617c5..1a13c6032 100644 --- a/tests/spdx3/model/test_tool.py +++ b/tests/spdx3/model/test_tool.py @@ -1,5 +1,5 @@ # SPDX-FileCopyrightText: 2023 spdx contributors - +# # SPDX-License-Identifier: Apache-2.0 from datetime import datetime From 184a34ee126ddbcff4221978380dd2d2529e52ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 6 Apr 2023 11:39:50 +0200 Subject: [PATCH 173/354] [issue-427] add bumping of ExternalPackageRef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/package.py | 48 ++++++++++++++++++++++++++- tests/spdx3/bump/test_package_bump.py | 18 +++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index 602656af5..f008772e4 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -1,14 +1,19 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from typing import Union + from spdx3.bump_from_spdx2.actor import bump_actor from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none from spdx3.bump_from_spdx2.checksum import bump_checksum from spdx3.bump_from_spdx2.message import print_missing_conversion from spdx3.model.creation_information import CreationInformation +from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx3.model.external_reference import ExternalReference, ExternalReferenceType from spdx3.model.software.package import Package from spdx3.model.software.software_purpose import SoftwarePurpose from spdx3.payload import Payload +from spdx.model.package import ExternalPackageRef from spdx.model.package import Package as Spdx2_Package @@ -41,7 +46,16 @@ def bump_package( summary = spdx2_package.summary description = spdx2_package.description comment = spdx2_package.comment - print_missing_conversion("package2.external_references", 1, "of ExternalReferences / ExternalIdentifiers") + + external_references = [] + external_identifiers = [] + for spdx2_external_ref in spdx2_package.external_references: + id_or_ref = bump_external_package_ref(spdx2_external_ref) + if isinstance(id_or_ref, ExternalReference): + external_references.append(id_or_ref) + elif isinstance(id_or_ref, ExternalIdentifier): + external_identifiers.append(id_or_ref) + print_missing_conversion("package2.attribution_texts", 0) package_purpose = ( [SoftwarePurpose[spdx2_package.primary_package_purpose.name]] if spdx2_package.primary_package_purpose else [] @@ -57,6 +71,8 @@ def bump_package( description=description, comment=comment, verified_using=integrity_methods, + external_references=external_references, + external_identifier=external_identifiers, originated_by=originated_by_spdx_id, package_purpose=package_purpose, package_version=package_version, @@ -64,3 +80,33 @@ def bump_package( homepage=homepage, ) ) + + +external_ref_map = { + "cpe22Type": ExternalIdentifierType.CPE22, + "cpe23Type": ExternalIdentifierType.CPE23, + "advisory": ExternalReferenceType.SECURITY_ADVISORY, + "fix": ExternalReferenceType.SECURITY_FIX, + "url": None, + "swid": ExternalIdentifierType.SWID, + "maven-central": None, + "npm": None, + "nuget": None, + "bower": None, + "purl": ExternalIdentifierType.PURL, + "swh": ExternalIdentifierType.SWHID, + "gitoid": ExternalIdentifierType.GITOID, +} + + +def bump_external_package_ref(spdx2_external_ref: ExternalPackageRef) -> Union[ExternalReference, ExternalIdentifier]: + type = spdx2_external_ref.reference_type + locator = spdx2_external_ref.locator + comment = spdx2_external_ref.comment + + id_or_ref = external_ref_map[type] + + if isinstance(id_or_ref, ExternalReferenceType): + return ExternalReference(id_or_ref, [locator], None, comment) + elif isinstance(id_or_ref, ExternalIdentifierType): + return ExternalIdentifier(id_or_ref, locator, comment) diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index b466cab69..85fbe4cde 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -4,8 +4,11 @@ from unittest import mock from spdx3.bump_from_spdx2.package import bump_package +from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx3.model.external_reference import ExternalReference, ExternalReferenceType from spdx3.model.software.package import Package from spdx3.payload import Payload +from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory from spdx.model.package import Package as Spdx2_Package from tests.spdx.fixtures import package_fixture @@ -14,7 +17,14 @@ def test_bump_package(creation_information): payload = Payload() document_namespace = "https://doc.namespace" - spdx2_package: Spdx2_Package = package_fixture() + spdx2_package: Spdx2_Package = package_fixture( + external_references=[ + ExternalPackageRef( + ExternalPackageRefCategory.SECURITY, "advisory", "advisory_locator", "advisory_comment" + ), + ExternalPackageRef(ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh_locator", "swh_comment"), + ] + ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" bump_package(spdx2_package, payload, creation_information, document_namespace) @@ -23,3 +33,9 @@ def test_bump_package(creation_information): assert isinstance(package, Package) assert package.spdx_id == expected_new_package_id assert package.package_version == spdx2_package.version + assert package.external_references == [ + ExternalReference(ExternalReferenceType.SECURITY_ADVISORY, ["advisory_locator"], None, "advisory_comment") + ] + assert package.external_identifier == [ + ExternalIdentifier(ExternalIdentifierType.SWHID, "swh_locator", "swh_comment") + ] From c28f999074664c829f934702c5a7305efaa69328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 6 Apr 2023 13:31:14 +0200 Subject: [PATCH 174/354] [issue-427] add purl special case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/package.py | 29 +++++++++--- src/spdx3/model/software/package.py | 4 +- .../writer/console/software/package_writer.py | 2 +- tests/spdx3/bump/test_package_bump.py | 47 ++++++++++++++++++- tests/spdx3/model/software/test_package.py | 8 ++-- 5 files changed, 75 insertions(+), 15 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index f008772e4..70cc3538e 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -49,7 +49,16 @@ def bump_package( external_references = [] external_identifiers = [] + purl_refs = [ + external_ref for external_ref in spdx2_package.external_references if external_ref.reference_type == "purl" + ] + exactly_one_purl = len(purl_refs) == 1 + package_url = None + if exactly_one_purl: + package_url = purl_refs[0].locator for spdx2_external_ref in spdx2_package.external_references: + if exactly_one_purl and spdx2_external_ref.reference_type == "purl": + continue id_or_ref = bump_external_package_ref(spdx2_external_ref) if isinstance(id_or_ref, ExternalReference): external_references.append(id_or_ref) @@ -77,12 +86,13 @@ def bump_package( package_purpose=package_purpose, package_version=package_version, download_location=download_location, + package_url=package_url, homepage=homepage, ) ) -external_ref_map = { +external_ref_type_map = { "cpe22Type": ExternalIdentifierType.CPE22, "cpe23Type": ExternalIdentifierType.CPE23, "advisory": ExternalReferenceType.SECURITY_ADVISORY, @@ -100,13 +110,18 @@ def bump_package( def bump_external_package_ref(spdx2_external_ref: ExternalPackageRef) -> Union[ExternalReference, ExternalIdentifier]: - type = spdx2_external_ref.reference_type + reference_type = spdx2_external_ref.reference_type locator = spdx2_external_ref.locator comment = spdx2_external_ref.comment - id_or_ref = external_ref_map[type] + if reference_type not in external_ref_type_map: + raise NotImplementedError( + f"Conversion of ExternalPackageRef of type {reference_type} is currently not supported." + ) + + id_or_ref_type = external_ref_type_map[reference_type] - if isinstance(id_or_ref, ExternalReferenceType): - return ExternalReference(id_or_ref, [locator], None, comment) - elif isinstance(id_or_ref, ExternalIdentifierType): - return ExternalIdentifier(id_or_ref, locator, comment) + if isinstance(id_or_ref_type, ExternalReferenceType): + return ExternalReference(id_or_ref_type, [locator], None, comment) + elif isinstance(id_or_ref_type, ExternalIdentifierType): + return ExternalIdentifier(id_or_ref_type, locator, comment) diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index 092db5585..af2ecd6cc 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -19,7 +19,7 @@ class Package(Artifact): package_purpose: Optional[List[SoftwarePurpose]] = None package_version: Optional[str] = None download_location: Optional[str] = None # anyURI - package_uri: Optional[str] = None # anyURI + package_url: Optional[str] = None # anyURI homepage: Optional[str] = None # anyURI def __init__( @@ -39,7 +39,7 @@ def __init__( package_purpose: Optional[List[SoftwarePurpose]] = None, package_version: Optional[str] = None, download_location: Optional[str] = None, - package_uri: Optional[str] = None, + package_url: Optional[str] = None, homepage: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx3/writer/console/software/package_writer.py b/src/spdx3/writer/console/software/package_writer.py index 776357a30..a422d18d4 100644 --- a/src/spdx3/writer/console/software/package_writer.py +++ b/src/spdx3/writer/console/software/package_writer.py @@ -15,5 +15,5 @@ def write_package(package: Package, text_output: TextIO): write_value("package_purpose", ", ".join([purpose.name for purpose in package.package_purpose]), text_output) write_value("package_version", package.package_version, text_output) write_value("download_location", package.download_location, text_output) - write_value("package_uri", package.package_uri, text_output) + write_value("package_uri", package.package_url, text_output) write_value("homepage", package.homepage, text_output) diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 85fbe4cde..fb6f81598 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from unittest import mock +from unittest import TestCase, mock from spdx3.bump_from_spdx2.package import bump_package from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType @@ -39,3 +39,48 @@ def test_bump_package(creation_information): assert package.external_identifier == [ ExternalIdentifier(ExternalIdentifierType.SWHID, "swh_locator", "swh_comment") ] + + +@mock.patch("spdx3.model.creation_information.CreationInformation") +def test_bump_of_single_purl(creation_information): + payload = Payload() + document_namespace = "https://doc.namespace" + spdx2_package: Spdx2_Package = package_fixture( + external_references=[ + ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator", "purl_comment"), + ] + ) + expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" + + bump_package(spdx2_package, payload, creation_information, document_namespace) + package = payload.get_element(expected_new_package_id) + + assert package.package_url == "purl_locator" + assert package.external_references == [] + assert package.external_identifier == [] + + +@mock.patch("spdx3.model.creation_information.CreationInformation") +def test_bump_of_multiple_purls(creation_information): + payload = Payload() + document_namespace = "https://doc.namespace" + spdx2_package: Spdx2_Package = package_fixture( + external_references=[ + ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator", "purl_comment"), + ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator2", "purl_comment2"), + ] + ) + expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" + + bump_package(spdx2_package, payload, creation_information, document_namespace) + package = payload.get_element(expected_new_package_id) + + assert package.package_url is None + assert package.external_references == [] + TestCase().assertCountEqual( + package.external_identifier, + [ + ExternalIdentifier(ExternalIdentifierType.PURL, "purl_locator", "purl_comment"), + ExternalIdentifier(ExternalIdentifierType.PURL, "purl_locator2", "purl_comment2"), + ], + ) diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 544fe6bb6..506704a07 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -18,7 +18,7 @@ def test_correct_initialization(creation_information): package_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH], package_version="1:23a_bc", download_location="https://downloadlocation", - package_uri="https://package.uri", + package_url="https://package.uri", homepage="https://homepage", ) @@ -28,7 +28,7 @@ def test_correct_initialization(creation_information): assert package.package_purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH] assert package.package_version == "1:23a_bc" assert package.download_location == "https://downloadlocation" - assert package.package_uri == "https://package.uri" + assert package.package_url == "https://package.uri" assert package.homepage == "https://homepage" @@ -42,7 +42,7 @@ def test_invalid_initialization(creation_information): package_purpose=SoftwarePurpose.FILE, package_version=42, download_location=4, - package_uri=["uris"], + package_url=["uris"], homepage=True, ) @@ -57,7 +57,7 @@ def test_invalid_initialization(creation_information): "(str, NoneType); got int instead: 42", 'SetterError Package: type of argument "download_location" must be one of ' "(str, NoneType); got int instead: 4", - 'SetterError Package: type of argument "package_uri" must be one of (str, ' + 'SetterError Package: type of argument "package_url" must be one of (str, ' "NoneType); got list instead: ['uris']", 'SetterError Package: type of argument "homepage" must be one of (str, ' "NoneType); got bool instead: True", ] From a4559e9f44553de6d1bc569f6a823bd235770fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 11 Apr 2023 13:23:35 +0200 Subject: [PATCH 175/354] [issue-427] add purl special case with comment distinction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/bump_from_spdx2/package.py | 6 ++--- tests/spdx3/bump/test_package_bump.py | 33 ++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index 70cc3538e..c5108f736 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -52,12 +52,12 @@ def bump_package( purl_refs = [ external_ref for external_ref in spdx2_package.external_references if external_ref.reference_type == "purl" ] - exactly_one_purl = len(purl_refs) == 1 + exactly_one_purl_without_comment = len(purl_refs) == 1 and purl_refs[0].comment is None package_url = None - if exactly_one_purl: + if exactly_one_purl_without_comment: package_url = purl_refs[0].locator for spdx2_external_ref in spdx2_package.external_references: - if exactly_one_purl and spdx2_external_ref.reference_type == "purl": + if exactly_one_purl_without_comment and spdx2_external_ref.reference_type == "purl": continue id_or_ref = bump_external_package_ref(spdx2_external_ref) if isinstance(id_or_ref, ExternalReference): diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index fb6f81598..f2ba8ff40 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -42,12 +42,12 @@ def test_bump_package(creation_information): @mock.patch("spdx3.model.creation_information.CreationInformation") -def test_bump_of_single_purl(creation_information): +def test_bump_of_single_purl_without_comment(creation_information): payload = Payload() document_namespace = "https://doc.namespace" spdx2_package: Spdx2_Package = package_fixture( external_references=[ - ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator", "purl_comment"), + ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator", None), ] ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" @@ -61,13 +61,34 @@ def test_bump_of_single_purl(creation_information): @mock.patch("spdx3.model.creation_information.CreationInformation") -def test_bump_of_multiple_purls(creation_information): +def test_bump_of_single_purl_with_comment(creation_information): payload = Payload() document_namespace = "https://doc.namespace" spdx2_package: Spdx2_Package = package_fixture( external_references=[ ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator", "purl_comment"), - ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator2", "purl_comment2"), + ] + ) + expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" + + bump_package(spdx2_package, payload, creation_information, document_namespace) + package = payload.get_element(expected_new_package_id) + + assert package.package_url is None + assert package.external_references == [] + assert package.external_identifier == [ + ExternalIdentifier(ExternalIdentifierType.PURL, "purl_locator", "purl_comment") + ] + + +@mock.patch("spdx3.model.creation_information.CreationInformation") +def test_bump_of_multiple_purls(creation_information): + payload = Payload() + document_namespace = "https://doc.namespace" + spdx2_package: Spdx2_Package = package_fixture( + external_references=[ + ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator", "comment"), + ExternalPackageRef(ExternalPackageRefCategory.PACKAGE_MANAGER, "purl", "purl_locator2", None), ] ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" @@ -80,7 +101,7 @@ def test_bump_of_multiple_purls(creation_information): TestCase().assertCountEqual( package.external_identifier, [ - ExternalIdentifier(ExternalIdentifierType.PURL, "purl_locator", "purl_comment"), - ExternalIdentifier(ExternalIdentifierType.PURL, "purl_locator2", "purl_comment2"), + ExternalIdentifier(ExternalIdentifierType.PURL, "purl_locator", "comment"), + ExternalIdentifier(ExternalIdentifierType.PURL, "purl_locator2", None), ], ) From 17c7f9006bf1d3c1c82691580fb6a7066c2fc532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 17 Apr 2023 12:09:40 +0200 Subject: [PATCH 176/354] [issue-426] SPDX 3: add source_info to Package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx3/README.md | 2 +- src/spdx3/bump_from_spdx2/package.py | 3 ++- src/spdx3/model/software/package.py | 2 ++ tests/spdx3/bump/test_package_bump.py | 4 ++++ tests/spdx3/model/software/test_package.py | 5 +++++ 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/spdx3/README.md b/src/spdx3/README.md index 01a227547..da81b6af8 100644 --- a/src/spdx3/README.md +++ b/src/spdx3/README.md @@ -1 +1 @@ -This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: 01360996d37c1d913f3d15e2d5911ace182ed200). +This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: 81ce08107ae8b295814dcc631cfa1c48124887aa). diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx3/bump_from_spdx2/package.py index c5108f736..2b920b40a 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx3/bump_from_spdx2/package.py @@ -36,7 +36,7 @@ def bump_package( # package.checksums -> package.verified_using integrity_methods = [bump_checksum(checksum) for checksum in spdx2_package.checksums] homepage = spdx2_package.homepage - print_missing_conversion("package2.source_info", 0) + source_info = spdx2_package.source_info print_missing_conversion( "package2.license_concluded, package2.license_info_from_files, package2.license_declared, " "package2.license_comment, package2.copyright_text", @@ -88,6 +88,7 @@ def bump_package( download_location=download_location, package_url=package_url, homepage=homepage, + source_info=source_info, ) ) diff --git a/src/spdx3/model/software/package.py b/src/spdx3/model/software/package.py index af2ecd6cc..587fc70e4 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx3/model/software/package.py @@ -21,6 +21,7 @@ class Package(Artifact): download_location: Optional[str] = None # anyURI package_url: Optional[str] = None # anyURI homepage: Optional[str] = None # anyURI + source_info: Optional[str] = None def __init__( self, @@ -41,6 +42,7 @@ def __init__( download_location: Optional[str] = None, package_url: Optional[str] = None, homepage: Optional[str] = None, + source_info: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index f2ba8ff40..bbfea0619 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -39,6 +39,10 @@ def test_bump_package(creation_information): assert package.external_identifier == [ ExternalIdentifier(ExternalIdentifierType.SWHID, "swh_locator", "swh_comment") ] + assert package.download_location == spdx2_package.download_location + assert package.package_version == spdx2_package.version + assert package.homepage == spdx2_package.homepage + assert package.source_info == spdx2_package.source_info @mock.patch("spdx3.model.creation_information.CreationInformation") diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 506704a07..3f3b84a2e 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -20,6 +20,7 @@ def test_correct_initialization(creation_information): download_location="https://downloadlocation", package_url="https://package.uri", homepage="https://homepage", + source_info="some info", ) assert package.spdx_id == "SPDXRef-Package" @@ -30,6 +31,7 @@ def test_correct_initialization(creation_information): assert package.download_location == "https://downloadlocation" assert package.package_url == "https://package.uri" assert package.homepage == "https://homepage" + assert package.source_info == "some info" @mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) @@ -44,6 +46,7 @@ def test_invalid_initialization(creation_information): download_location=4, package_url=["uris"], homepage=True, + source_info=["some info"], ) assert err.value.args[0] == [ @@ -60,4 +63,6 @@ def test_invalid_initialization(creation_information): 'SetterError Package: type of argument "package_url" must be one of (str, ' "NoneType); got list instead: ['uris']", 'SetterError Package: type of argument "homepage" must be one of (str, ' "NoneType); got bool instead: True", + 'SetterError Package: type of argument "source_info" must be one of (str, ' + "NoneType); got list instead: ['some info']", ] From a370f7be65bad2adc1af4b6872a51b6708355c39 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 19 Apr 2023 10:39:08 +0200 Subject: [PATCH 177/354] [issue_592] add top-level package Signed-off-by: Meret Behrens --- pyproject.toml | 2 +- src/spdx3/writer/console/__init__.py | 2 - src/spdx3/writer/console/payload_writer.py | 53 ------------------- src/{ => spdx_tools}/spdx3/README.md | 0 src/{ => spdx_tools}/spdx3/__init__.py | 0 .../spdx3/bump_from_spdx2/__init__.py | 0 .../spdx3/bump_from_spdx2/actor.py | 16 +++--- .../spdx3/bump_from_spdx2/annotation.py | 12 ++--- .../spdx3/bump_from_spdx2/bump_utils.py | 4 +- .../spdx3/bump_from_spdx2/checksum.py | 6 +-- .../bump_from_spdx2/creation_information.py | 16 +++--- .../bump_from_spdx2/external_document_ref.py | 8 +-- .../spdx3/bump_from_spdx2/file.py | 12 ++--- .../spdx3/bump_from_spdx2/message.py | 0 .../spdx3/bump_from_spdx2/package.py | 24 ++++----- .../spdx3/bump_from_spdx2/relationship.py | 14 ++--- .../spdx3/bump_from_spdx2/snippet.py | 10 ++-- .../spdx3/bump_from_spdx2/spdx_document.py | 20 +++---- .../spdx3/clitools/__init__.py | 0 .../spdx3/clitools/pyspdxtools3.py | 14 ++--- src/{ => spdx_tools}/spdx3/model/__init__.py | 0 src/{ => spdx_tools}/spdx3/model/agent.py | 14 ++--- .../spdx3/model/annotation.py | 14 ++--- src/{ => spdx_tools}/spdx3/model/artifact.py | 4 +- src/{ => spdx_tools}/spdx3/model/bom.py | 18 +++---- src/{ => spdx_tools}/spdx3/model/bundle.py | 18 +++---- .../spdx3/model/creation_information.py | 4 +- src/{ => spdx_tools}/spdx3/model/element.py | 10 ++-- .../spdx3/model/external_identifier.py | 4 +- .../spdx3/model/external_map.py | 6 +-- .../spdx3/model/external_reference.py | 4 +- src/{ => spdx_tools}/spdx3/model/hash.py | 6 +-- .../spdx3/model/integrity_method.py | 2 +- .../spdx3/model/namespace_map.py | 4 +- .../spdx3/model/organization.py | 14 ++--- src/{ => spdx_tools}/spdx3/model/person.py | 14 ++--- .../spdx3/model/profile_identifier.py | 0 .../spdx3/model/relationship.py | 14 ++--- .../spdx3/model/software/__init__.py | 0 .../spdx3/model/software/file.py | 16 +++--- .../spdx3/model/software/package.py | 16 +++--- .../spdx3/model/software/sbom.py | 18 +++---- .../spdx3/model/software/snippet.py | 16 +++--- .../spdx3/model/software/software_purpose.py | 0 .../spdx3/model/software_agent.py | 14 ++--- .../spdx3/model/spdx_collection.py | 8 +-- .../spdx3/model/spdx_document.py | 18 +++---- src/{ => spdx_tools}/spdx3/model/tool.py | 14 ++--- src/{ => spdx_tools}/spdx3/payload.py | 2 +- .../spdx3/writer}/__init__.py | 0 .../spdx3/writer/console/__init__.py | 2 + .../spdx3/writer/console/agent_writer.py | 10 ++-- .../spdx3/writer/console/annotation_writer.py | 6 +-- .../spdx3/writer/console/artifact_writer.py | 6 +-- .../spdx3/writer/console/bom_writer.py | 4 +- .../spdx3/writer/console/bundle_writer.py | 6 +-- .../spdx3/writer/console/console.py | 4 +- .../console/creation_information_writer.py | 6 +-- .../spdx3/writer/console/element_writer.py | 14 ++--- .../console/external_identifier_writer.py | 4 +- .../writer/console/external_map_writer.py | 8 +-- .../console/external_reference_writer.py | 4 +- .../spdx3/writer/console/hash_writer.py | 6 +-- .../writer/console/integrity_method_writer.py | 4 +- .../writer/console/namespace_map_writer.py | 4 +- .../spdx3/writer/console/payload_writer.py | 53 +++++++++++++++++++ .../writer/console/relationship_writer.py | 6 +-- .../spdx3/writer/console/software/__init__.py | 0 .../writer/console/software/file_writer.py | 6 +-- .../writer/console/software/package_writer.py | 6 +-- .../writer/console/software/sbom_writer.py | 4 +- .../writer/console/software/snippet_writer.py | 8 +-- .../writer/console/spdx_collection_writer.py | 10 ++-- .../writer/console/spdx_document_writer.py | 4 +- .../spdx3/writer/console/tool_writer.py | 4 +- tests/spdx3/bump/test_actor_bump.py | 16 +++--- tests/spdx3/bump/test_bump_utils.py | 6 +-- tests/spdx3/bump/test_checksum_bump.py | 6 +-- tests/spdx3/bump/test_file_bump.py | 12 ++--- tests/spdx3/bump/test_package_bump.py | 22 ++++---- tests/spdx3/bump/test_snippet_bump.py | 10 ++-- tests/spdx3/bump/test_spdx_document_bump.py | 10 ++-- tests/spdx3/model/software/test_file.py | 14 ++--- tests/spdx3/model/software/test_package.py | 12 ++--- tests/spdx3/model/software/test_sbom.py | 6 +-- tests/spdx3/model/software/test_snippet.py | 8 +-- tests/spdx3/model/test_abstract_classes.py | 8 +-- tests/spdx3/model/test_agent.py | 14 ++--- tests/spdx3/model/test_annotation.py | 8 +-- tests/spdx3/model/test_bom.py | 6 +-- tests/spdx3/model/test_bundle.py | 10 ++-- .../spdx3/model/test_creation_information.py | 2 +- tests/spdx3/model/test_external_identifier.py | 4 +- tests/spdx3/model/test_external_map.py | 4 +- tests/spdx3/model/test_external_reference.py | 4 +- tests/spdx3/model/test_hash.py | 4 +- tests/spdx3/model/test_namespace_map.py | 2 +- tests/spdx3/model/test_relationship.py | 10 ++-- tests/spdx3/model/test_spdx_document.py | 8 +-- tests/spdx3/model/test_tool.py | 6 +-- 100 files changed, 443 insertions(+), 443 deletions(-) delete mode 100644 src/spdx3/writer/console/__init__.py delete mode 100644 src/spdx3/writer/console/payload_writer.py rename src/{ => spdx_tools}/spdx3/README.md (100%) rename src/{ => spdx_tools}/spdx3/__init__.py (100%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/__init__.py (100%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/actor.py (77%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/annotation.py (78%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/bump_utils.py (79%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/checksum.py (78%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/creation_information.py (82%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/external_document_ref.py (65%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/file.py (74%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/message.py (100%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/package.py (84%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/relationship.py (84%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/snippet.py (77%) rename src/{ => spdx_tools}/spdx3/bump_from_spdx2/spdx_document.py (70%) rename src/{ => spdx_tools}/spdx3/clitools/__init__.py (100%) rename src/{ => spdx_tools}/spdx3/clitools/pyspdxtools3.py (79%) rename src/{ => spdx_tools}/spdx3/model/__init__.py (100%) rename src/{ => spdx_tools}/spdx3/model/agent.py (65%) rename src/{ => spdx_tools}/spdx3/model/annotation.py (73%) rename src/{ => spdx_tools}/spdx3/model/artifact.py (70%) rename src/{ => spdx_tools}/spdx3/model/bom.py (69%) rename src/{ => spdx_tools}/spdx3/model/bundle.py (67%) rename src/{ => spdx_tools}/spdx3/model/creation_information.py (83%) rename src/{ => spdx_tools}/spdx3/model/element.py (68%) rename src/{ => spdx_tools}/spdx3/model/external_identifier.py (81%) rename src/{ => spdx_tools}/spdx3/model/external_map.py (74%) rename src/{ => spdx_tools}/spdx3/model/external_reference.py (85%) rename src/{ => spdx_tools}/spdx3/model/hash.py (78%) rename src/{ => spdx_tools}/spdx3/model/integrity_method.py (77%) rename src/{ => spdx_tools}/spdx3/model/namespace_map.py (70%) rename src/{ => spdx_tools}/spdx3/model/organization.py (66%) rename src/{ => spdx_tools}/spdx3/model/person.py (66%) rename src/{ => spdx_tools}/spdx3/model/profile_identifier.py (100%) rename src/{ => spdx_tools}/spdx3/model/relationship.py (84%) rename src/{ => spdx_tools}/spdx3/model/software/__init__.py (100%) rename src/{ => spdx_tools}/spdx3/model/software/file.py (71%) rename src/{ => spdx_tools}/spdx3/model/software/package.py (75%) rename src/{ => spdx_tools}/spdx3/model/software/sbom.py (69%) rename src/{ => spdx_tools}/spdx3/model/software/snippet.py (72%) rename src/{ => spdx_tools}/spdx3/model/software/software_purpose.py (100%) rename src/{ => spdx_tools}/spdx3/model/software_agent.py (66%) rename src/{ => spdx_tools}/spdx3/model/spdx_collection.py (73%) rename src/{ => spdx_tools}/spdx3/model/spdx_document.py (70%) rename src/{ => spdx_tools}/spdx3/model/tool.py (65%) rename src/{ => spdx_tools}/spdx3/payload.py (91%) rename src/{spdx3/writer/console/software => spdx_tools/spdx3/writer}/__init__.py (100%) create mode 100644 src/spdx_tools/spdx3/writer/console/__init__.py rename src/{ => spdx_tools}/spdx3/writer/console/agent_writer.py (63%) rename src/{ => spdx_tools}/spdx3/writer/console/annotation_writer.py (73%) rename src/{ => spdx_tools}/spdx3/writer/console/artifact_writer.py (60%) rename src/{ => spdx_tools}/spdx3/writer/console/bom_writer.py (71%) rename src/{ => spdx_tools}/spdx3/writer/console/bundle_writer.py (63%) rename src/{ => spdx_tools}/spdx3/writer/console/console.py (68%) rename src/{ => spdx_tools}/spdx3/writer/console/creation_information_writer.py (81%) rename src/{ => spdx_tools}/spdx3/writer/console/element_writer.py (71%) rename src/{ => spdx_tools}/spdx3/writer/console/external_identifier_writer.py (76%) rename src/{ => spdx_tools}/spdx3/writer/console/external_map_writer.py (73%) rename src/{ => spdx_tools}/spdx3/writer/console/external_reference_writer.py (79%) rename src/{ => spdx_tools}/spdx3/writer/console/hash_writer.py (70%) rename src/{ => spdx_tools}/spdx3/writer/console/integrity_method_writer.py (69%) rename src/{ => spdx_tools}/spdx3/writer/console/namespace_map_writer.py (71%) create mode 100644 src/spdx_tools/spdx3/writer/console/payload_writer.py rename src/{ => spdx_tools}/spdx3/writer/console/relationship_writer.py (75%) create mode 100644 src/spdx_tools/spdx3/writer/console/software/__init__.py rename src/{ => spdx_tools}/spdx3/writer/console/software/file_writer.py (70%) rename src/{ => spdx_tools}/spdx3/writer/console/software/package_writer.py (77%) rename src/{ => spdx_tools}/spdx3/writer/console/software/sbom_writer.py (67%) rename src/{ => spdx_tools}/spdx3/writer/console/software/snippet_writer.py (66%) rename src/{ => spdx_tools}/spdx3/writer/console/spdx_collection_writer.py (61%) rename src/{ => spdx_tools}/spdx3/writer/console/spdx_document_writer.py (68%) rename src/{ => spdx_tools}/spdx3/writer/console/tool_writer.py (85%) diff --git a/pyproject.toml b/pyproject.toml index ed52dd970..1cc724e42 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,7 @@ development = ["black", "flake8", "isort", "networkx", "pytest"] [project.scripts] pyspdxtools = "spdx_tools.spdx.clitools.pyspdxtools:main" -pyspdxtools3 = "spdx3.clitools.pyspdxtools3:main" +pyspdxtools3 = "spdx_tools.spdx3.clitools.pyspdxtools3:main" [tool.setuptools] zip-safe = false # because of the uses of __file__: https://github.com/spdx/tools-python/issues/257 diff --git a/src/spdx3/writer/console/__init__.py b/src/spdx3/writer/console/__init__.py deleted file mode 100644 index c2d090abc..000000000 --- a/src/spdx3/writer/console/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -""" This is a temporary package to write the implemented model of spdx3.0 to console. As soon as serialization formats - are properly defined this package can be deleted.""" diff --git a/src/spdx3/writer/console/payload_writer.py b/src/spdx3/writer/console/payload_writer.py deleted file mode 100644 index 5f18d7e88..000000000 --- a/src/spdx3/writer/console/payload_writer.py +++ /dev/null @@ -1,53 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from typing import TextIO - -from spdx3.model.annotation import Annotation -from spdx3.model.bom import Bom -from spdx3.model.bundle import Bundle -from spdx3.model.organization import Organization -from spdx3.model.person import Person -from spdx3.model.relationship import Relationship -from spdx3.model.software.file import File -from spdx3.model.software.package import Package -from spdx3.model.software.sbom import Sbom -from spdx3.model.software.snippet import Snippet -from spdx3.model.software_agent import SoftwareAgent -from spdx3.model.spdx_document import SpdxDocument -from spdx3.model.tool import Tool -from spdx3.payload import Payload -from spdx3.writer.console.agent_writer import write_agent -from spdx3.writer.console.annotation_writer import write_annotation -from spdx3.writer.console.bom_writer import write_bom -from spdx3.writer.console.bundle_writer import write_bundle -from spdx3.writer.console.relationship_writer import write_relationship -from spdx3.writer.console.software.file_writer import write_file -from spdx3.writer.console.software.package_writer import write_package -from spdx3.writer.console.software.sbom_writer import write_sbom -from spdx3.writer.console.software.snippet_writer import write_snippet -from spdx3.writer.console.spdx_document_writer import write_spdx_document -from spdx3.writer.console.tool_writer import write_tool - -MAP_CLASS_TO_WRITE_METHOD = { - Annotation: write_annotation, - Relationship: write_relationship, - Bundle: write_bundle, - SpdxDocument: write_spdx_document, - Bom: write_bom, - File: write_file, - Package: write_package, - Snippet: write_snippet, - Sbom: write_sbom, - Person: write_agent, - Organization: write_agent, - SoftwareAgent: write_agent, - Tool: write_tool, -} - - -def write_payload(payload: Payload, text_output: TextIO): - for element in payload.get_full_map().values(): - write_method = MAP_CLASS_TO_WRITE_METHOD[type(element)] - write_method(element, text_output) - text_output.write("\n") diff --git a/src/spdx3/README.md b/src/spdx_tools/spdx3/README.md similarity index 100% rename from src/spdx3/README.md rename to src/spdx_tools/spdx3/README.md diff --git a/src/spdx3/__init__.py b/src/spdx_tools/spdx3/__init__.py similarity index 100% rename from src/spdx3/__init__.py rename to src/spdx_tools/spdx3/__init__.py diff --git a/src/spdx3/bump_from_spdx2/__init__.py b/src/spdx_tools/spdx3/bump_from_spdx2/__init__.py similarity index 100% rename from src/spdx3/bump_from_spdx2/__init__.py rename to src/spdx_tools/spdx3/bump_from_spdx2/__init__.py diff --git a/src/spdx3/bump_from_spdx2/actor.py b/src/spdx_tools/spdx3/bump_from_spdx2/actor.py similarity index 77% rename from src/spdx3/bump_from_spdx2/actor.py rename to src/spdx_tools/spdx3/bump_from_spdx2/actor.py index d24bc2804..99212a54a 100644 --- a/src/spdx3/bump_from_spdx2/actor.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/actor.py @@ -3,14 +3,14 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType -from spdx3.model.organization import Organization -from spdx3.model.person import Person -from spdx3.model.tool import Tool -from spdx3.payload import Payload -from spdx.model.actor import Actor as Spdx2_Actor -from spdx.model.actor import ActorType +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx_tools.spdx3.model.organization import Organization +from spdx_tools.spdx3.model.person import Person +from spdx_tools.spdx3.model.tool import Tool +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.actor import Actor as Spdx2_Actor +from spdx_tools.spdx.model.actor import ActorType def bump_actor( diff --git a/src/spdx3/bump_from_spdx2/annotation.py b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py similarity index 78% rename from src/spdx3/bump_from_spdx2/annotation.py rename to src/spdx_tools/spdx3/bump_from_spdx2/annotation.py index a03bb619f..e14340aa9 100644 --- a/src/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py @@ -3,12 +3,12 @@ # SPDX-License-Identifier: Apache-2.0 from copy import deepcopy -from spdx3.bump_from_spdx2.actor import bump_actor -from spdx3.model.annotation import Annotation, AnnotationType -from spdx3.model.creation_information import CreationInformation -from spdx3.payload import Payload -from spdx.model.actor import ActorType -from spdx.model.annotation import Annotation as Spdx2_Annotation +from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor +from spdx_tools.spdx3.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.actor import ActorType +from spdx_tools.spdx.model.annotation import Annotation as Spdx2_Annotation def bump_annotation( diff --git a/src/spdx3/bump_from_spdx2/bump_utils.py b/src/spdx_tools/spdx3/bump_from_spdx2/bump_utils.py similarity index 79% rename from src/spdx3/bump_from_spdx2/bump_utils.py rename to src/spdx_tools/spdx3/bump_from_spdx2/bump_utils.py index 801ccc27e..e45b05909 100644 --- a/src/spdx3/bump_from_spdx2/bump_utils.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/bump_utils.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Optional, Union -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone def handle_no_assertion_or_none(field: Union[SpdxNone, SpdxNoAssertion, str], field_name: str) -> Optional[str]: diff --git a/src/spdx3/bump_from_spdx2/checksum.py b/src/spdx_tools/spdx3/bump_from_spdx2/checksum.py similarity index 78% rename from src/spdx3/bump_from_spdx2/checksum.py rename to src/spdx_tools/spdx3/bump_from_spdx2/checksum.py index 0f66b5221..b52b5472b 100644 --- a/src/spdx3/bump_from_spdx2/checksum.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/checksum.py @@ -1,9 +1,9 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from spdx3.model.hash import Hash, HashAlgorithm -from spdx.model.checksum import Checksum as Spdx2_Checksum -from spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm +from spdx_tools.spdx.model.checksum import Checksum as Spdx2_Checksum +from spdx_tools.spdx.model.checksum import ChecksumAlgorithm def bump_checksum(spdx2_checksum: Spdx2_Checksum) -> Hash: diff --git a/src/spdx3/bump_from_spdx2/creation_information.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py similarity index 82% rename from src/spdx3/bump_from_spdx2/creation_information.py rename to src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py index 0c1fd0ec7..68e4f1484 100644 --- a/src/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py @@ -6,14 +6,14 @@ from semantic_version import Version -from spdx3.bump_from_spdx2.actor import bump_actor -from spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref -from spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx3.model.creation_information import CreationInformation -from spdx3.model.spdx_document import SpdxDocument -from spdx3.payload import Payload -from spdx.model.actor import ActorType -from spdx.model.document import CreationInfo as Spdx2_CreationInfo +from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor +from spdx_tools.spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref +from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.spdx_document import SpdxDocument +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.actor import ActorType +from spdx_tools.spdx.model.document import CreationInfo as Spdx2_CreationInfo def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload) -> SpdxDocument: diff --git a/src/spdx3/bump_from_spdx2/external_document_ref.py b/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py similarity index 65% rename from src/spdx3/bump_from_spdx2/external_document_ref.py rename to src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py index 89dd4cecc..b17b41f34 100644 --- a/src/spdx3/bump_from_spdx2/external_document_ref.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py @@ -3,10 +3,10 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List -from spdx3.bump_from_spdx2.checksum import bump_checksum -from spdx3.model.external_map import ExternalMap -from spdx3.model.hash import Hash -from spdx.model.external_document_ref import ExternalDocumentRef +from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.model.hash import Hash +from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef def bump_external_document_ref(external_document_ref: ExternalDocumentRef) -> ExternalMap: diff --git a/src/spdx3/bump_from_spdx2/file.py b/src/spdx_tools/spdx3/bump_from_spdx2/file.py similarity index 74% rename from src/spdx3/bump_from_spdx2/file.py rename to src/spdx_tools/spdx3/bump_from_spdx2/file.py index eee707ba1..55ed3438a 100644 --- a/src/spdx3/bump_from_spdx2/file.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/file.py @@ -1,12 +1,12 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from spdx3.bump_from_spdx2.checksum import bump_checksum -from spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx3.model.creation_information import CreationInformation -from spdx3.model.software.file import File -from spdx3.payload import Payload -from spdx.model.file import File as Spdx2_File +from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.software.file import File +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.file import File as Spdx2_File def bump_file( diff --git a/src/spdx3/bump_from_spdx2/message.py b/src/spdx_tools/spdx3/bump_from_spdx2/message.py similarity index 100% rename from src/spdx3/bump_from_spdx2/message.py rename to src/spdx_tools/spdx3/bump_from_spdx2/message.py diff --git a/src/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py similarity index 84% rename from src/spdx3/bump_from_spdx2/package.py rename to src/spdx_tools/spdx3/bump_from_spdx2/package.py index 2b920b40a..2b3736481 100644 --- a/src/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -3,18 +3,18 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Union -from spdx3.bump_from_spdx2.actor import bump_actor -from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none -from spdx3.bump_from_spdx2.checksum import bump_checksum -from spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType -from spdx3.model.external_reference import ExternalReference, ExternalReferenceType -from spdx3.model.software.package import Package -from spdx3.model.software.software_purpose import SoftwarePurpose -from spdx3.payload import Payload -from spdx.model.package import ExternalPackageRef -from spdx.model.package import Package as Spdx2_Package +from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor +from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none +from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx_tools.spdx3.model.external_reference import ExternalReference, ExternalReferenceType +from spdx_tools.spdx3.model.software.package import Package +from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.package import ExternalPackageRef +from spdx_tools.spdx.model.package import Package as Spdx2_Package def bump_package( diff --git a/src/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py similarity index 84% rename from src/spdx3/bump_from_spdx2/relationship.py rename to src/spdx_tools/spdx3/bump_from_spdx2/relationship.py index 42913ee0d..aa42c6a4b 100644 --- a/src/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -3,13 +3,13 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Optional, Tuple -from spdx3.model.creation_information import CreationInformation -from spdx3.model.relationship import Relationship, RelationshipCompleteness, RelationshipType -from spdx3.payload import Payload -from spdx.model.relationship import Relationship as Spdx2_Relationship -from spdx.model.relationship import RelationshipType as Spdx2_RelationshipType -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.relationship import Relationship, RelationshipCompleteness, RelationshipType +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.relationship import Relationship as Spdx2_Relationship +from spdx_tools.spdx.model.relationship import RelationshipType as Spdx2_RelationshipType +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone def bump_relationship( diff --git a/src/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py similarity index 77% rename from src/spdx3/bump_from_spdx2/snippet.py rename to src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index e05b187da..5f2ae554b 100644 --- a/src/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -1,11 +1,11 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx3.model.creation_information import CreationInformation -from spdx3.model.software.snippet import Snippet -from spdx3.payload import Payload -from spdx.model.snippet import Snippet as Spdx2_Snippet +from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.software.snippet import Snippet +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet def bump_snippet( diff --git a/src/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py similarity index 70% rename from src/spdx3/bump_from_spdx2/spdx_document.py rename to src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py index 4a4544895..5a3c0a3ea 100644 --- a/src/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py @@ -1,16 +1,16 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from spdx3.bump_from_spdx2.annotation import bump_annotation -from spdx3.bump_from_spdx2.creation_information import bump_creation_information -from spdx3.bump_from_spdx2.file import bump_file -from spdx3.bump_from_spdx2.package import bump_package -from spdx3.bump_from_spdx2.relationship import bump_relationship -from spdx3.bump_from_spdx2.snippet import bump_snippet -from spdx3.model.creation_information import CreationInformation -from spdx3.model.spdx_document import SpdxDocument -from spdx3.payload import Payload -from spdx.model.document import Document as Spdx2_Document +from spdx_tools.spdx3.bump_from_spdx2.annotation import bump_annotation +from spdx_tools.spdx3.bump_from_spdx2.creation_information import bump_creation_information +from spdx_tools.spdx3.bump_from_spdx2.file import bump_file +from spdx_tools.spdx3.bump_from_spdx2.package import bump_package +from spdx_tools.spdx3.bump_from_spdx2.relationship import bump_relationship +from spdx_tools.spdx3.bump_from_spdx2.snippet import bump_snippet +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.spdx_document import SpdxDocument +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.document import Document as Spdx2_Document """ We want to implement a bump_from_spdx2 from the data model in src.spdx to the data model in src.spdx3. As there are many fundamental differences between these version we want each bump_from_spdx2 method to take diff --git a/src/spdx3/clitools/__init__.py b/src/spdx_tools/spdx3/clitools/__init__.py similarity index 100% rename from src/spdx3/clitools/__init__.py rename to src/spdx_tools/spdx3/clitools/__init__.py diff --git a/src/spdx3/clitools/pyspdxtools3.py b/src/spdx_tools/spdx3/clitools/pyspdxtools3.py similarity index 79% rename from src/spdx3/clitools/pyspdxtools3.py rename to src/spdx_tools/spdx3/clitools/pyspdxtools3.py index 20faeb5c4..f5b00c6e1 100644 --- a/src/spdx3/clitools/pyspdxtools3.py +++ b/src/spdx_tools/spdx3/clitools/pyspdxtools3.py @@ -6,13 +6,13 @@ import click -from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document -from spdx3.payload import Payload -from spdx3.writer.console.payload_writer import write_payload -from spdx.model.document import Document -from spdx.parser.parse_anything import parse_file -from spdx.validation.document_validator import validate_full_spdx_document -from spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx3.writer.console.payload_writer import write_payload +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.parser.parse_anything import parse_file +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage @click.command() diff --git a/src/spdx3/model/__init__.py b/src/spdx_tools/spdx3/model/__init__.py similarity index 100% rename from src/spdx3/model/__init__.py rename to src/spdx_tools/spdx3/model/__init__.py diff --git a/src/spdx3/model/agent.py b/src/spdx_tools/spdx3/model/agent.py similarity index 65% rename from src/spdx3/model/agent.py rename to src/spdx_tools/spdx3/model/agent.py index 2eec0b1c1..2aa29b783 100644 --- a/src/spdx3/model/agent.py +++ b/src/spdx_tools/spdx3/model/agent.py @@ -3,13 +3,13 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.creation_information import CreationInformation -from spdx3.model.element import Element -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.element import Element +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod @dataclass_with_properties diff --git a/src/spdx3/model/annotation.py b/src/spdx_tools/spdx3/model/annotation.py similarity index 73% rename from src/spdx3/model/annotation.py rename to src/spdx_tools/spdx3/model/annotation.py index 0e9132395..925233871 100644 --- a/src/spdx3/model/annotation.py +++ b/src/spdx_tools/spdx3/model/annotation.py @@ -4,13 +4,13 @@ from enum import Enum, auto from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.creation_information import CreationInformation -from spdx3.model.element import Element -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.element import Element +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod class AnnotationType(Enum): diff --git a/src/spdx3/model/artifact.py b/src/spdx_tools/spdx3/model/artifact.py similarity index 70% rename from src/spdx3/model/artifact.py rename to src/spdx_tools/spdx3/model/artifact.py index 8e4555a0f..b3270dc1e 100644 --- a/src/spdx3/model/artifact.py +++ b/src/spdx_tools/spdx3/model/artifact.py @@ -4,8 +4,8 @@ from abc import abstractmethod from typing import Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.element import Element +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model.element import Element @dataclass_with_properties diff --git a/src/spdx3/model/bom.py b/src/spdx_tools/spdx3/model/bom.py similarity index 69% rename from src/spdx3/model/bom.py rename to src/spdx_tools/spdx3/model/bom.py index cf1ff35f1..1fc2d57d6 100644 --- a/src/spdx3/model/bom.py +++ b/src/spdx_tools/spdx3/model/bom.py @@ -3,15 +3,15 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.bundle import Bundle -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_map import ExternalMap -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod -from spdx3.model.namespace_map import NamespaceMap +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.bundle import Bundle +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model.namespace_map import NamespaceMap @dataclass_with_properties diff --git a/src/spdx3/model/bundle.py b/src/spdx_tools/spdx3/model/bundle.py similarity index 67% rename from src/spdx3/model/bundle.py rename to src/spdx_tools/spdx3/model/bundle.py index ec531c9ad..9b0aedf48 100644 --- a/src/spdx3/model/bundle.py +++ b/src/spdx_tools/spdx3/model/bundle.py @@ -3,15 +3,15 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_map import ExternalMap -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod -from spdx3.model.namespace_map import NamespaceMap -from spdx3.model.spdx_collection import SpdxCollection +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model.namespace_map import NamespaceMap +from spdx_tools.spdx3.model.spdx_collection import SpdxCollection @dataclass_with_properties diff --git a/src/spdx3/model/creation_information.py b/src/spdx_tools/spdx3/model/creation_information.py similarity index 83% rename from src/spdx3/model/creation_information.py rename to src/spdx_tools/spdx3/model/creation_information.py index cdffd4b13..bac8c83f5 100644 --- a/src/spdx3/model/creation_information.py +++ b/src/spdx_tools/spdx3/model/creation_information.py @@ -6,8 +6,8 @@ from semantic_version import Version -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values @dataclass_with_properties diff --git a/src/spdx3/model/element.py b/src/spdx_tools/spdx3/model/element.py similarity index 68% rename from src/spdx3/model/element.py rename to src/spdx_tools/spdx3/model/element.py index 50333d0ee..25ac72373 100644 --- a/src/spdx3/model/element.py +++ b/src/spdx_tools/spdx3/model/element.py @@ -5,11 +5,11 @@ from dataclasses import field from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod @dataclass_with_properties diff --git a/src/spdx3/model/external_identifier.py b/src/spdx_tools/spdx3/model/external_identifier.py similarity index 81% rename from src/spdx3/model/external_identifier.py rename to src/spdx_tools/spdx3/model/external_identifier.py index 31b39db98..9131bd888 100644 --- a/src/spdx3/model/external_identifier.py +++ b/src/spdx_tools/spdx3/model/external_identifier.py @@ -4,8 +4,8 @@ from enum import Enum, auto from typing import Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values class ExternalIdentifierType(Enum): diff --git a/src/spdx3/model/external_map.py b/src/spdx_tools/spdx3/model/external_map.py similarity index 74% rename from src/spdx3/model/external_map.py rename to src/spdx_tools/spdx3/model/external_map.py index 34b6542ca..ec4d7d979 100644 --- a/src/spdx3/model/external_map.py +++ b/src/spdx_tools/spdx3/model/external_map.py @@ -4,9 +4,9 @@ from dataclasses import field from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod @dataclass_with_properties diff --git a/src/spdx3/model/external_reference.py b/src/spdx_tools/spdx3/model/external_reference.py similarity index 85% rename from src/spdx3/model/external_reference.py rename to src/spdx_tools/spdx3/model/external_reference.py index 9b574b30e..e1732ab33 100644 --- a/src/spdx3/model/external_reference.py +++ b/src/spdx_tools/spdx3/model/external_reference.py @@ -5,8 +5,8 @@ from enum import Enum, auto from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values class ExternalReferenceType(Enum): diff --git a/src/spdx3/model/hash.py b/src/spdx_tools/spdx3/model/hash.py similarity index 78% rename from src/spdx3/model/hash.py rename to src/spdx_tools/spdx3/model/hash.py index 153d2b9d1..5971bfb37 100644 --- a/src/spdx3/model/hash.py +++ b/src/spdx_tools/spdx3/model/hash.py @@ -4,9 +4,9 @@ from enum import Enum, auto from typing import Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod class HashAlgorithm(Enum): diff --git a/src/spdx3/model/integrity_method.py b/src/spdx_tools/spdx3/model/integrity_method.py similarity index 77% rename from src/spdx3/model/integrity_method.py rename to src/spdx_tools/spdx3/model/integrity_method.py index 8744c9c0a..aac00ab11 100644 --- a/src/spdx3/model/integrity_method.py +++ b/src/spdx_tools/spdx3/model/integrity_method.py @@ -4,7 +4,7 @@ from abc import ABC, abstractmethod from typing import Optional -from common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties @dataclass_with_properties diff --git a/src/spdx3/model/namespace_map.py b/src/spdx_tools/spdx3/model/namespace_map.py similarity index 70% rename from src/spdx3/model/namespace_map.py rename to src/spdx_tools/spdx3/model/namespace_map.py index 7452d7e50..e87f62810 100644 --- a/src/spdx3/model/namespace_map.py +++ b/src/spdx_tools/spdx3/model/namespace_map.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values @dataclass_with_properties diff --git a/src/spdx3/model/organization.py b/src/spdx_tools/spdx3/model/organization.py similarity index 66% rename from src/spdx3/model/organization.py rename to src/spdx_tools/spdx3/model/organization.py index 8c2a2e2e8..9a601c81a 100644 --- a/src/spdx3/model/organization.py +++ b/src/spdx_tools/spdx3/model/organization.py @@ -3,13 +3,13 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.agent import Agent -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.agent import Agent +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod @dataclass_with_properties diff --git a/src/spdx3/model/person.py b/src/spdx_tools/spdx3/model/person.py similarity index 66% rename from src/spdx3/model/person.py rename to src/spdx_tools/spdx3/model/person.py index 00f1fda5b..d69cba3a5 100644 --- a/src/spdx3/model/person.py +++ b/src/spdx_tools/spdx3/model/person.py @@ -3,13 +3,13 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.agent import Agent -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.agent import Agent +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod @dataclass_with_properties diff --git a/src/spdx3/model/profile_identifier.py b/src/spdx_tools/spdx3/model/profile_identifier.py similarity index 100% rename from src/spdx3/model/profile_identifier.py rename to src/spdx_tools/spdx3/model/profile_identifier.py diff --git a/src/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py similarity index 84% rename from src/spdx3/model/relationship.py rename to src/spdx_tools/spdx3/model/relationship.py index 7d103d8a6..88284c8cc 100644 --- a/src/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -4,13 +4,13 @@ from enum import Enum, auto from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.creation_information import CreationInformation -from spdx3.model.element import Element -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.element import Element +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod class RelationshipType(Enum): diff --git a/src/spdx3/model/software/__init__.py b/src/spdx_tools/spdx3/model/software/__init__.py similarity index 100% rename from src/spdx3/model/software/__init__.py rename to src/spdx_tools/spdx3/model/software/__init__.py diff --git a/src/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py similarity index 71% rename from src/spdx3/model/software/file.py rename to src/spdx_tools/spdx3/model/software/file.py index 4dec4fb90..1b8afbe96 100644 --- a/src/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -3,14 +3,14 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.artifact import Artifact -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod -from spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.artifact import Artifact +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose @dataclass_with_properties diff --git a/src/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py similarity index 75% rename from src/spdx3/model/software/package.py rename to src/spdx_tools/spdx3/model/software/package.py index 587fc70e4..c68df220e 100644 --- a/src/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -3,14 +3,14 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.artifact import Artifact -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod -from spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.artifact import Artifact +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose @dataclass_with_properties diff --git a/src/spdx3/model/software/sbom.py b/src/spdx_tools/spdx3/model/software/sbom.py similarity index 69% rename from src/spdx3/model/software/sbom.py rename to src/spdx_tools/spdx3/model/software/sbom.py index 305c6112f..8cafed690 100644 --- a/src/spdx3/model/software/sbom.py +++ b/src/spdx_tools/spdx3/model/software/sbom.py @@ -3,15 +3,15 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.bom import Bom -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_map import ExternalMap -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod -from spdx3.model.namespace_map import NamespaceMap +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.bom import Bom +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model.namespace_map import NamespaceMap @dataclass_with_properties diff --git a/src/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py similarity index 72% rename from src/spdx3/model/software/snippet.py rename to src/spdx_tools/spdx3/model/software/snippet.py index 6f9f3238e..81b886873 100644 --- a/src/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -3,14 +3,14 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional, Tuple -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.artifact import Artifact -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod -from spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.artifact import Artifact +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose @dataclass_with_properties diff --git a/src/spdx3/model/software/software_purpose.py b/src/spdx_tools/spdx3/model/software/software_purpose.py similarity index 100% rename from src/spdx3/model/software/software_purpose.py rename to src/spdx_tools/spdx3/model/software/software_purpose.py diff --git a/src/spdx3/model/software_agent.py b/src/spdx_tools/spdx3/model/software_agent.py similarity index 66% rename from src/spdx3/model/software_agent.py rename to src/spdx_tools/spdx3/model/software_agent.py index 1d6b62f7e..d3a6c05f1 100644 --- a/src/spdx3/model/software_agent.py +++ b/src/spdx_tools/spdx3/model/software_agent.py @@ -3,13 +3,13 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.agent import Agent -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.agent import Agent +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod @dataclass_with_properties diff --git a/src/spdx3/model/spdx_collection.py b/src/spdx_tools/spdx3/model/spdx_collection.py similarity index 73% rename from src/spdx3/model/spdx_collection.py rename to src/spdx_tools/spdx3/model/spdx_collection.py index d1c4676cb..d6a9bdcda 100644 --- a/src/spdx3/model/spdx_collection.py +++ b/src/spdx_tools/spdx3/model/spdx_collection.py @@ -5,10 +5,10 @@ from dataclasses import field from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from spdx3.model.element import Element -from spdx3.model.external_map import ExternalMap -from spdx3.model.namespace_map import NamespaceMap +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model.element import Element +from spdx_tools.spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.model.namespace_map import NamespaceMap @dataclass_with_properties diff --git a/src/spdx3/model/spdx_document.py b/src/spdx_tools/spdx3/model/spdx_document.py similarity index 70% rename from src/spdx3/model/spdx_document.py rename to src/spdx_tools/spdx3/model/spdx_document.py index 0562a2fb6..8c1a1bdf6 100644 --- a/src/spdx3/model/spdx_document.py +++ b/src/spdx_tools/spdx3/model/spdx_document.py @@ -3,15 +3,15 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.bundle import Bundle -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_map import ExternalMap -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod -from spdx3.model.namespace_map import NamespaceMap +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.bundle import Bundle +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model.namespace_map import NamespaceMap @dataclass_with_properties diff --git a/src/spdx3/model/tool.py b/src/spdx_tools/spdx3/model/tool.py similarity index 65% rename from src/spdx3/model/tool.py rename to src/spdx_tools/spdx3/model/tool.py index d65fd1a35..8a10fbdd3 100644 --- a/src/spdx3/model/tool.py +++ b/src/spdx_tools/spdx3/model/tool.py @@ -3,13 +3,13 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List, Optional -from common.typing.dataclass_with_properties import dataclass_with_properties -from common.typing.type_checks import check_types_and_set_values -from spdx3.model.creation_information import CreationInformation -from spdx3.model.element import Element -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.model.external_reference import ExternalReference -from spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.element import Element +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod @dataclass_with_properties diff --git a/src/spdx3/payload.py b/src/spdx_tools/spdx3/payload.py similarity index 91% rename from src/spdx3/payload.py rename to src/spdx_tools/spdx3/payload.py index ff4aea6aa..b28e90a9e 100644 --- a/src/spdx3/payload.py +++ b/src/spdx_tools/spdx3/payload.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Dict -from spdx3.model.element import Element +from spdx_tools.spdx3.model.element import Element class Payload: diff --git a/src/spdx3/writer/console/software/__init__.py b/src/spdx_tools/spdx3/writer/__init__.py similarity index 100% rename from src/spdx3/writer/console/software/__init__.py rename to src/spdx_tools/spdx3/writer/__init__.py diff --git a/src/spdx_tools/spdx3/writer/console/__init__.py b/src/spdx_tools/spdx3/writer/console/__init__.py new file mode 100644 index 000000000..7c191400b --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/__init__.py @@ -0,0 +1,2 @@ +""" This is a temporary package to write the implemented model of spdx_tools.spdx3.0 to console. As soon as + serialization formats are properly defined this package can be deleted.""" diff --git a/src/spdx3/writer/console/agent_writer.py b/src/spdx_tools/spdx3/writer/console/agent_writer.py similarity index 63% rename from src/spdx3/writer/console/agent_writer.py rename to src/spdx_tools/spdx3/writer/console/agent_writer.py index a906a8df5..58f36abfb 100644 --- a/src/spdx3/writer/console/agent_writer.py +++ b/src/spdx_tools/spdx3/writer/console/agent_writer.py @@ -3,11 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.agent import Agent -from spdx3.model.organization import Organization -from spdx3.model.person import Person -from spdx3.model.software_agent import SoftwareAgent -from spdx3.writer.console.element_writer import write_element_properties +from spdx_tools.spdx3.model.agent import Agent +from spdx_tools.spdx3.model.organization import Organization +from spdx_tools.spdx3.model.person import Person +from spdx_tools.spdx3.model.software_agent import SoftwareAgent +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties def write_agent(agent: Agent, text_output: TextIO, heading: bool = True): diff --git a/src/spdx3/writer/console/annotation_writer.py b/src/spdx_tools/spdx3/writer/console/annotation_writer.py similarity index 73% rename from src/spdx3/writer/console/annotation_writer.py rename to src/spdx_tools/spdx3/writer/console/annotation_writer.py index 92d56cc67..92d474a72 100644 --- a/src/spdx3/writer/console/annotation_writer.py +++ b/src/spdx_tools/spdx3/writer/console/annotation_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.annotation import Annotation -from spdx3.writer.console.console import write_value -from spdx3.writer.console.element_writer import write_element_properties +from spdx_tools.spdx3.model.annotation import Annotation +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties def write_annotation(annotation: Annotation, text_output: TextIO): diff --git a/src/spdx3/writer/console/artifact_writer.py b/src/spdx_tools/spdx3/writer/console/artifact_writer.py similarity index 60% rename from src/spdx3/writer/console/artifact_writer.py rename to src/spdx_tools/spdx3/writer/console/artifact_writer.py index 7e47d587f..5c1532dd6 100644 --- a/src/spdx3/writer/console/artifact_writer.py +++ b/src/spdx_tools/spdx3/writer/console/artifact_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.artifact import Artifact -from spdx3.writer.console.console import write_value -from spdx3.writer.console.element_writer import write_element_properties +from spdx_tools.spdx3.model.artifact import Artifact +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties def write_artifact_properties(artifact: Artifact, text_output: TextIO): diff --git a/src/spdx3/writer/console/bom_writer.py b/src/spdx_tools/spdx3/writer/console/bom_writer.py similarity index 71% rename from src/spdx3/writer/console/bom_writer.py rename to src/spdx_tools/spdx3/writer/console/bom_writer.py index 7e019eacc..229e95005 100644 --- a/src/spdx3/writer/console/bom_writer.py +++ b/src/spdx_tools/spdx3/writer/console/bom_writer.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.bom import Bom -from spdx3.writer.console.bundle_writer import write_bundle +from spdx_tools.spdx3.model.bom import Bom +from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle def write_bom(bom: Bom, text_output: TextIO, heading: bool = True): diff --git a/src/spdx3/writer/console/bundle_writer.py b/src/spdx_tools/spdx3/writer/console/bundle_writer.py similarity index 63% rename from src/spdx3/writer/console/bundle_writer.py rename to src/spdx_tools/spdx3/writer/console/bundle_writer.py index 20818e40e..8c0384383 100644 --- a/src/spdx3/writer/console/bundle_writer.py +++ b/src/spdx_tools/spdx3/writer/console/bundle_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.bundle import Bundle -from spdx3.writer.console.console import write_value -from spdx3.writer.console.spdx_collection_writer import write_collection +from spdx_tools.spdx3.model.bundle import Bundle +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.spdx_collection_writer import write_collection def write_bundle(bundle: Bundle, text_output: TextIO, heading: bool = True): diff --git a/src/spdx3/writer/console/console.py b/src/spdx_tools/spdx3/writer/console/console.py similarity index 68% rename from src/spdx3/writer/console/console.py rename to src/spdx_tools/spdx3/writer/console/console.py index fd434e796..4cb90b344 100644 --- a/src/spdx3/writer/console/console.py +++ b/src/spdx_tools/spdx3/writer/console/console.py @@ -6,8 +6,8 @@ def write_value(tag: str, value: Optional[Union[bool, str]], out: TextIO, indent: bool = False): - """This function is duplicated from spdx.writer.tagvalue.tag_value_writer_helper_functions and slightly adapted to - make indentation of output possible.""" + """This function is duplicated from spdx_tools.spdx.writer.tagvalue.tag_value_writer_helper_functions + and slightly adapted to make indentation of output possible.""" if not value: return if indent: diff --git a/src/spdx3/writer/console/creation_information_writer.py b/src/spdx_tools/spdx3/writer/console/creation_information_writer.py similarity index 81% rename from src/spdx3/writer/console/creation_information_writer.py rename to src/spdx_tools/spdx3/writer/console/creation_information_writer.py index f7790eeed..3c1a2b076 100644 --- a/src/spdx3/writer/console/creation_information_writer.py +++ b/src/spdx_tools/spdx3/writer/console/creation_information_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.creation_information import CreationInformation -from spdx3.writer.console.console import write_value -from spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string def write_creation_info(creation_info: CreationInformation, text_output: TextIO, indent: bool = True): diff --git a/src/spdx3/writer/console/element_writer.py b/src/spdx_tools/spdx3/writer/console/element_writer.py similarity index 71% rename from src/spdx3/writer/console/element_writer.py rename to src/spdx_tools/spdx3/writer/console/element_writer.py index afc91ccdc..14b814584 100644 --- a/src/spdx3/writer/console/element_writer.py +++ b/src/spdx_tools/spdx3/writer/console/element_writer.py @@ -3,13 +3,13 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.element import Element -from spdx3.writer.console.console import write_value -from spdx3.writer.console.creation_information_writer import write_creation_info -from spdx3.writer.console.external_identifier_writer import write_external_identifier -from spdx3.writer.console.external_reference_writer import write_external_reference -from spdx3.writer.console.hash_writer import write_hash -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading +from spdx_tools.spdx3.model.element import Element +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.creation_information_writer import write_creation_info +from spdx_tools.spdx3.writer.console.external_identifier_writer import write_external_identifier +from spdx_tools.spdx3.writer.console.external_reference_writer import write_external_reference +from spdx_tools.spdx3.writer.console.hash_writer import write_hash +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading def write_element_properties(element: Element, text_output: TextIO): diff --git a/src/spdx3/writer/console/external_identifier_writer.py b/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py similarity index 76% rename from src/spdx3/writer/console/external_identifier_writer.py rename to src/spdx_tools/spdx3/writer/console/external_identifier_writer.py index 120b783ad..f2d2db59e 100644 --- a/src/spdx3/writer/console/external_identifier_writer.py +++ b/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.external_identifier import ExternalIdentifier -from spdx3.writer.console.console import write_value +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.writer.console.console import write_value def write_external_identifier(external_identifier: ExternalIdentifier, text_output: TextIO): diff --git a/src/spdx3/writer/console/external_map_writer.py b/src/spdx_tools/spdx3/writer/console/external_map_writer.py similarity index 73% rename from src/spdx3/writer/console/external_map_writer.py rename to src/spdx_tools/spdx3/writer/console/external_map_writer.py index c4dacc58b..75ab4f4a6 100644 --- a/src/spdx3/writer/console/external_map_writer.py +++ b/src/spdx_tools/spdx3/writer/console/external_map_writer.py @@ -3,10 +3,10 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.external_map import ExternalMap -from spdx3.writer.console.console import write_value -from spdx3.writer.console.hash_writer import write_hash -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading +from spdx_tools.spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.hash_writer import write_hash +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading def write_external_map(external_map: ExternalMap, text_output: TextIO): diff --git a/src/spdx3/writer/console/external_reference_writer.py b/src/spdx_tools/spdx3/writer/console/external_reference_writer.py similarity index 79% rename from src/spdx3/writer/console/external_reference_writer.py rename to src/spdx_tools/spdx3/writer/console/external_reference_writer.py index c0fb4d93c..fd1e21293 100644 --- a/src/spdx3/writer/console/external_reference_writer.py +++ b/src/spdx_tools/spdx3/writer/console/external_reference_writer.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.external_reference import ExternalReference -from spdx3.writer.console.console import write_value +from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.writer.console.console import write_value def write_external_reference(external_reference: ExternalReference, text_output: TextIO): diff --git a/src/spdx3/writer/console/hash_writer.py b/src/spdx_tools/spdx3/writer/console/hash_writer.py similarity index 70% rename from src/spdx3/writer/console/hash_writer.py rename to src/spdx_tools/spdx3/writer/console/hash_writer.py index 420d32e9f..a1e56b71a 100644 --- a/src/spdx3/writer/console/hash_writer.py +++ b/src/spdx_tools/spdx3/writer/console/hash_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.hash import Hash -from spdx3.writer.console.console import write_value -from spdx3.writer.console.integrity_method_writer import write_integrity_method +from spdx_tools.spdx3.model.hash import Hash +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.integrity_method_writer import write_integrity_method def write_hash(hash_object: Hash, text_output: TextIO, heading: bool, indent: bool = True): diff --git a/src/spdx3/writer/console/integrity_method_writer.py b/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py similarity index 69% rename from src/spdx3/writer/console/integrity_method_writer.py rename to src/spdx_tools/spdx3/writer/console/integrity_method_writer.py index 315952898..14b61b497 100644 --- a/src/spdx3/writer/console/integrity_method_writer.py +++ b/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.integrity_method import IntegrityMethod -from spdx3.writer.console.console import write_value +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.writer.console.console import write_value def write_integrity_method(integrity_method: IntegrityMethod, text_output: TextIO, indent: bool = True): diff --git a/src/spdx3/writer/console/namespace_map_writer.py b/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py similarity index 71% rename from src/spdx3/writer/console/namespace_map_writer.py rename to src/spdx_tools/spdx3/writer/console/namespace_map_writer.py index 5ff609eeb..4fbada5b3 100644 --- a/src/spdx3/writer/console/namespace_map_writer.py +++ b/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.namespace_map import NamespaceMap -from spdx3.writer.console.console import write_value +from spdx_tools.spdx3.model.namespace_map import NamespaceMap +from spdx_tools.spdx3.writer.console.console import write_value def write_namespace_map(namespace_map: NamespaceMap, text_output: TextIO): diff --git a/src/spdx_tools/spdx3/writer/console/payload_writer.py b/src/spdx_tools/spdx3/writer/console/payload_writer.py new file mode 100644 index 000000000..59ce9b01e --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/payload_writer.py @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import TextIO + +from spdx_tools.spdx3.model.annotation import Annotation +from spdx_tools.spdx3.model.bom import Bom +from spdx_tools.spdx3.model.bundle import Bundle +from spdx_tools.spdx3.model.organization import Organization +from spdx_tools.spdx3.model.person import Person +from spdx_tools.spdx3.model.relationship import Relationship +from spdx_tools.spdx3.model.software.file import File +from spdx_tools.spdx3.model.software.package import Package +from spdx_tools.spdx3.model.software.sbom import Sbom +from spdx_tools.spdx3.model.software.snippet import Snippet +from spdx_tools.spdx3.model.software_agent import SoftwareAgent +from spdx_tools.spdx3.model.spdx_document import SpdxDocument +from spdx_tools.spdx3.model.tool import Tool +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx3.writer.console.agent_writer import write_agent +from spdx_tools.spdx3.writer.console.annotation_writer import write_annotation +from spdx_tools.spdx3.writer.console.bom_writer import write_bom +from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle +from spdx_tools.spdx3.writer.console.relationship_writer import write_relationship +from spdx_tools.spdx3.writer.console.software.file_writer import write_file +from spdx_tools.spdx3.writer.console.software.package_writer import write_package +from spdx_tools.spdx3.writer.console.software.sbom_writer import write_sbom +from spdx_tools.spdx3.writer.console.software.snippet_writer import write_snippet +from spdx_tools.spdx3.writer.console.spdx_document_writer import write_spdx_document +from spdx_tools.spdx3.writer.console.tool_writer import write_tool + +MAP_CLASS_TO_WRITE_METHOD = { + Annotation: write_annotation, + Relationship: write_relationship, + Bundle: write_bundle, + SpdxDocument: write_spdx_document, + Bom: write_bom, + File: write_file, + Package: write_package, + Snippet: write_snippet, + Sbom: write_sbom, + Person: write_agent, + Organization: write_agent, + SoftwareAgent: write_agent, + Tool: write_tool, +} + + +def write_payload(payload: Payload, text_output: TextIO): + for element in payload.get_full_map().values(): + write_method = MAP_CLASS_TO_WRITE_METHOD[type(element)] + write_method(element, text_output) + text_output.write("\n") diff --git a/src/spdx3/writer/console/relationship_writer.py b/src/spdx_tools/spdx3/writer/console/relationship_writer.py similarity index 75% rename from src/spdx3/writer/console/relationship_writer.py rename to src/spdx_tools/spdx3/writer/console/relationship_writer.py index b83aaa919..7944e2090 100644 --- a/src/spdx3/writer/console/relationship_writer.py +++ b/src/spdx_tools/spdx3/writer/console/relationship_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.relationship import Relationship -from spdx3.writer.console.console import write_value -from spdx3.writer.console.element_writer import write_element_properties +from spdx_tools.spdx3.model.relationship import Relationship +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties def write_relationship(relationship: Relationship, text_output: TextIO): diff --git a/src/spdx_tools/spdx3/writer/console/software/__init__.py b/src/spdx_tools/spdx3/writer/console/software/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx3/writer/console/software/file_writer.py b/src/spdx_tools/spdx3/writer/console/software/file_writer.py similarity index 70% rename from src/spdx3/writer/console/software/file_writer.py rename to src/spdx_tools/spdx3/writer/console/software/file_writer.py index 3e7e4937d..9257a0612 100644 --- a/src/spdx3/writer/console/software/file_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/file_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.software.file import File -from spdx3.writer.console.artifact_writer import write_artifact_properties -from spdx3.writer.console.console import write_value +from spdx_tools.spdx3.model.software.file import File +from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties +from spdx_tools.spdx3.writer.console.console import write_value def write_file(file: File, text_output: TextIO): diff --git a/src/spdx3/writer/console/software/package_writer.py b/src/spdx_tools/spdx3/writer/console/software/package_writer.py similarity index 77% rename from src/spdx3/writer/console/software/package_writer.py rename to src/spdx_tools/spdx3/writer/console/software/package_writer.py index a422d18d4..4af2f5b4c 100644 --- a/src/spdx3/writer/console/software/package_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/package_writer.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.software.package import Package -from spdx3.writer.console.artifact_writer import write_artifact_properties -from spdx3.writer.console.console import write_value +from spdx_tools.spdx3.model.software.package import Package +from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties +from spdx_tools.spdx3.writer.console.console import write_value def write_package(package: Package, text_output: TextIO): diff --git a/src/spdx3/writer/console/software/sbom_writer.py b/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py similarity index 67% rename from src/spdx3/writer/console/software/sbom_writer.py rename to src/spdx_tools/spdx3/writer/console/software/sbom_writer.py index 30f42a426..83a5b7956 100644 --- a/src/spdx3/writer/console/software/sbom_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.software.sbom import Sbom -from spdx3.writer.console.bom_writer import write_bom +from spdx_tools.spdx3.model.software.sbom import Sbom +from spdx_tools.spdx3.writer.console.bom_writer import write_bom def write_sbom(sbom: Sbom, text_output: TextIO): diff --git a/src/spdx3/writer/console/software/snippet_writer.py b/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py similarity index 66% rename from src/spdx3/writer/console/software/snippet_writer.py rename to src/spdx_tools/spdx3/writer/console/software/snippet_writer.py index 143dcd257..22415ee53 100644 --- a/src/spdx3/writer/console/software/snippet_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py @@ -3,10 +3,10 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.software.snippet import Snippet -from spdx3.writer.console.artifact_writer import write_artifact_properties -from spdx3.writer.console.console import write_value -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range +from spdx_tools.spdx3.model.software.snippet import Snippet +from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range def write_snippet(snippet: Snippet, text_output: TextIO): diff --git a/src/spdx3/writer/console/spdx_collection_writer.py b/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py similarity index 61% rename from src/spdx3/writer/console/spdx_collection_writer.py rename to src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py index 72d763d56..96461c09c 100644 --- a/src/spdx3/writer/console/spdx_collection_writer.py +++ b/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py @@ -3,11 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.spdx_collection import SpdxCollection -from spdx3.writer.console.element_writer import write_element_properties -from spdx3.writer.console.external_map_writer import write_external_map -from spdx3.writer.console.namespace_map_writer import write_namespace_map -from spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading +from spdx_tools.spdx3.model.spdx_collection import SpdxCollection +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties +from spdx_tools.spdx3.writer.console.external_map_writer import write_external_map +from spdx_tools.spdx3.writer.console.namespace_map_writer import write_namespace_map +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading def write_collection(collection: SpdxCollection, text_output: TextIO): diff --git a/src/spdx3/writer/console/spdx_document_writer.py b/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py similarity index 68% rename from src/spdx3/writer/console/spdx_document_writer.py rename to src/spdx_tools/spdx3/writer/console/spdx_document_writer.py index 0f408e63e..426421753 100644 --- a/src/spdx3/writer/console/spdx_document_writer.py +++ b/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx3.model.spdx_document import SpdxDocument -from spdx3.writer.console.bundle_writer import write_bundle +from spdx_tools.spdx3.model.spdx_document import SpdxDocument +from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle def write_spdx_document(spdx_document: SpdxDocument, text_output: TextIO): diff --git a/src/spdx3/writer/console/tool_writer.py b/src/spdx_tools/spdx3/writer/console/tool_writer.py similarity index 85% rename from src/spdx3/writer/console/tool_writer.py rename to src/spdx_tools/spdx3/writer/console/tool_writer.py index 4f20e4df3..3b2ee1560 100644 --- a/src/spdx3/writer/console/tool_writer.py +++ b/src/spdx_tools/spdx3/writer/console/tool_writer.py @@ -10,8 +10,8 @@ # limitations under the License. from typing import TextIO -from spdx3.model.tool import Tool -from spdx3.writer.console.element_writer import write_element_properties +from spdx_tools.spdx3.model.tool import Tool +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties def write_tool(tool: Tool, text_output: TextIO, heading: bool = True): diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index a55ecf705..bc91d555b 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -6,14 +6,14 @@ import pytest from semantic_version import Version -from spdx3.bump_from_spdx2.actor import bump_actor -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType -from spdx3.model.organization import Organization -from spdx3.model.person import Person -from spdx3.model.tool import Tool -from spdx3.payload import Payload -from spdx.model.actor import Actor, ActorType +from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx_tools.spdx3.model.organization import Organization +from spdx_tools.spdx3.model.person import Person +from spdx_tools.spdx3.model.tool import Tool +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.actor import Actor, ActorType @pytest.mark.parametrize( diff --git a/tests/spdx3/bump/test_bump_utils.py b/tests/spdx3/bump/test_bump_utils.py index 6c33970bf..258ab19f9 100644 --- a/tests/spdx3/bump/test_bump_utils.py +++ b/tests/spdx3/bump/test_bump_utils.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none -from spdx.model.spdx_no_assertion import SpdxNoAssertion -from spdx.model.spdx_none import SpdxNone +from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none +from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion +from spdx_tools.spdx.model.spdx_none import SpdxNone @pytest.mark.parametrize( diff --git a/tests/spdx3/bump/test_checksum_bump.py b/tests/spdx3/bump/test_checksum_bump.py index 461b704b9..d1c167783 100644 --- a/tests/spdx3/bump/test_checksum_bump.py +++ b/tests/spdx3/bump/test_checksum_bump.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx3.bump_from_spdx2.checksum import bump_checksum, convert_checksum_algorithm_to_hash_algorithm -from spdx3.model.hash import HashAlgorithm -from spdx.model.checksum import ChecksumAlgorithm +from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum, convert_checksum_algorithm_to_hash_algorithm +from spdx_tools.spdx3.model.hash import HashAlgorithm +from spdx_tools.spdx.model.checksum import ChecksumAlgorithm from tests.spdx.fixtures import checksum_fixture diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index 5c4193ddc..5ac6c7214 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -3,15 +3,15 @@ # SPDX-License-Identifier: Apache-2.0 from unittest import mock -from spdx3.bump_from_spdx2.file import bump_file -from spdx3.model.hash import Hash, HashAlgorithm -from spdx3.model.software.file import File -from spdx3.payload import Payload -from spdx.model.file import File as Spdx2_File +from spdx_tools.spdx3.bump_from_spdx2.file import bump_file +from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm +from spdx_tools.spdx3.model.software.file import File +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.file import File as Spdx2_File from tests.spdx.fixtures import file_fixture -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_bump_file(creation_information): payload = Payload() document_namespace = "https://doc.namespace" diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index bbfea0619..923fe6479 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -3,17 +3,17 @@ # SPDX-License-Identifier: Apache-2.0 from unittest import TestCase, mock -from spdx3.bump_from_spdx2.package import bump_package -from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType -from spdx3.model.external_reference import ExternalReference, ExternalReferenceType -from spdx3.model.software.package import Package -from spdx3.payload import Payload -from spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory -from spdx.model.package import Package as Spdx2_Package +from spdx_tools.spdx3.bump_from_spdx2.package import bump_package +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx_tools.spdx3.model.external_reference import ExternalReference, ExternalReferenceType +from spdx_tools.spdx3.model.software.package import Package +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory +from spdx_tools.spdx.model.package import Package as Spdx2_Package from tests.spdx.fixtures import package_fixture -@mock.patch("spdx3.model.creation_information.CreationInformation") +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation") def test_bump_package(creation_information): payload = Payload() document_namespace = "https://doc.namespace" @@ -45,7 +45,7 @@ def test_bump_package(creation_information): assert package.source_info == spdx2_package.source_info -@mock.patch("spdx3.model.creation_information.CreationInformation") +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation") def test_bump_of_single_purl_without_comment(creation_information): payload = Payload() document_namespace = "https://doc.namespace" @@ -64,7 +64,7 @@ def test_bump_of_single_purl_without_comment(creation_information): assert package.external_identifier == [] -@mock.patch("spdx3.model.creation_information.CreationInformation") +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation") def test_bump_of_single_purl_with_comment(creation_information): payload = Payload() document_namespace = "https://doc.namespace" @@ -85,7 +85,7 @@ def test_bump_of_single_purl_with_comment(creation_information): ] -@mock.patch("spdx3.model.creation_information.CreationInformation") +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation") def test_bump_of_multiple_purls(creation_information): payload = Payload() document_namespace = "https://doc.namespace" diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index bdc98cb63..fa2b88889 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -3,14 +3,14 @@ # SPDX-License-Identifier: Apache-2.0 from unittest import mock -from spdx3.bump_from_spdx2.snippet import bump_snippet -from spdx3.model.software.snippet import Snippet -from spdx3.payload import Payload -from spdx.model.snippet import Snippet as Spdx2_Snippet +from spdx_tools.spdx3.bump_from_spdx2.snippet import bump_snippet +from spdx_tools.spdx3.model.software.snippet import Snippet +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet from tests.spdx.fixtures import snippet_fixture -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_bump_snippet(creation_information): payload = Payload() document_namespace = "https://doc.namespace" diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index dc18a08b6..f6a1df4fb 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -3,11 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 import sys -from spdx3.bump_from_spdx2.spdx_document import bump_spdx_document -from spdx3.payload import Payload -from spdx3.writer.console.payload_writer import write_payload -from spdx.model.actor import ActorType -from spdx.model.document import Document as Spdx2_Document +from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx3.writer.console.payload_writer import write_payload +from spdx_tools.spdx.model.actor import ActorType +from spdx_tools.spdx.model.document import Document as Spdx2_Document from tests.spdx.fixtures import actor_fixture, annotation_fixture, creation_info_fixture, document_fixture diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index 2bed165c5..57247909f 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -5,11 +5,11 @@ import pytest -from spdx3.model.software.file import File -from spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.model.software.file import File +from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): file = File( "SPDXRef-File", @@ -27,7 +27,7 @@ def test_correct_initialization(creation_information): assert file.content_type == "MediaType" -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: File( @@ -43,10 +43,10 @@ def test_invalid_initialization(creation_information): 'SetterError File: type of argument "content_identifier" must be one of (str, ' "NoneType); got int instead: 3", 'SetterError File: type of argument "file_purpose" must be one of ' - "(List[spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got " - "spdx3.model.software.software_purpose.SoftwarePurpose instead: " + "(List[spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got " + "spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose instead: " "SoftwarePurpose.FILE", 'SetterError File: type of argument "content_type" must be one of (str, ' - "NoneType); got spdx3.model.software.software_purpose.SoftwarePurpose " + "NoneType); got spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose " "instead: SoftwarePurpose.ARCHIVE", ] diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 3f3b84a2e..fc9d9d0e9 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -5,11 +5,11 @@ import pytest -from spdx3.model.software.package import Package -from spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.model.software.package import Package +from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): package = Package( "SPDXRef-Package", @@ -34,7 +34,7 @@ def test_correct_initialization(creation_information): assert package.source_info == "some info" -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Package( @@ -53,8 +53,8 @@ def test_invalid_initialization(creation_information): 'SetterError Package: type of argument "content_identifier" must be one of ' "(str, NoneType); got int instead: 3", 'SetterError Package: type of argument "package_purpose" must be one of ' - "(List[spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got " - "spdx3.model.software.software_purpose.SoftwarePurpose instead: " + "(List[spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got " + "spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose instead: " "SoftwarePurpose.FILE", 'SetterError Package: type of argument "package_version" must be one of ' "(str, NoneType); got int instead: 42", diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index 033746980..d51ea3a8f 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -5,10 +5,10 @@ import pytest -from spdx3.model.software.sbom import Sbom +from spdx_tools.spdx3.model.software.sbom import Sbom -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): sbom = Sbom("SPDXRef-Sbom", creation_information, elements=["spdx_id1", "spdx_id2"], root_elements=["spdx_id3"]) @@ -25,6 +25,6 @@ def test_invalid_initialization(): assert err.value.args[0] == [ 'SetterError Sbom: type of argument "spdx_id" must be str; got int instead: 2', 'SetterError Sbom: type of argument "creation_info" must be ' - "spdx3.model.creation_information.CreationInformation; got dict instead: " + "spdx_tools.spdx3.model.creation_information.CreationInformation; got dict instead: " "{'creation_info': [3, 4, 5]}", ] diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index 16b116fa1..f7ff9f2b9 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -5,11 +5,11 @@ import pytest -from spdx3.model.software.snippet import Snippet -from spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.model.software.snippet import Snippet +from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose -@mock.patch("spdx3.model.software.snippet.Snippet", autospec=True) +@mock.patch("spdx_tools.spdx3.model.software.snippet.Snippet", autospec=True) def test_correct_initialization(creation_information): snippet = Snippet( "SPDXRef-Snippet", @@ -28,7 +28,7 @@ def test_correct_initialization(creation_information): assert snippet.line_range == (346, 456) -@mock.patch("spdx3.model.software.snippet.Snippet", autospec=True) +@mock.patch("spdx_tools.spdx3.model.software.snippet.Snippet", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Snippet(2, creation_information, originated_by=34, byte_range="34:45") diff --git a/tests/spdx3/model/test_abstract_classes.py b/tests/spdx3/model/test_abstract_classes.py index 5a5f72451..7eb583a28 100644 --- a/tests/spdx3/model/test_abstract_classes.py +++ b/tests/spdx3/model/test_abstract_classes.py @@ -3,10 +3,10 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx3.model.artifact import Artifact -from spdx3.model.element import Element -from spdx3.model.integrity_method import IntegrityMethod -from spdx3.model.spdx_collection import SpdxCollection +from spdx_tools.spdx3.model.artifact import Artifact +from spdx_tools.spdx3.model.element import Element +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model.spdx_collection import SpdxCollection @pytest.mark.parametrize("abstract_class", [Element, Artifact, SpdxCollection, IntegrityMethod]) diff --git a/tests/spdx3/model/test_agent.py b/tests/spdx3/model/test_agent.py index 86097e2c9..ec4cf8f00 100644 --- a/tests/spdx3/model/test_agent.py +++ b/tests/spdx3/model/test_agent.py @@ -6,12 +6,12 @@ import pytest from semantic_version import Version -from spdx3.model.agent import Agent -from spdx3.model.creation_information import CreationInformation -from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType -from spdx3.model.organization import Organization -from spdx3.model.person import Person -from spdx3.model.software_agent import SoftwareAgent +from spdx_tools.spdx3.model.agent import Agent +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx_tools.spdx3.model.organization import Organization +from spdx_tools.spdx3.model.person import Person +from spdx_tools.spdx3.model.software_agent import SoftwareAgent @pytest.mark.parametrize("agent_class", [Agent, Person, Organization, SoftwareAgent]) @@ -37,5 +37,5 @@ def test_invalid_initialization(agent_class): assert err.value.args[0] == [ f'SetterError {agent_class.__name__}: type of argument "spdx_id" must be str; got int instead: 12', f'SetterError {agent_class.__name__}: type of argument "creation_info" must be ' - "spdx3.model.creation_information.CreationInformation; got int instead: 345", + "spdx_tools.spdx3.model.creation_information.CreationInformation; got int instead: 345", ] diff --git a/tests/spdx3/model/test_annotation.py b/tests/spdx3/model/test_annotation.py index aaf60dd71..bd8019153 100644 --- a/tests/spdx3/model/test_annotation.py +++ b/tests/spdx3/model/test_annotation.py @@ -5,10 +5,10 @@ import pytest -from spdx3.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx3.model.annotation import Annotation, AnnotationType -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): annotation = Annotation( "SPDXRef-Annotation", @@ -27,7 +27,7 @@ def test_correct_initialization(creation_information): assert annotation.statement == "This is a statement" -@mock.patch("spdx3.model.creation_information.CreationInformation") +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation") def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Annotation( @@ -41,7 +41,7 @@ def test_invalid_initialization(creation_information): assert err.value.args[0] == [ 'SetterError Annotation: type of argument "annotation_type" must be ' - "spdx3.model.annotation.AnnotationType; got str instead: REVIEW", + "spdx_tools.spdx3.model.annotation.AnnotationType; got str instead: REVIEW", 'SetterError Annotation: type of argument "subject" must be str; got dict ' "instead: {'element': 1}", 'SetterError Annotation: type of argument "content_type" must be one of (str, ' "NoneType); got int instead: 4", diff --git a/tests/spdx3/model/test_bom.py b/tests/spdx3/model/test_bom.py index 3f8cfed86..8e93afeae 100644 --- a/tests/spdx3/model/test_bom.py +++ b/tests/spdx3/model/test_bom.py @@ -6,10 +6,10 @@ import pytest -from spdx3.model.bom import Bom +from spdx_tools.spdx3.model.bom import Bom -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): bom = Bom("SPDXRef-Bom", creation_information, elements=["spdx_id1"], root_elements=["spdx_id2"]) @@ -26,7 +26,7 @@ def test_invalid_initialization(): assert err.value.args[0] == [ 'SetterError Bom: type of argument "spdx_id" must be str; got int instead: 1', 'SetterError Bom: type of argument "creation_info" must be ' - "spdx3.model.creation_information.CreationInformation; got str instead: " + "spdx_tools.spdx3.model.creation_information.CreationInformation; got str instead: " "Creation Information", 'SetterError Bom: type of argument "elements"[0] must be ' "str; got int instead: [5]", ] diff --git a/tests/spdx3/model/test_bundle.py b/tests/spdx3/model/test_bundle.py index 336059f27..f5a4643c2 100644 --- a/tests/spdx3/model/test_bundle.py +++ b/tests/spdx3/model/test_bundle.py @@ -5,11 +5,11 @@ import pytest -from spdx3.model.bundle import Bundle +from spdx_tools.spdx3.model.bundle import Bundle -@mock.patch("spdx3.model.namespace_map.NamespaceMap", autospec=True) -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.namespace_map.NamespaceMap", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information, namespace): bundle = Bundle( "SPDXRef-Bundle", @@ -28,7 +28,7 @@ def test_correct_initialization(creation_information, namespace): assert bundle.namespaces == [namespace] -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Bundle(4, creation_information, elements="spdx_id1", root_elements=[42], namespaces=True, context=["yes"]) @@ -38,6 +38,6 @@ def test_invalid_initialization(creation_information): 'SetterError Bundle: type of argument "elements" must be a list; got str ' "instead: spdx_id1", 'SetterError Bundle: type of argument "root_elements"[0] must be str; got int ' "instead: [42]", 'SetterError Bundle: type of argument "namespaces" must be one of ' - "(List[spdx3.model.namespace_map.NamespaceMap], NoneType); got bool instead: True", + "(List[spdx_tools.spdx3.model.namespace_map.NamespaceMap], NoneType); got bool instead: True", 'SetterError Bundle: type of argument "context" must be one of (str, ' "NoneType); got list instead: ['yes']", ] diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py index 4aab6d25f..bccb9e0f9 100644 --- a/tests/spdx3/model/test_creation_information.py +++ b/tests/spdx3/model/test_creation_information.py @@ -6,7 +6,7 @@ import pytest from semantic_version import Version -from spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.creation_information import CreationInformation def test_correct_initialization(): diff --git a/tests/spdx3/model/test_external_identifier.py b/tests/spdx3/model/test_external_identifier.py index 4a90d65d7..e6f4107c4 100644 --- a/tests/spdx3/model/test_external_identifier.py +++ b/tests/spdx3/model/test_external_identifier.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType def test_correct_initialization(): @@ -21,7 +21,7 @@ def test_invalid_initialization(): assert err.value.args[0] == [ 'SetterError ExternalIdentifier: type of argument "external_identifier_type" ' - "must be spdx3.model.external_identifier.ExternalIdentifierType; got str " + "must be spdx_tools.spdx3.model.external_identifier.ExternalIdentifierType; got str " "instead: CPE22", 'SetterError ExternalIdentifier: type of argument "identifier" must be str; ' "got list instead: ['identifier', 'another_identifier']", diff --git a/tests/spdx3/model/test_external_map.py b/tests/spdx3/model/test_external_map.py index 606257911..9f46e83b0 100644 --- a/tests/spdx3/model/test_external_map.py +++ b/tests/spdx3/model/test_external_map.py @@ -5,10 +5,10 @@ import pytest -from spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.model.external_map import ExternalMap -@mock.patch("spdx3.model.integrity_method.IntegrityMethod", autospec=True) +@mock.patch("spdx_tools.spdx3.model.integrity_method.IntegrityMethod", autospec=True) def test_correct_initialization(integrity_method): external_map = ExternalMap("https://external.id", [integrity_method], "https://location.hint") diff --git a/tests/spdx3/model/test_external_reference.py b/tests/spdx3/model/test_external_reference.py index e882ddeb0..e087dac4e 100644 --- a/tests/spdx3/model/test_external_reference.py +++ b/tests/spdx3/model/test_external_reference.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx3.model.external_reference import ExternalReference, ExternalReferenceType +from spdx_tools.spdx3.model.external_reference import ExternalReference, ExternalReferenceType def test_correct_initialization(): @@ -22,7 +22,7 @@ def test_invalid_initialization(): assert err.value.args[0] == [ 'SetterError ExternalReference: type of argument "external_reference_type" ' - "must be one of (spdx3.model.external_reference.ExternalReferenceType, " + "must be one of (spdx_tools.spdx3.model.external_reference.ExternalReferenceType, " "NoneType); got str instead: OTHER", 'SetterError ExternalReference: type of argument "locator" must be a list; ' "got str instead: a URI", 'SetterError ExternalReference: type of argument "content_type" must be one ' diff --git a/tests/spdx3/model/test_hash.py b/tests/spdx3/model/test_hash.py index d383adce3..460a55747 100644 --- a/tests/spdx3/model/test_hash.py +++ b/tests/spdx3/model/test_hash.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx3.model.hash import Hash, HashAlgorithm +from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm def test_correct_initialization(): @@ -19,6 +19,6 @@ def test_invalid_initialization(): assert err.value.args[0] == [ 'SetterError Hash: type of argument "algorithm" must be ' - "spdx3.model.hash.HashAlgorithm; got str instead: SHA1", + "spdx_tools.spdx3.model.hash.HashAlgorithm; got str instead: SHA1", 'SetterError Hash: type of argument "hash_value" must be str; got int ' "instead: 345", ] diff --git a/tests/spdx3/model/test_namespace_map.py b/tests/spdx3/model/test_namespace_map.py index 469753d32..a6b63ef64 100644 --- a/tests/spdx3/model/test_namespace_map.py +++ b/tests/spdx3/model/test_namespace_map.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx3.model.namespace_map import NamespaceMap +from spdx_tools.spdx3.model.namespace_map import NamespaceMap def test_correct_initialization(): diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py index b0869d7cc..4c7d60f8a 100644 --- a/tests/spdx3/model/test_relationship.py +++ b/tests/spdx3/model/test_relationship.py @@ -5,10 +5,10 @@ import pytest -from spdx3.model.relationship import Relationship, RelationshipCompleteness, RelationshipType +from spdx_tools.spdx3.model.relationship import Relationship, RelationshipCompleteness, RelationshipType -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): relationship = Relationship( "SPDXRef-Relationship", @@ -27,7 +27,7 @@ def test_correct_initialization(creation_information): assert relationship.completeness == RelationshipCompleteness.UNKNOWN -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Relationship("SPDXRef-Relationship", creation_information, 42, 5, "Relationshiptype", completeness=True) @@ -36,8 +36,8 @@ def test_invalid_initialization(creation_information): 'SetterError Relationship: type of argument "from_element" must be ' "str; got int instead: 42", 'SetterError Relationship: type of argument "to" must be a list; got int ' "instead: 5", 'SetterError Relationship: type of argument "relationship_type" must be ' - "spdx3.model.relationship.RelationshipType; got str instead: Relationshiptype", + "spdx_tools.spdx3.model.relationship.RelationshipType; got str instead: Relationshiptype", 'SetterError Relationship: type of argument "completeness" must be one of ' - "(spdx3.model.relationship.RelationshipCompleteness, NoneType); got bool " + "(spdx_tools.spdx3.model.relationship.RelationshipCompleteness, NoneType); got bool " "instead: True", ] diff --git a/tests/spdx3/model/test_spdx_document.py b/tests/spdx3/model/test_spdx_document.py index e234414df..9e5480abc 100644 --- a/tests/spdx3/model/test_spdx_document.py +++ b/tests/spdx3/model/test_spdx_document.py @@ -5,10 +5,10 @@ import pytest -from spdx3.model.spdx_document import SpdxDocument +from spdx_tools.spdx3.model.spdx_document import SpdxDocument -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_correct_initialization(creation_information): spdx_document = SpdxDocument( "SPDXRef-DOCUMENT", creation_information, "Test document", elements=["spdx_id1"], root_elements=["spdx_id2"] @@ -28,13 +28,13 @@ def test_invalid_initialization(): assert err.value.args[0] == [ 'SetterError SpdxDocument: type of argument "spdx_id" must be str; got int ' "instead: 1", 'SetterError SpdxDocument: type of argument "creation_info" must be ' - "spdx3.model.creation_information.CreationInformation; got dict instead: " + "spdx_tools.spdx3.model.creation_information.CreationInformation; got dict instead: " "{'info': 5}", 'SetterError SpdxDocument: type of argument "elements"[0] must be ' "str; got int instead: [8]", ] -@mock.patch("spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) def test_incomplete_initialization(creation_information): with pytest.raises(TypeError) as err: SpdxDocument("SPDXRef-Document", creation_information) diff --git a/tests/spdx3/model/test_tool.py b/tests/spdx3/model/test_tool.py index 1a13c6032..dd54118f2 100644 --- a/tests/spdx3/model/test_tool.py +++ b/tests/spdx3/model/test_tool.py @@ -6,8 +6,8 @@ import pytest from semantic_version import Version -from spdx3.model.creation_information import CreationInformation -from spdx3.model.tool import Tool +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.tool import Tool def test_correct_initialization(): @@ -29,5 +29,5 @@ def test_invalid_initialization(): assert err.value.args[0] == [ 'SetterError Tool: type of argument "spdx_id" must be str; got int instead: 12', 'SetterError Tool: type of argument "creation_info" must be ' - "spdx3.model.creation_information.CreationInformation; got int instead: 345", + "spdx_tools.spdx3.model.creation_information.CreationInformation; got int instead: 345", ] From 52c547002fbe1c1ea44e3d89c6898f6999a68dab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 20 Apr 2023 08:17:30 +0200 Subject: [PATCH 178/354] [issue-593] expose model classes at model package level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/bump_from_spdx2/actor.py | 13 ++++++---- .../spdx3/bump_from_spdx2/annotation.py | 3 +-- .../spdx3/bump_from_spdx2/checksum.py | 2 +- .../bump_from_spdx2/creation_information.py | 3 +-- .../bump_from_spdx2/external_document_ref.py | 3 +-- src/spdx_tools/spdx3/bump_from_spdx2/file.py | 4 +-- .../spdx3/bump_from_spdx2/package.py | 13 ++++++---- .../spdx3/bump_from_spdx2/relationship.py | 3 +-- .../spdx3/bump_from_spdx2/snippet.py | 4 +-- .../spdx3/bump_from_spdx2/spdx_document.py | 3 +-- src/spdx_tools/spdx3/model/__init__.py | 21 ++++++++++++++++ src/spdx_tools/spdx3/model/agent.py | 6 +---- src/spdx_tools/spdx3/model/annotation.py | 6 +---- src/spdx_tools/spdx3/model/artifact.py | 2 +- src/spdx_tools/spdx3/model/bom.py | 16 ++++++------ src/spdx_tools/spdx3/model/bundle.py | 16 ++++++------ src/spdx_tools/spdx3/model/element.py | 5 +--- src/spdx_tools/spdx3/model/external_map.py | 2 +- src/spdx_tools/spdx3/model/hash.py | 2 +- src/spdx_tools/spdx3/model/organization.py | 6 +---- src/spdx_tools/spdx3/model/person.py | 6 +---- src/spdx_tools/spdx3/model/relationship.py | 6 +---- .../spdx3/model/software/__init__.py | 5 ++++ src/spdx_tools/spdx3/model/software/file.py | 14 ++++++----- .../spdx3/model/software/package.py | 14 ++++++----- src/spdx_tools/spdx3/model/software/sbom.py | 16 ++++++------ .../spdx3/model/software/snippet.py | 14 ++++++----- src/spdx_tools/spdx3/model/software_agent.py | 6 +---- src/spdx_tools/spdx3/model/spdx_collection.py | 4 +-- src/spdx_tools/spdx3/model/spdx_document.py | 16 ++++++------ src/spdx_tools/spdx3/model/tool.py | 6 +---- src/spdx_tools/spdx3/payload.py | 2 +- .../spdx3/writer/console/agent_writer.py | 5 +--- .../spdx3/writer/console/annotation_writer.py | 2 +- .../spdx3/writer/console/artifact_writer.py | 2 +- .../spdx3/writer/console/bom_writer.py | 2 +- .../spdx3/writer/console/bundle_writer.py | 2 +- .../console/creation_information_writer.py | 2 +- .../spdx3/writer/console/element_writer.py | 2 +- .../console/external_identifier_writer.py | 2 +- .../writer/console/external_map_writer.py | 2 +- .../console/external_reference_writer.py | 2 +- .../spdx3/writer/console/hash_writer.py | 2 +- .../writer/console/integrity_method_writer.py | 2 +- .../writer/console/namespace_map_writer.py | 2 +- .../spdx3/writer/console/payload_writer.py | 25 +++++++++---------- .../writer/console/relationship_writer.py | 2 +- .../writer/console/software/file_writer.py | 2 +- .../writer/console/software/package_writer.py | 2 +- .../writer/console/software/sbom_writer.py | 2 +- .../writer/console/software/snippet_writer.py | 2 +- .../writer/console/spdx_collection_writer.py | 2 +- .../writer/console/spdx_document_writer.py | 2 +- .../spdx3/writer/console/tool_writer.py | 2 +- tests/spdx3/bump/test_actor_bump.py | 13 ++++++---- tests/spdx3/bump/test_checksum_bump.py | 2 +- tests/spdx3/bump/test_file_bump.py | 6 ++--- tests/spdx3/bump/test_package_bump.py | 13 +++++----- tests/spdx3/bump/test_snippet_bump.py | 4 +-- tests/spdx3/model/software/test_file.py | 7 +++--- tests/spdx3/model/software/test_package.py | 7 +++--- tests/spdx3/model/software/test_sbom.py | 4 +-- tests/spdx3/model/software/test_snippet.py | 7 +++--- tests/spdx3/model/test_abstract_classes.py | 5 +--- tests/spdx3/model/test_agent.py | 15 ++++++----- tests/spdx3/model/test_annotation.py | 6 ++--- tests/spdx3/model/test_bom.py | 4 +-- tests/spdx3/model/test_bundle.py | 8 +++--- .../spdx3/model/test_creation_information.py | 2 +- tests/spdx3/model/test_external_identifier.py | 2 +- tests/spdx3/model/test_external_map.py | 4 +-- tests/spdx3/model/test_external_reference.py | 2 +- tests/spdx3/model/test_hash.py | 2 +- tests/spdx3/model/test_namespace_map.py | 2 +- tests/spdx3/model/test_relationship.py | 6 ++--- tests/spdx3/model/test_spdx_document.py | 6 ++--- tests/spdx3/model/test_tool.py | 3 +-- 77 files changed, 222 insertions(+), 220 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/actor.py b/src/spdx_tools/spdx3/bump_from_spdx2/actor.py index 99212a54a..3c9e0a430 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/actor.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/actor.py @@ -3,11 +3,14 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType -from spdx_tools.spdx3.model.organization import Organization -from spdx_tools.spdx3.model.person import Person -from spdx_tools.spdx3.model.tool import Tool +from spdx_tools.spdx3.model import ( + CreationInformation, + ExternalIdentifier, + ExternalIdentifierType, + Organization, + Person, + Tool, +) from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.actor import Actor as Spdx2_Actor from spdx_tools.spdx.model.actor import ActorType diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py index e14340aa9..d7cd383dc 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py @@ -4,8 +4,7 @@ from copy import deepcopy from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor -from spdx_tools.spdx3.model.annotation import Annotation, AnnotationType -from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model import Annotation, AnnotationType, CreationInformation from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.actor import ActorType from spdx_tools.spdx.model.annotation import Annotation as Spdx2_Annotation diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/checksum.py b/src/spdx_tools/spdx3/bump_from_spdx2/checksum.py index b52b5472b..ae056081f 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/checksum.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/checksum.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm +from spdx_tools.spdx3.model import Hash, HashAlgorithm from spdx_tools.spdx.model.checksum import Checksum as Spdx2_Checksum from spdx_tools.spdx.model.checksum import ChecksumAlgorithm diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py index 68e4f1484..ac365cac3 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py @@ -9,8 +9,7 @@ from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor from spdx_tools.spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.spdx_document import SpdxDocument +from spdx_tools.spdx3.model import CreationInformation, SpdxDocument from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.actor import ActorType from spdx_tools.spdx.model.document import CreationInfo as Spdx2_CreationInfo diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py b/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py index b17b41f34..bdbb0a9f7 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py @@ -4,8 +4,7 @@ from typing import List from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum -from spdx_tools.spdx3.model.external_map import ExternalMap -from spdx_tools.spdx3.model.hash import Hash +from spdx_tools.spdx3.model import ExternalMap, Hash from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/file.py b/src/spdx_tools/spdx3/bump_from_spdx2/file.py index 55ed3438a..3e8cba161 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/file.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/file.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.software.file import File +from spdx_tools.spdx3.model import CreationInformation +from spdx_tools.spdx3.model.software import File from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.file import File as Spdx2_File diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index 2b3736481..0ef6692c3 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -7,11 +7,14 @@ from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType -from spdx_tools.spdx3.model.external_reference import ExternalReference, ExternalReferenceType -from spdx_tools.spdx3.model.software.package import Package -from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.model import ( + CreationInformation, + ExternalIdentifier, + ExternalIdentifierType, + ExternalReference, + ExternalReferenceType, +) +from spdx_tools.spdx3.model.software import Package, SoftwarePurpose from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.package import ExternalPackageRef from spdx_tools.spdx.model.package import Package as Spdx2_Package diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py index aa42c6a4b..3ec263736 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -3,8 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Optional, Tuple -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.relationship import Relationship, RelationshipCompleteness, RelationshipType +from spdx_tools.spdx3.model import CreationInformation, Relationship, RelationshipCompleteness, RelationshipType from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.relationship import Relationship as Spdx2_Relationship from spdx_tools.spdx.model.relationship import RelationshipType as Spdx2_RelationshipType diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index 5f2ae554b..4bb012016 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -2,8 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.software.snippet import Snippet +from spdx_tools.spdx3.model import CreationInformation +from spdx_tools.spdx3.model.software import Snippet from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py index 5a3c0a3ea..b12204c5e 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py @@ -7,8 +7,7 @@ from spdx_tools.spdx3.bump_from_spdx2.package import bump_package from spdx_tools.spdx3.bump_from_spdx2.relationship import bump_relationship from spdx_tools.spdx3.bump_from_spdx2.snippet import bump_snippet -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.spdx_document import SpdxDocument +from spdx_tools.spdx3.model import CreationInformation, SpdxDocument from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.document import Document as Spdx2_Document diff --git a/src/spdx_tools/spdx3/model/__init__.py b/src/spdx_tools/spdx3/model/__init__.py index e69de29bb..64fd80e39 100644 --- a/src/spdx_tools/spdx3/model/__init__.py +++ b/src/spdx_tools/spdx3/model/__init__.py @@ -0,0 +1,21 @@ +from spdx_tools.spdx3.model.profile_identifier import ProfileIdentifier +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm +from spdx_tools.spdx3.model.external_reference import ExternalReference, ExternalReferenceType +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx_tools.spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.model.namespace_map import NamespaceMap +from spdx_tools.spdx3.model.element import Element +from spdx_tools.spdx3.model.agent import Agent +from spdx_tools.spdx3.model.person import Person +from spdx_tools.spdx3.model.organization import Organization +from spdx_tools.spdx3.model.software_agent import SoftwareAgent +from spdx_tools.spdx3.model.tool import Tool +from spdx_tools.spdx3.model.spdx_collection import SpdxCollection +from spdx_tools.spdx3.model.bundle import Bundle +from spdx_tools.spdx3.model.bom import Bom +from spdx_tools.spdx3.model.spdx_document import SpdxDocument +from spdx_tools.spdx3.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness +from spdx_tools.spdx3.model.artifact import Artifact diff --git a/src/spdx_tools/spdx3/model/agent.py b/src/spdx_tools/spdx3/model/agent.py index 2aa29b783..827a94d58 100644 --- a/src/spdx_tools/spdx3/model/agent.py +++ b/src/spdx_tools/spdx3/model/agent.py @@ -5,11 +5,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.element import Element -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model import CreationInformation, Element, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/annotation.py b/src/spdx_tools/spdx3/model/annotation.py index 925233871..3a35374d0 100644 --- a/src/spdx_tools/spdx3/model/annotation.py +++ b/src/spdx_tools/spdx3/model/annotation.py @@ -6,11 +6,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.element import Element -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model import CreationInformation, Element, ExternalIdentifier, ExternalReference, IntegrityMethod class AnnotationType(Enum): diff --git a/src/spdx_tools/spdx3/model/artifact.py b/src/spdx_tools/spdx3/model/artifact.py index b3270dc1e..71758ef42 100644 --- a/src/spdx_tools/spdx3/model/artifact.py +++ b/src/spdx_tools/spdx3/model/artifact.py @@ -5,7 +5,7 @@ from typing import Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties -from spdx_tools.spdx3.model.element import Element +from spdx_tools.spdx3.model import Element @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/bom.py b/src/spdx_tools/spdx3/model/bom.py index 1fc2d57d6..be28b5536 100644 --- a/src/spdx_tools/spdx3/model/bom.py +++ b/src/spdx_tools/spdx3/model/bom.py @@ -5,13 +5,15 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.bundle import Bundle -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_map import ExternalMap -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod -from spdx_tools.spdx3.model.namespace_map import NamespaceMap +from spdx_tools.spdx3.model import ( + Bundle, + CreationInformation, + ExternalIdentifier, + ExternalMap, + ExternalReference, + IntegrityMethod, + NamespaceMap, +) @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/bundle.py b/src/spdx_tools/spdx3/model/bundle.py index 9b0aedf48..f23a86cdb 100644 --- a/src/spdx_tools/spdx3/model/bundle.py +++ b/src/spdx_tools/spdx3/model/bundle.py @@ -5,13 +5,15 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_map import ExternalMap -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod -from spdx_tools.spdx3.model.namespace_map import NamespaceMap -from spdx_tools.spdx3.model.spdx_collection import SpdxCollection +from spdx_tools.spdx3.model import ( + CreationInformation, + ExternalIdentifier, + ExternalMap, + ExternalReference, + IntegrityMethod, + NamespaceMap, + SpdxCollection, +) @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/element.py b/src/spdx_tools/spdx3/model/element.py index 25ac72373..c5bcd0632 100644 --- a/src/spdx_tools/spdx3/model/element.py +++ b/src/spdx_tools/spdx3/model/element.py @@ -6,10 +6,7 @@ from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/external_map.py b/src/spdx_tools/spdx3/model/external_map.py index ec4d7d979..c26f96289 100644 --- a/src/spdx_tools/spdx3/model/external_map.py +++ b/src/spdx_tools/spdx3/model/external_map.py @@ -6,7 +6,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model import IntegrityMethod @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/hash.py b/src/spdx_tools/spdx3/model/hash.py index 5971bfb37..6e050845f 100644 --- a/src/spdx_tools/spdx3/model/hash.py +++ b/src/spdx_tools/spdx3/model/hash.py @@ -6,7 +6,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model import IntegrityMethod class HashAlgorithm(Enum): diff --git a/src/spdx_tools/spdx3/model/organization.py b/src/spdx_tools/spdx3/model/organization.py index 9a601c81a..0f204cb1f 100644 --- a/src/spdx_tools/spdx3/model/organization.py +++ b/src/spdx_tools/spdx3/model/organization.py @@ -5,11 +5,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.agent import Agent -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model import Agent, CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/person.py b/src/spdx_tools/spdx3/model/person.py index d69cba3a5..fe9bf338e 100644 --- a/src/spdx_tools/spdx3/model/person.py +++ b/src/spdx_tools/spdx3/model/person.py @@ -5,11 +5,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.agent import Agent -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model import Agent, CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index 88284c8cc..beff233f9 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -6,11 +6,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.element import Element -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model import CreationInformation, Element, ExternalIdentifier, ExternalReference, IntegrityMethod class RelationshipType(Enum): diff --git a/src/spdx_tools/spdx3/model/software/__init__.py b/src/spdx_tools/spdx3/model/software/__init__.py index e69de29bb..61c798ade 100644 --- a/src/spdx_tools/spdx3/model/software/__init__.py +++ b/src/spdx_tools/spdx3/model/software/__init__.py @@ -0,0 +1,5 @@ +from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.model.software.file import File +from spdx_tools.spdx3.model.software.package import Package +from spdx_tools.spdx3.model.software.snippet import Snippet +from spdx_tools.spdx3.model.software.sbom import Sbom diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py index 1b8afbe96..3e80f841d 100644 --- a/src/spdx_tools/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -5,12 +5,14 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.artifact import Artifact -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod -from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.model import ( + Artifact, + CreationInformation, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, +) +from spdx_tools.spdx3.model.software import SoftwarePurpose @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py index c68df220e..bee1b227f 100644 --- a/src/spdx_tools/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -5,12 +5,14 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.artifact import Artifact -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod -from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.model import ( + Artifact, + CreationInformation, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, +) +from spdx_tools.spdx3.model.software import SoftwarePurpose @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/software/sbom.py b/src/spdx_tools/spdx3/model/software/sbom.py index 8cafed690..c3b568905 100644 --- a/src/spdx_tools/spdx3/model/software/sbom.py +++ b/src/spdx_tools/spdx3/model/software/sbom.py @@ -5,13 +5,15 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.bom import Bom -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_map import ExternalMap -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod -from spdx_tools.spdx3.model.namespace_map import NamespaceMap +from spdx_tools.spdx3.model import ( + Bom, + CreationInformation, + ExternalIdentifier, + ExternalMap, + ExternalReference, + IntegrityMethod, + NamespaceMap, +) @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py index 81b886873..5690ed24a 100644 --- a/src/spdx_tools/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -5,12 +5,14 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.artifact import Artifact -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod -from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.model import ( + Artifact, + CreationInformation, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, +) +from spdx_tools.spdx3.model.software import SoftwarePurpose @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/software_agent.py b/src/spdx_tools/spdx3/model/software_agent.py index d3a6c05f1..53f6cc934 100644 --- a/src/spdx_tools/spdx3/model/software_agent.py +++ b/src/spdx_tools/spdx3/model/software_agent.py @@ -5,11 +5,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.agent import Agent -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model import Agent, CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/spdx_collection.py b/src/spdx_tools/spdx3/model/spdx_collection.py index d6a9bdcda..8e94e149e 100644 --- a/src/spdx_tools/spdx3/model/spdx_collection.py +++ b/src/spdx_tools/spdx3/model/spdx_collection.py @@ -6,9 +6,7 @@ from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties -from spdx_tools.spdx3.model.element import Element -from spdx_tools.spdx3.model.external_map import ExternalMap -from spdx_tools.spdx3.model.namespace_map import NamespaceMap +from spdx_tools.spdx3.model import Element, ExternalMap, NamespaceMap @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/spdx_document.py b/src/spdx_tools/spdx3/model/spdx_document.py index 8c1a1bdf6..be0f26a4d 100644 --- a/src/spdx_tools/spdx3/model/spdx_document.py +++ b/src/spdx_tools/spdx3/model/spdx_document.py @@ -5,13 +5,15 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.bundle import Bundle -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_map import ExternalMap -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod -from spdx_tools.spdx3.model.namespace_map import NamespaceMap +from spdx_tools.spdx3.model import ( + Bundle, + CreationInformation, + ExternalIdentifier, + ExternalMap, + ExternalReference, + IntegrityMethod, + NamespaceMap, +) @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/tool.py b/src/spdx_tools/spdx3/model/tool.py index 8a10fbdd3..3ac27ada1 100644 --- a/src/spdx_tools/spdx3/model/tool.py +++ b/src/spdx_tools/spdx3/model/tool.py @@ -5,11 +5,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.element import Element -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier -from spdx_tools.spdx3.model.external_reference import ExternalReference -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model import CreationInformation, Element, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/payload.py b/src/spdx_tools/spdx3/payload.py index b28e90a9e..911709a24 100644 --- a/src/spdx_tools/spdx3/payload.py +++ b/src/spdx_tools/spdx3/payload.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Dict -from spdx_tools.spdx3.model.element import Element +from spdx_tools.spdx3.model import Element class Payload: diff --git a/src/spdx_tools/spdx3/writer/console/agent_writer.py b/src/spdx_tools/spdx3/writer/console/agent_writer.py index 58f36abfb..cd46ff703 100644 --- a/src/spdx_tools/spdx3/writer/console/agent_writer.py +++ b/src/spdx_tools/spdx3/writer/console/agent_writer.py @@ -3,10 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.agent import Agent -from spdx_tools.spdx3.model.organization import Organization -from spdx_tools.spdx3.model.person import Person -from spdx_tools.spdx3.model.software_agent import SoftwareAgent +from spdx_tools.spdx3.model import Agent, Organization, Person, SoftwareAgent from spdx_tools.spdx3.writer.console.element_writer import write_element_properties diff --git a/src/spdx_tools/spdx3/writer/console/annotation_writer.py b/src/spdx_tools/spdx3/writer/console/annotation_writer.py index 92d474a72..f5e4ac00b 100644 --- a/src/spdx_tools/spdx3/writer/console/annotation_writer.py +++ b/src/spdx_tools/spdx3/writer/console/annotation_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.annotation import Annotation +from spdx_tools.spdx3.model import Annotation from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx3.writer.console.element_writer import write_element_properties diff --git a/src/spdx_tools/spdx3/writer/console/artifact_writer.py b/src/spdx_tools/spdx3/writer/console/artifact_writer.py index 5c1532dd6..474be979a 100644 --- a/src/spdx_tools/spdx3/writer/console/artifact_writer.py +++ b/src/spdx_tools/spdx3/writer/console/artifact_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.artifact import Artifact +from spdx_tools.spdx3.model import Artifact from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx3.writer.console.element_writer import write_element_properties diff --git a/src/spdx_tools/spdx3/writer/console/bom_writer.py b/src/spdx_tools/spdx3/writer/console/bom_writer.py index 229e95005..c6e0f71ec 100644 --- a/src/spdx_tools/spdx3/writer/console/bom_writer.py +++ b/src/spdx_tools/spdx3/writer/console/bom_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.bom import Bom +from spdx_tools.spdx3.model import Bom from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle diff --git a/src/spdx_tools/spdx3/writer/console/bundle_writer.py b/src/spdx_tools/spdx3/writer/console/bundle_writer.py index 8c0384383..2a7fc8d78 100644 --- a/src/spdx_tools/spdx3/writer/console/bundle_writer.py +++ b/src/spdx_tools/spdx3/writer/console/bundle_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.bundle import Bundle +from spdx_tools.spdx3.model import Bundle from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx3.writer.console.spdx_collection_writer import write_collection diff --git a/src/spdx_tools/spdx3/writer/console/creation_information_writer.py b/src/spdx_tools/spdx3/writer/console/creation_information_writer.py index 3c1a2b076..25072ad3d 100644 --- a/src/spdx_tools/spdx3/writer/console/creation_information_writer.py +++ b/src/spdx_tools/spdx3/writer/console/creation_information_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model import CreationInformation from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string diff --git a/src/spdx_tools/spdx3/writer/console/element_writer.py b/src/spdx_tools/spdx3/writer/console/element_writer.py index 14b814584..f3f14aa2c 100644 --- a/src/spdx_tools/spdx3/writer/console/element_writer.py +++ b/src/spdx_tools/spdx3/writer/console/element_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.element import Element +from spdx_tools.spdx3.model import Element from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx3.writer.console.creation_information_writer import write_creation_info from spdx_tools.spdx3.writer.console.external_identifier_writer import write_external_identifier diff --git a/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py b/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py index f2d2db59e..e197581be 100644 --- a/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py +++ b/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier +from spdx_tools.spdx3.model import ExternalIdentifier from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/external_map_writer.py b/src/spdx_tools/spdx3/writer/console/external_map_writer.py index 75ab4f4a6..1b53a1024 100644 --- a/src/spdx_tools/spdx3/writer/console/external_map_writer.py +++ b/src/spdx_tools/spdx3/writer/console/external_map_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.model import ExternalMap from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx3.writer.console.hash_writer import write_hash from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading diff --git a/src/spdx_tools/spdx3/writer/console/external_reference_writer.py b/src/spdx_tools/spdx3/writer/console/external_reference_writer.py index fd1e21293..64b8da2fd 100644 --- a/src/spdx_tools/spdx3/writer/console/external_reference_writer.py +++ b/src/spdx_tools/spdx3/writer/console/external_reference_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.external_reference import ExternalReference +from spdx_tools.spdx3.model import ExternalReference from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/hash_writer.py b/src/spdx_tools/spdx3/writer/console/hash_writer.py index a1e56b71a..cbc0a99ed 100644 --- a/src/spdx_tools/spdx3/writer/console/hash_writer.py +++ b/src/spdx_tools/spdx3/writer/console/hash_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.hash import Hash +from spdx_tools.spdx3.model import Hash from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx3.writer.console.integrity_method_writer import write_integrity_method diff --git a/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py b/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py index 14b61b497..2e3d4dfe5 100644 --- a/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py +++ b/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod +from spdx_tools.spdx3.model import IntegrityMethod from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py b/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py index 4fbada5b3..d4adf12b5 100644 --- a/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py +++ b/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.namespace_map import NamespaceMap +from spdx_tools.spdx3.model import NamespaceMap from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/payload_writer.py b/src/spdx_tools/spdx3/writer/console/payload_writer.py index 59ce9b01e..2a91a4d90 100644 --- a/src/spdx_tools/spdx3/writer/console/payload_writer.py +++ b/src/spdx_tools/spdx3/writer/console/payload_writer.py @@ -3,19 +3,18 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.annotation import Annotation -from spdx_tools.spdx3.model.bom import Bom -from spdx_tools.spdx3.model.bundle import Bundle -from spdx_tools.spdx3.model.organization import Organization -from spdx_tools.spdx3.model.person import Person -from spdx_tools.spdx3.model.relationship import Relationship -from spdx_tools.spdx3.model.software.file import File -from spdx_tools.spdx3.model.software.package import Package -from spdx_tools.spdx3.model.software.sbom import Sbom -from spdx_tools.spdx3.model.software.snippet import Snippet -from spdx_tools.spdx3.model.software_agent import SoftwareAgent -from spdx_tools.spdx3.model.spdx_document import SpdxDocument -from spdx_tools.spdx3.model.tool import Tool +from spdx_tools.spdx3.model import ( + Annotation, + Bom, + Bundle, + Organization, + Person, + Relationship, + SoftwareAgent, + SpdxDocument, + Tool, +) +from spdx_tools.spdx3.model.software import File, Package, Sbom, Snippet from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx3.writer.console.agent_writer import write_agent from spdx_tools.spdx3.writer.console.annotation_writer import write_annotation diff --git a/src/spdx_tools/spdx3/writer/console/relationship_writer.py b/src/spdx_tools/spdx3/writer/console/relationship_writer.py index 7944e2090..738f45c4e 100644 --- a/src/spdx_tools/spdx3/writer/console/relationship_writer.py +++ b/src/spdx_tools/spdx3/writer/console/relationship_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.relationship import Relationship +from spdx_tools.spdx3.model import Relationship from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx3.writer.console.element_writer import write_element_properties diff --git a/src/spdx_tools/spdx3/writer/console/software/file_writer.py b/src/spdx_tools/spdx3/writer/console/software/file_writer.py index 9257a0612..bd0bdfa54 100644 --- a/src/spdx_tools/spdx3/writer/console/software/file_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/file_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.software.file import File +from spdx_tools.spdx3.model.software import File from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/software/package_writer.py b/src/spdx_tools/spdx3/writer/console/software/package_writer.py index 4af2f5b4c..2e7535c2a 100644 --- a/src/spdx_tools/spdx3/writer/console/software/package_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/package_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.software.package import Package +from spdx_tools.spdx3.model.software import Package from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py b/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py index 83a5b7956..039d55cc2 100644 --- a/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.software.sbom import Sbom +from spdx_tools.spdx3.model.software import Sbom from spdx_tools.spdx3.writer.console.bom_writer import write_bom diff --git a/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py b/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py index 22415ee53..0378b3aa0 100644 --- a/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.software.snippet import Snippet +from spdx_tools.spdx3.model.software import Snippet from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range diff --git a/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py b/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py index 96461c09c..c34dcdb5e 100644 --- a/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py +++ b/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.spdx_collection import SpdxCollection +from spdx_tools.spdx3.model import SpdxCollection from spdx_tools.spdx3.writer.console.element_writer import write_element_properties from spdx_tools.spdx3.writer.console.external_map_writer import write_external_map from spdx_tools.spdx3.writer.console.namespace_map_writer import write_namespace_map diff --git a/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py b/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py index 426421753..15f3e57f7 100644 --- a/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py +++ b/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model.spdx_document import SpdxDocument +from spdx_tools.spdx3.model import SpdxDocument from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle diff --git a/src/spdx_tools/spdx3/writer/console/tool_writer.py b/src/spdx_tools/spdx3/writer/console/tool_writer.py index 3b2ee1560..35824a778 100644 --- a/src/spdx_tools/spdx3/writer/console/tool_writer.py +++ b/src/spdx_tools/spdx3/writer/console/tool_writer.py @@ -10,7 +10,7 @@ # limitations under the License. from typing import TextIO -from spdx_tools.spdx3.model.tool import Tool +from spdx_tools.spdx3.model import Tool from spdx_tools.spdx3.writer.console.element_writer import write_element_properties diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index bc91d555b..af01149f7 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -7,11 +7,14 @@ from semantic_version import Version from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType -from spdx_tools.spdx3.model.organization import Organization -from spdx_tools.spdx3.model.person import Person -from spdx_tools.spdx3.model.tool import Tool +from spdx_tools.spdx3.model import ( + CreationInformation, + ExternalIdentifier, + ExternalIdentifierType, + Organization, + Person, + Tool, +) from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.actor import Actor, ActorType diff --git a/tests/spdx3/bump/test_checksum_bump.py b/tests/spdx3/bump/test_checksum_bump.py index d1c167783..671653535 100644 --- a/tests/spdx3/bump/test_checksum_bump.py +++ b/tests/spdx3/bump/test_checksum_bump.py @@ -4,7 +4,7 @@ import pytest from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum, convert_checksum_algorithm_to_hash_algorithm -from spdx_tools.spdx3.model.hash import HashAlgorithm +from spdx_tools.spdx3.model import HashAlgorithm from spdx_tools.spdx.model.checksum import ChecksumAlgorithm from tests.spdx.fixtures import checksum_fixture diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index 5ac6c7214..7e63e6dd3 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -4,14 +4,14 @@ from unittest import mock from spdx_tools.spdx3.bump_from_spdx2.file import bump_file -from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm -from spdx_tools.spdx3.model.software.file import File +from spdx_tools.spdx3.model import Hash, HashAlgorithm +from spdx_tools.spdx3.model.software import File from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.file import File as Spdx2_File from tests.spdx.fixtures import file_fixture -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_bump_file(creation_information): payload = Payload() document_namespace = "https://doc.namespace" diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 923fe6479..6abbc2c8a 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -4,16 +4,15 @@ from unittest import TestCase, mock from spdx_tools.spdx3.bump_from_spdx2.package import bump_package -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType -from spdx_tools.spdx3.model.external_reference import ExternalReference, ExternalReferenceType -from spdx_tools.spdx3.model.software.package import Package +from spdx_tools.spdx3.model import ExternalIdentifier, ExternalIdentifierType, ExternalReference, ExternalReferenceType +from spdx_tools.spdx3.model.software import Package from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory from spdx_tools.spdx.model.package import Package as Spdx2_Package from tests.spdx.fixtures import package_fixture -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation") +@mock.patch("spdx_tools.spdx3.model.CreationInformation") def test_bump_package(creation_information): payload = Payload() document_namespace = "https://doc.namespace" @@ -45,7 +44,7 @@ def test_bump_package(creation_information): assert package.source_info == spdx2_package.source_info -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation") +@mock.patch("spdx_tools.spdx3.model.CreationInformation") def test_bump_of_single_purl_without_comment(creation_information): payload = Payload() document_namespace = "https://doc.namespace" @@ -64,7 +63,7 @@ def test_bump_of_single_purl_without_comment(creation_information): assert package.external_identifier == [] -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation") +@mock.patch("spdx_tools.spdx3.model.CreationInformation") def test_bump_of_single_purl_with_comment(creation_information): payload = Payload() document_namespace = "https://doc.namespace" @@ -85,7 +84,7 @@ def test_bump_of_single_purl_with_comment(creation_information): ] -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation") +@mock.patch("spdx_tools.spdx3.model.CreationInformation") def test_bump_of_multiple_purls(creation_information): payload = Payload() document_namespace = "https://doc.namespace" diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index fa2b88889..9c9ecb72e 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -4,13 +4,13 @@ from unittest import mock from spdx_tools.spdx3.bump_from_spdx2.snippet import bump_snippet -from spdx_tools.spdx3.model.software.snippet import Snippet +from spdx_tools.spdx3.model.software import Snippet from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet from tests.spdx.fixtures import snippet_fixture -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_bump_snippet(creation_information): payload = Payload() document_namespace = "https://doc.namespace" diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index 57247909f..49ee3a72d 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -5,11 +5,10 @@ import pytest -from spdx_tools.spdx3.model.software.file import File -from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.model.software import File, SoftwarePurpose -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_correct_initialization(creation_information): file = File( "SPDXRef-File", @@ -27,7 +26,7 @@ def test_correct_initialization(creation_information): assert file.content_type == "MediaType" -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: File( diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index fc9d9d0e9..8bc4dfbc5 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -5,11 +5,10 @@ import pytest -from spdx_tools.spdx3.model.software.package import Package -from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.model.software import Package, SoftwarePurpose -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_correct_initialization(creation_information): package = Package( "SPDXRef-Package", @@ -34,7 +33,7 @@ def test_correct_initialization(creation_information): assert package.source_info == "some info" -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Package( diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index d51ea3a8f..9e2c304ca 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -5,10 +5,10 @@ import pytest -from spdx_tools.spdx3.model.software.sbom import Sbom +from spdx_tools.spdx3.model.software import Sbom -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_correct_initialization(creation_information): sbom = Sbom("SPDXRef-Sbom", creation_information, elements=["spdx_id1", "spdx_id2"], root_elements=["spdx_id3"]) diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index f7ff9f2b9..4657cc635 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -5,11 +5,10 @@ import pytest -from spdx_tools.spdx3.model.software.snippet import Snippet -from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose +from spdx_tools.spdx3.model.software import Snippet, SoftwarePurpose -@mock.patch("spdx_tools.spdx3.model.software.snippet.Snippet", autospec=True) +@mock.patch("spdx_tools.spdx3.model.software.Snippet", autospec=True) def test_correct_initialization(creation_information): snippet = Snippet( "SPDXRef-Snippet", @@ -28,7 +27,7 @@ def test_correct_initialization(creation_information): assert snippet.line_range == (346, 456) -@mock.patch("spdx_tools.spdx3.model.software.snippet.Snippet", autospec=True) +@mock.patch("spdx_tools.spdx3.model.software.Snippet", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Snippet(2, creation_information, originated_by=34, byte_range="34:45") diff --git a/tests/spdx3/model/test_abstract_classes.py b/tests/spdx3/model/test_abstract_classes.py index 7eb583a28..39e45a46a 100644 --- a/tests/spdx3/model/test_abstract_classes.py +++ b/tests/spdx3/model/test_abstract_classes.py @@ -3,10 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx_tools.spdx3.model.artifact import Artifact -from spdx_tools.spdx3.model.element import Element -from spdx_tools.spdx3.model.integrity_method import IntegrityMethod -from spdx_tools.spdx3.model.spdx_collection import SpdxCollection +from spdx_tools.spdx3.model import Artifact, Element, IntegrityMethod, SpdxCollection @pytest.mark.parametrize("abstract_class", [Element, Artifact, SpdxCollection, IntegrityMethod]) diff --git a/tests/spdx3/model/test_agent.py b/tests/spdx3/model/test_agent.py index ec4cf8f00..ed057c4da 100644 --- a/tests/spdx3/model/test_agent.py +++ b/tests/spdx3/model/test_agent.py @@ -6,12 +6,15 @@ import pytest from semantic_version import Version -from spdx_tools.spdx3.model.agent import Agent -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType -from spdx_tools.spdx3.model.organization import Organization -from spdx_tools.spdx3.model.person import Person -from spdx_tools.spdx3.model.software_agent import SoftwareAgent +from spdx_tools.spdx3.model import ( + Agent, + CreationInformation, + ExternalIdentifier, + ExternalIdentifierType, + Organization, + Person, + SoftwareAgent, +) @pytest.mark.parametrize("agent_class", [Agent, Person, Organization, SoftwareAgent]) diff --git a/tests/spdx3/model/test_annotation.py b/tests/spdx3/model/test_annotation.py index bd8019153..f951fd671 100644 --- a/tests/spdx3/model/test_annotation.py +++ b/tests/spdx3/model/test_annotation.py @@ -5,10 +5,10 @@ import pytest -from spdx_tools.spdx3.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx3.model import Annotation, AnnotationType -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_correct_initialization(creation_information): annotation = Annotation( "SPDXRef-Annotation", @@ -27,7 +27,7 @@ def test_correct_initialization(creation_information): assert annotation.statement == "This is a statement" -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation") +@mock.patch("spdx_tools.spdx3.model.CreationInformation") def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Annotation( diff --git a/tests/spdx3/model/test_bom.py b/tests/spdx3/model/test_bom.py index 8e93afeae..0c897d841 100644 --- a/tests/spdx3/model/test_bom.py +++ b/tests/spdx3/model/test_bom.py @@ -6,10 +6,10 @@ import pytest -from spdx_tools.spdx3.model.bom import Bom +from spdx_tools.spdx3.model import Bom -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_correct_initialization(creation_information): bom = Bom("SPDXRef-Bom", creation_information, elements=["spdx_id1"], root_elements=["spdx_id2"]) diff --git a/tests/spdx3/model/test_bundle.py b/tests/spdx3/model/test_bundle.py index f5a4643c2..b3c58e77b 100644 --- a/tests/spdx3/model/test_bundle.py +++ b/tests/spdx3/model/test_bundle.py @@ -5,11 +5,11 @@ import pytest -from spdx_tools.spdx3.model.bundle import Bundle +from spdx_tools.spdx3.model import Bundle -@mock.patch("spdx_tools.spdx3.model.namespace_map.NamespaceMap", autospec=True) -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.NamespaceMap", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_correct_initialization(creation_information, namespace): bundle = Bundle( "SPDXRef-Bundle", @@ -28,7 +28,7 @@ def test_correct_initialization(creation_information, namespace): assert bundle.namespaces == [namespace] -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Bundle(4, creation_information, elements="spdx_id1", root_elements=[42], namespaces=True, context=["yes"]) diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py index bccb9e0f9..1c6ed1cba 100644 --- a/tests/spdx3/model/test_creation_information.py +++ b/tests/spdx3/model/test_creation_information.py @@ -6,7 +6,7 @@ import pytest from semantic_version import Version -from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model import CreationInformation def test_correct_initialization(): diff --git a/tests/spdx3/model/test_external_identifier.py b/tests/spdx3/model/test_external_identifier.py index e6f4107c4..ab37631fe 100644 --- a/tests/spdx3/model/test_external_identifier.py +++ b/tests/spdx3/model/test_external_identifier.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx_tools.spdx3.model import ExternalIdentifier, ExternalIdentifierType def test_correct_initialization(): diff --git a/tests/spdx3/model/test_external_map.py b/tests/spdx3/model/test_external_map.py index 9f46e83b0..c925dade2 100644 --- a/tests/spdx3/model/test_external_map.py +++ b/tests/spdx3/model/test_external_map.py @@ -5,10 +5,10 @@ import pytest -from spdx_tools.spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.model import ExternalMap -@mock.patch("spdx_tools.spdx3.model.integrity_method.IntegrityMethod", autospec=True) +@mock.patch("spdx_tools.spdx3.model.IntegrityMethod", autospec=True) def test_correct_initialization(integrity_method): external_map = ExternalMap("https://external.id", [integrity_method], "https://location.hint") diff --git a/tests/spdx3/model/test_external_reference.py b/tests/spdx3/model/test_external_reference.py index e087dac4e..ebee27713 100644 --- a/tests/spdx3/model/test_external_reference.py +++ b/tests/spdx3/model/test_external_reference.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx_tools.spdx3.model.external_reference import ExternalReference, ExternalReferenceType +from spdx_tools.spdx3.model import ExternalReference, ExternalReferenceType def test_correct_initialization(): diff --git a/tests/spdx3/model/test_hash.py b/tests/spdx3/model/test_hash.py index 460a55747..1cfc4f117 100644 --- a/tests/spdx3/model/test_hash.py +++ b/tests/spdx3/model/test_hash.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm +from spdx_tools.spdx3.model import Hash, HashAlgorithm def test_correct_initialization(): diff --git a/tests/spdx3/model/test_namespace_map.py b/tests/spdx3/model/test_namespace_map.py index a6b63ef64..0217bff18 100644 --- a/tests/spdx3/model/test_namespace_map.py +++ b/tests/spdx3/model/test_namespace_map.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx_tools.spdx3.model.namespace_map import NamespaceMap +from spdx_tools.spdx3.model import NamespaceMap def test_correct_initialization(): diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py index 4c7d60f8a..27c127543 100644 --- a/tests/spdx3/model/test_relationship.py +++ b/tests/spdx3/model/test_relationship.py @@ -5,10 +5,10 @@ import pytest -from spdx_tools.spdx3.model.relationship import Relationship, RelationshipCompleteness, RelationshipType +from spdx_tools.spdx3.model import Relationship, RelationshipCompleteness, RelationshipType -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_correct_initialization(creation_information): relationship = Relationship( "SPDXRef-Relationship", @@ -27,7 +27,7 @@ def test_correct_initialization(creation_information): assert relationship.completeness == RelationshipCompleteness.UNKNOWN -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Relationship("SPDXRef-Relationship", creation_information, 42, 5, "Relationshiptype", completeness=True) diff --git a/tests/spdx3/model/test_spdx_document.py b/tests/spdx3/model/test_spdx_document.py index 9e5480abc..d5a1f2cba 100644 --- a/tests/spdx3/model/test_spdx_document.py +++ b/tests/spdx3/model/test_spdx_document.py @@ -5,10 +5,10 @@ import pytest -from spdx_tools.spdx3.model.spdx_document import SpdxDocument +from spdx_tools.spdx3.model import SpdxDocument -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_correct_initialization(creation_information): spdx_document = SpdxDocument( "SPDXRef-DOCUMENT", creation_information, "Test document", elements=["spdx_id1"], root_elements=["spdx_id2"] @@ -34,7 +34,7 @@ def test_invalid_initialization(): ] -@mock.patch("spdx_tools.spdx3.model.creation_information.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_incomplete_initialization(creation_information): with pytest.raises(TypeError) as err: SpdxDocument("SPDXRef-Document", creation_information) diff --git a/tests/spdx3/model/test_tool.py b/tests/spdx3/model/test_tool.py index dd54118f2..1820c7c6e 100644 --- a/tests/spdx3/model/test_tool.py +++ b/tests/spdx3/model/test_tool.py @@ -6,8 +6,7 @@ import pytest from semantic_version import Version -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.tool import Tool +from spdx_tools.spdx3.model import CreationInformation, Tool def test_correct_initialization(): From cca949a53e66af73e83f651e2b18f7ba202f9b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 20 Apr 2023 10:37:15 +0200 Subject: [PATCH 179/354] [issue-426] add time properties to artifact MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/README.md | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/package.py | 7 ++++++- src/spdx_tools/spdx3/bump_from_spdx2/snippet.py | 4 ++-- src/spdx_tools/spdx3/model/artifact.py | 4 ++++ src/spdx_tools/spdx3/model/software/file.py | 4 ++++ src/spdx_tools/spdx3/model/software/package.py | 4 ++++ src/spdx_tools/spdx3/model/software/snippet.py | 4 ++++ src/spdx_tools/spdx3/writer/console/artifact_writer.py | 3 +++ tests/spdx3/bump/test_package_bump.py | 3 +++ tests/spdx3/model/software/test_package.py | 10 ++++++++++ 10 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/spdx_tools/spdx3/README.md b/src/spdx_tools/spdx3/README.md index da81b6af8..2f0f9021c 100644 --- a/src/spdx_tools/spdx3/README.md +++ b/src/spdx_tools/spdx3/README.md @@ -1 +1 @@ -This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: 81ce08107ae8b295814dcc631cfa1c48124887aa). +This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: 5cc54f4d8a44d4082172940f6b81fdd0edc798df). diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index 0ef6692c3..c53d6defe 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -49,6 +49,9 @@ def bump_package( summary = spdx2_package.summary description = spdx2_package.description comment = spdx2_package.comment + built_time = spdx2_package.built_date + release_time = spdx2_package.release_date + valid_until_time = spdx2_package.valid_until_date external_references = [] external_identifiers = [] @@ -72,7 +75,6 @@ def bump_package( package_purpose = ( [SoftwarePurpose[spdx2_package.primary_package_purpose.name]] if spdx2_package.primary_package_purpose else [] ) - print_missing_conversion("package2.release_date, package2.built_date, package2.valid_until_date", 0) payload.add_element( Package( @@ -86,6 +88,9 @@ def bump_package( external_references=external_references, external_identifier=external_identifiers, originated_by=originated_by_spdx_id, + built_time=built_time, + release_time=release_time, + valid_until_time=valid_until_time, package_purpose=package_purpose, package_version=package_version, download_location=download_location, diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index 4bb012016..0f732ab9b 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -30,9 +30,9 @@ def bump_snippet( Snippet( spdx_id=spdx_id, creation_info=creation_information, + name=name, + comment=comment, byte_range=byte_range, line_range=line_range, - comment=comment, - name=name, ) ) diff --git a/src/spdx_tools/spdx3/model/artifact.py b/src/spdx_tools/spdx3/model/artifact.py index 71758ef42..9f581ddff 100644 --- a/src/spdx_tools/spdx3/model/artifact.py +++ b/src/spdx_tools/spdx3/model/artifact.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod +from datetime import datetime from typing import Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties @@ -11,6 +12,9 @@ @dataclass_with_properties class Artifact(Element): originated_by: Optional[str] = None # SPDXID of the Agent/Tool + built_time: Optional[datetime] = None + release_time: Optional[datetime] = None + valid_until_time: Optional[datetime] = None @abstractmethod def __init__(self): diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py index 3e80f841d..001c4ed1c 100644 --- a/src/spdx_tools/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties @@ -34,6 +35,9 @@ def __init__( external_identifier: Optional[List[ExternalIdentifier]] = None, extension: None = None, originated_by: Optional[str] = None, + built_time: Optional[datetime] = None, + release_time: Optional[datetime] = None, + valid_until_time: Optional[datetime] = None, content_identifier: Optional[str] = None, file_purpose: Optional[List[SoftwarePurpose]] = None, content_type: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py index bee1b227f..a1be702fb 100644 --- a/src/spdx_tools/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties @@ -39,6 +40,9 @@ def __init__( extension: None = None, originated_by: Optional[str] = None, content_identifier: Optional[str] = None, + built_time: Optional[datetime] = None, + release_time: Optional[datetime] = None, + valid_until_time: Optional[datetime] = None, package_purpose: Optional[List[SoftwarePurpose]] = None, package_version: Optional[str] = None, download_location: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py index 5690ed24a..9e8e05885 100644 --- a/src/spdx_tools/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime from typing import List, Optional, Tuple from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties @@ -36,6 +37,9 @@ def __init__( extension: None = None, originated_by: Optional[str] = None, content_identifier: Optional[str] = None, + built_time: Optional[datetime] = None, + release_time: Optional[datetime] = None, + valid_until_time: Optional[datetime] = None, snippet_purpose: Optional[List[SoftwarePurpose]] = None, byte_range: Optional[Tuple[int, int]] = None, line_range: Optional[Tuple[int, int]] = None, diff --git a/src/spdx_tools/spdx3/writer/console/artifact_writer.py b/src/spdx_tools/spdx3/writer/console/artifact_writer.py index 474be979a..b873e4163 100644 --- a/src/spdx_tools/spdx3/writer/console/artifact_writer.py +++ b/src/spdx_tools/spdx3/writer/console/artifact_writer.py @@ -11,3 +11,6 @@ def write_artifact_properties(artifact: Artifact, text_output: TextIO): write_element_properties(artifact, text_output) write_value("originated_by", artifact.originated_by, text_output) + write_value("built_time", artifact.built_time, text_output) + write_value("release_time", artifact.release_time, text_output) + write_value("valid_until_time", artifact.valid_until_time, text_output) diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 6abbc2c8a..f5f6d59d2 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -42,6 +42,9 @@ def test_bump_package(creation_information): assert package.package_version == spdx2_package.version assert package.homepage == spdx2_package.homepage assert package.source_info == spdx2_package.source_info + assert package.built_time == spdx2_package.built_date + assert package.release_time == spdx2_package.release_date + assert package.valid_until_time == spdx2_package.valid_until_date @mock.patch("spdx_tools.spdx3.model.CreationInformation") diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 8bc4dfbc5..859ea7514 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime from unittest import mock import pytest @@ -14,6 +15,9 @@ def test_correct_initialization(creation_information): "SPDXRef-Package", creation_information, content_identifier="https://any.uri", + built_time=datetime(2022, 1, 1), + release_time=datetime(2022, 1, 2), + valid_until_time=datetime(2022, 1, 3), package_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH], package_version="1:23a_bc", download_location="https://downloadlocation", @@ -25,6 +29,9 @@ def test_correct_initialization(creation_information): assert package.spdx_id == "SPDXRef-Package" assert package.creation_info == creation_information assert package.content_identifier == "https://any.uri" + assert package.built_time == datetime(2022, 1, 1) + assert package.release_time == datetime(2022, 1, 2) + assert package.valid_until_time == datetime(2022, 1, 3) assert package.package_purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH] assert package.package_version == "1:23a_bc" assert package.download_location == "https://downloadlocation" @@ -39,6 +46,7 @@ def test_invalid_initialization(creation_information): Package( "SPDXRef-Package", creation_information, + built_time="2022-03-04T00:00:00Z", content_identifier=3, package_purpose=SoftwarePurpose.FILE, package_version=42, @@ -49,6 +57,8 @@ def test_invalid_initialization(creation_information): ) assert err.value.args[0] == [ + 'SetterError Package: type of argument "built_time" must be one of ' + "(datetime.datetime, NoneType); got str instead: 2022-03-04T00:00:00Z", 'SetterError Package: type of argument "content_identifier" must be one of ' "(str, NoneType); got int instead: 3", 'SetterError Package: type of argument "package_purpose" must be one of ' From c44d08518f304d427adddc1b8733bfb86c1cb21a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 20 Apr 2023 10:58:00 +0200 Subject: [PATCH 180/354] refactor bumping methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../spdx3/bump_from_spdx2/annotation.py | 12 ++++++-- .../bump_from_spdx2/creation_information.py | 21 ++++++------- .../bump_from_spdx2/external_document_ref.py | 8 +++-- src/spdx_tools/spdx3/bump_from_spdx2/file.py | 10 +++++-- .../spdx3/bump_from_spdx2/package.py | 30 +++++++------------ .../spdx3/bump_from_spdx2/relationship.py | 3 +- .../spdx3/bump_from_spdx2/snippet.py | 12 +++----- 7 files changed, 45 insertions(+), 51 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py index d7cd383dc..a43c89964 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py @@ -33,7 +33,13 @@ def bump_annotation( " This case leads to an invalid SPDX3 document and is currently not supported." ) annotation_type: AnnotationType = AnnotationType[spdx2_annotation.annotation_type.name] - subject: str = spdx2_annotation.spdx_id - statement: str = spdx2_annotation.annotation_comment - payload.add_element(Annotation(spdx_id, creation_info, annotation_type, subject, statement=statement)) + payload.add_element( + Annotation( + spdx_id, + creation_info, + annotation_type, + subject=spdx2_annotation.spdx_id, + statement=spdx2_annotation.annotation_comment, + ) + ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py index ac365cac3..8694a695e 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py @@ -1,7 +1,6 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from datetime import datetime from typing import List from semantic_version import Version @@ -20,15 +19,9 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: document_namespace = spdx2_creation_info.document_namespace spdx_id = f"{document_namespace}#{spdx2_creation_info.spdx_id}" - # creation_info.name -> spdx_document.name - name = spdx2_creation_info.name - # creation_info.document_namespace -> ? print_missing_conversion("creation_info.document_namespace", 0) - created: datetime = spdx2_creation_info.created - comment = spdx2_creation_info.document_comment - data_license = spdx2_creation_info.data_license # creation_info.external_document_refs -> spdx_document.imports imports = [ bump_external_document_ref(external_document_ref) @@ -39,7 +32,13 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: # creation_info.document_comment -> spdx_document.comment document_comment = spdx2_creation_info.document_comment creation_information = CreationInformation( - Version("3.0.0"), created, [], [], ["core", "software", "licensing"], data_license, comment + spec_version=Version("3.0.0"), + created=spdx2_creation_info.created, + created_by=[], + created_using=[], + profile=["core", "software", "licensing"], + data_license=spdx2_creation_info.data_license, + comment=spdx2_creation_info.document_comment, ) # due to creators having a creation_information themselves which inherits from the document's one, @@ -62,14 +61,12 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: creation_information.created_by = creator_ids creation_information.created_using = tool_ids - spdx_document = SpdxDocument( + return SpdxDocument( spdx_id=spdx_id, creation_info=creation_information, - name=name, + name=spdx2_creation_info.name, comment=document_comment, elements=[], root_elements=[], imports=imports, ) - - return spdx_document diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py b/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py index bdbb0a9f7..10cfdd530 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py @@ -9,8 +9,10 @@ def bump_external_document_ref(external_document_ref: ExternalDocumentRef) -> ExternalMap: - external_id: str = external_document_ref.document_ref_id verified_using: List[Hash] = [bump_checksum(external_document_ref.checksum)] - location_hint: str = external_document_ref.document_uri - return ExternalMap(external_id, verified_using, location_hint) + return ExternalMap( + external_id=external_document_ref.document_ref_id, + verified_using=verified_using, + location_hint=external_document_ref.document_uri, + ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/file.py b/src/spdx_tools/spdx3/bump_from_spdx2/file.py index 3e8cba161..8273d05eb 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/file.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/file.py @@ -13,7 +13,6 @@ def bump_file( spdx2_file: Spdx2_File, payload: Payload, creation_information: CreationInformation, document_namespace: str ): spdx_id = "#".join([document_namespace, spdx2_file.spdx_id]) - name = spdx2_file.name integrity_methods = [bump_checksum(checksum) for checksum in spdx2_file.checksums] # file.checksums -> file.verifiedUsing # file.file_types -> file.content_type (MediaType with Cardinality 1) @@ -24,11 +23,16 @@ def bump_file( "missing definition for license profile", ) - comment = spdx2_file.comment print_missing_conversion( "file.notice, file.contributors, file.attribution_texts", 0, "missing definition for license profile" ) payload.add_element( - File(spdx_id, creation_info=creation_information, name=name, comment=comment, verified_using=integrity_methods) + File( + spdx_id, + creation_info=creation_information, + name=spdx2_file.name, + comment=spdx2_file.comment, + verified_using=integrity_methods, + ) ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index c53d6defe..2aba0a172 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -24,9 +24,7 @@ def bump_package( spdx2_package: Spdx2_Package, payload: Payload, creation_information: CreationInformation, document_namespace: str ): spdx_id = "#".join([document_namespace, spdx2_package.spdx_id]) - name = spdx2_package.name download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") - package_version = spdx2_package.version # package.file_name -> ? print_missing_conversion("package2.file_name", 0) # package.supplier -> Relationship, suppliedBy? @@ -38,20 +36,12 @@ def bump_package( print_missing_conversion("package2.verification_code", 1, "of IntegrityMethod") # package.checksums -> package.verified_using integrity_methods = [bump_checksum(checksum) for checksum in spdx2_package.checksums] - homepage = spdx2_package.homepage - source_info = spdx2_package.source_info print_missing_conversion( "package2.license_concluded, package2.license_info_from_files, package2.license_declared, " "package2.license_comment, package2.copyright_text", 0, "and missing definition of license profile", ) - summary = spdx2_package.summary - description = spdx2_package.description - comment = spdx2_package.comment - built_time = spdx2_package.built_date - release_time = spdx2_package.release_date - valid_until_time = spdx2_package.valid_until_date external_references = [] external_identifiers = [] @@ -80,23 +70,23 @@ def bump_package( Package( spdx_id, creation_information, - name, - summary=summary, - description=description, - comment=comment, + spdx2_package.name, + summary=spdx2_package.summary, + description=spdx2_package.description, + comment=spdx2_package.comment, verified_using=integrity_methods, external_references=external_references, external_identifier=external_identifiers, originated_by=originated_by_spdx_id, - built_time=built_time, - release_time=release_time, - valid_until_time=valid_until_time, + built_time=spdx2_package.built_date, + release_time=spdx2_package.release_date, + valid_until_time=spdx2_package.valid_until_date, package_purpose=package_purpose, - package_version=package_version, + package_version=spdx2_package.version, download_location=download_location, package_url=package_url, - homepage=homepage, - source_info=source_info, + homepage=spdx2_package.homepage, + source_info=spdx2_package.source_info, ) ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py index 3ec263736..874721ee4 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -37,7 +37,6 @@ def bump_relationship( else: from_element = spdx2_relationship.spdx_element_id to = [spdx2_relationship.related_spdx_element_id] - comment = spdx2_relationship.comment payload.add_element( Relationship( @@ -46,7 +45,7 @@ def bump_relationship( from_element, to, relationship_type, - comment=comment, + comment=spdx2_relationship.comment, completeness=completeness, ) ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index 0f732ab9b..1b41c9178 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -13,16 +13,12 @@ def bump_snippet( ): spdx_id = "#".join([document_namespace, spdx2_snippet.spdx_id]) print_missing_conversion("snippet.file_spdx_id", 0) - byte_range = spdx2_snippet.byte_range - line_range = spdx2_snippet.line_range print_missing_conversion( "snippet.concluded_license, snippet.license_info_in_snippet, snippet.license_comment," "snippet.copyright_text", 0, "missing definitions for license profile", ) - comment = spdx2_snippet.comment - name = spdx2_snippet.name print_missing_conversion("snippet.attribution_texts", 0, "missing definitions for license profile") @@ -30,9 +26,9 @@ def bump_snippet( Snippet( spdx_id=spdx_id, creation_info=creation_information, - name=name, - comment=comment, - byte_range=byte_range, - line_range=line_range, + name=spdx2_snippet.name, + comment=spdx2_snippet.comment, + byte_range=spdx2_snippet.byte_range, + line_range=spdx2_snippet.line_range, ) ) From e49404ad907f2e8441629e16967cce512cd074e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 20 Apr 2023 16:48:01 +0200 Subject: [PATCH 181/354] make lists non-optional in model classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/model/agent.py | 6 +++--- src/spdx_tools/spdx3/model/annotation.py | 6 +++--- src/spdx_tools/spdx3/model/bom.py | 10 +++++----- src/spdx_tools/spdx3/model/bundle.py | 10 +++++----- src/spdx_tools/spdx3/model/element.py | 6 +++--- src/spdx_tools/spdx3/model/external_map.py | 4 ++-- src/spdx_tools/spdx3/model/organization.py | 6 +++--- src/spdx_tools/spdx3/model/person.py | 6 +++--- src/spdx_tools/spdx3/model/relationship.py | 6 +++--- src/spdx_tools/spdx3/model/software/file.py | 11 ++++++----- src/spdx_tools/spdx3/model/software/package.py | 11 ++++++----- src/spdx_tools/spdx3/model/software/sbom.py | 10 +++++----- src/spdx_tools/spdx3/model/software/snippet.py | 11 ++++++----- src/spdx_tools/spdx3/model/software_agent.py | 6 +++--- src/spdx_tools/spdx3/model/spdx_collection.py | 6 +++--- src/spdx_tools/spdx3/model/spdx_document.py | 10 +++++----- src/spdx_tools/spdx3/model/tool.py | 6 +++--- tests/spdx3/model/software/test_file.py | 3 +-- tests/spdx3/model/software/test_package.py | 3 +-- tests/spdx3/model/test_bundle.py | 3 +-- 20 files changed, 70 insertions(+), 70 deletions(-) diff --git a/src/spdx_tools/spdx3/model/agent.py b/src/spdx_tools/spdx3/model/agent.py index 827a94d58..50afb99cf 100644 --- a/src/spdx_tools/spdx3/model/agent.py +++ b/src/spdx_tools/spdx3/model/agent.py @@ -18,9 +18,9 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx_tools/spdx3/model/annotation.py b/src/spdx_tools/spdx3/model/annotation.py index 3a35374d0..d2db8aa2f 100644 --- a/src/spdx_tools/spdx3/model/annotation.py +++ b/src/spdx_tools/spdx3/model/annotation.py @@ -31,9 +31,9 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, content_type: Optional[str] = None, statement: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/bom.py b/src/spdx_tools/spdx3/model/bom.py index be28b5536..a32614042 100644 --- a/src/spdx_tools/spdx3/model/bom.py +++ b/src/spdx_tools/spdx3/model/bom.py @@ -31,12 +31,12 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, - imports: Optional[List[ExternalMap]] = None, + namespaces: List[NamespaceMap] = None, + imports: List[ExternalMap] = None, context: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx_tools/spdx3/model/bundle.py b/src/spdx_tools/spdx3/model/bundle.py index f23a86cdb..e6869cecb 100644 --- a/src/spdx_tools/spdx3/model/bundle.py +++ b/src/spdx_tools/spdx3/model/bundle.py @@ -30,12 +30,12 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, - imports: Optional[List[ExternalMap]] = None, + namespaces: List[NamespaceMap] = None, + imports: List[ExternalMap] = None, context: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx_tools/spdx3/model/element.py b/src/spdx_tools/spdx3/model/element.py index c5bcd0632..7abd88f34 100644 --- a/src/spdx_tools/spdx3/model/element.py +++ b/src/spdx_tools/spdx3/model/element.py @@ -17,9 +17,9 @@ class Element(ABC): summary: Optional[str] = None description: Optional[str] = None comment: Optional[str] = None - verified_using: Optional[List[IntegrityMethod]] = field(default_factory=list) - external_references: Optional[List[ExternalReference]] = field(default_factory=list) - external_identifier: Optional[List[ExternalIdentifier]] = field(default_factory=list) + verified_using: List[IntegrityMethod] = field(default_factory=list) + external_references: List[ExternalReference] = field(default_factory=list) + external_identifier: List[ExternalIdentifier] = field(default_factory=list) extension: None = None # placeholder for extension @abstractmethod diff --git a/src/spdx_tools/spdx3/model/external_map.py b/src/spdx_tools/spdx3/model/external_map.py index c26f96289..e5674f065 100644 --- a/src/spdx_tools/spdx3/model/external_map.py +++ b/src/spdx_tools/spdx3/model/external_map.py @@ -12,13 +12,13 @@ @dataclass_with_properties class ExternalMap: external_id: str # anyURI - verified_using: Optional[List[IntegrityMethod]] = field(default_factory=list) + verified_using: List[IntegrityMethod] = field(default_factory=list) location_hint: Optional[str] = None # anyURI def __init__( self, external_id: str, - verified_using: Optional[List[IntegrityMethod]] = None, + verified_using: List[IntegrityMethod] = None, location_hint: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx_tools/spdx3/model/organization.py b/src/spdx_tools/spdx3/model/organization.py index 0f204cb1f..19fec3cc5 100644 --- a/src/spdx_tools/spdx3/model/organization.py +++ b/src/spdx_tools/spdx3/model/organization.py @@ -18,9 +18,9 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx_tools/spdx3/model/person.py b/src/spdx_tools/spdx3/model/person.py index fe9bf338e..95a80d015 100644 --- a/src/spdx_tools/spdx3/model/person.py +++ b/src/spdx_tools/spdx3/model/person.py @@ -18,9 +18,9 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index beff233f9..82f600a23 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -78,9 +78,9 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, completeness: Optional[RelationshipCompleteness] = None, ): diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py index 001c4ed1c..29f9bbba5 100644 --- a/src/spdx_tools/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from dataclasses import field from datetime import datetime from typing import List, Optional @@ -19,7 +20,7 @@ @dataclass_with_properties class File(Artifact): content_identifier: Optional[str] = None # should be a valid URI - file_purpose: Optional[List[SoftwarePurpose]] = None + file_purpose: List[SoftwarePurpose] = field(default_factory=list) content_type: Optional[str] = None # placeholder for MediaType def __init__( @@ -30,16 +31,16 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, originated_by: Optional[str] = None, built_time: Optional[datetime] = None, release_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, content_identifier: Optional[str] = None, - file_purpose: Optional[List[SoftwarePurpose]] = None, + file_purpose: List[SoftwarePurpose] = None, content_type: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py index a1be702fb..12b4875e7 100644 --- a/src/spdx_tools/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from dataclasses import field from datetime import datetime from typing import List, Optional @@ -19,7 +20,7 @@ @dataclass_with_properties class Package(Artifact): content_identifier: Optional[str] = None # anyURI - package_purpose: Optional[List[SoftwarePurpose]] = None + package_purpose: List[SoftwarePurpose] = field(default_factory=list) package_version: Optional[str] = None download_location: Optional[str] = None # anyURI package_url: Optional[str] = None # anyURI @@ -34,16 +35,16 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, originated_by: Optional[str] = None, content_identifier: Optional[str] = None, built_time: Optional[datetime] = None, release_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, - package_purpose: Optional[List[SoftwarePurpose]] = None, + package_purpose: List[SoftwarePurpose] = None, package_version: Optional[str] = None, download_location: Optional[str] = None, package_url: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/sbom.py b/src/spdx_tools/spdx3/model/software/sbom.py index c3b568905..bbe1cb9ea 100644 --- a/src/spdx_tools/spdx3/model/software/sbom.py +++ b/src/spdx_tools/spdx3/model/software/sbom.py @@ -30,12 +30,12 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, - imports: Optional[List[ExternalMap]] = None, + namespaces: List[NamespaceMap] = None, + imports: List[ExternalMap] = None, context: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py index 9e8e05885..160090ad4 100644 --- a/src/spdx_tools/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from dataclasses import field from datetime import datetime from typing import List, Optional, Tuple @@ -19,7 +20,7 @@ @dataclass_with_properties class Snippet(Artifact): content_identifier: Optional[str] = None # anyURI - snippet_purpose: Optional[List[SoftwarePurpose]] = None + snippet_purpose: List[SoftwarePurpose] = field(default_factory=list) byte_range: Optional[Tuple[int, int]] = None line_range: Optional[Tuple[int, int]] = None @@ -31,16 +32,16 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, originated_by: Optional[str] = None, content_identifier: Optional[str] = None, built_time: Optional[datetime] = None, release_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, - snippet_purpose: Optional[List[SoftwarePurpose]] = None, + snippet_purpose: List[SoftwarePurpose] = None, byte_range: Optional[Tuple[int, int]] = None, line_range: Optional[Tuple[int, int]] = None, ): diff --git a/src/spdx_tools/spdx3/model/software_agent.py b/src/spdx_tools/spdx3/model/software_agent.py index 53f6cc934..05087d9a9 100644 --- a/src/spdx_tools/spdx3/model/software_agent.py +++ b/src/spdx_tools/spdx3/model/software_agent.py @@ -18,9 +18,9 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx_tools/spdx3/model/spdx_collection.py b/src/spdx_tools/spdx3/model/spdx_collection.py index 8e94e149e..733604464 100644 --- a/src/spdx_tools/spdx3/model/spdx_collection.py +++ b/src/spdx_tools/spdx3/model/spdx_collection.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod from dataclasses import field -from typing import List, Optional +from typing import List from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.spdx3.model import Element, ExternalMap, NamespaceMap @@ -15,8 +15,8 @@ class SpdxCollection(Element): # the __init__ method still raises an error if required fields are not set elements: List[str] = field(default_factory=list) root_elements: List[str] = field(default_factory=list) - namespaces: Optional[List[NamespaceMap]] = field(default_factory=list) - imports: Optional[List[ExternalMap]] = field(default_factory=list) + namespaces: List[NamespaceMap] = field(default_factory=list) + imports: List[ExternalMap] = field(default_factory=list) @abstractmethod def __init__(self): diff --git a/src/spdx_tools/spdx3/model/spdx_document.py b/src/spdx_tools/spdx3/model/spdx_document.py index be0f26a4d..6939e5d22 100644 --- a/src/spdx_tools/spdx3/model/spdx_document.py +++ b/src/spdx_tools/spdx3/model/spdx_document.py @@ -31,12 +31,12 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, - namespaces: Optional[List[NamespaceMap]] = None, - imports: Optional[List[ExternalMap]] = None, + namespaces: List[NamespaceMap] = None, + imports: List[ExternalMap] = None, context: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx_tools/spdx3/model/tool.py b/src/spdx_tools/spdx3/model/tool.py index 3ac27ada1..d707926ca 100644 --- a/src/spdx_tools/spdx3/model/tool.py +++ b/src/spdx_tools/spdx3/model/tool.py @@ -18,9 +18,9 @@ def __init__( summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, - verified_using: Optional[List[IntegrityMethod]] = None, - external_references: Optional[List[ExternalReference]] = None, - external_identifier: Optional[List[ExternalIdentifier]] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, extension: None = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index 49ee3a72d..5bd0aa594 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -41,8 +41,7 @@ def test_invalid_initialization(creation_information): 'SetterError File: type of argument "spdx_id" must be str; got int instead: 1', 'SetterError File: type of argument "content_identifier" must be one of (str, ' "NoneType); got int instead: 3", - 'SetterError File: type of argument "file_purpose" must be one of ' - "(List[spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got " + 'SetterError File: type of argument "file_purpose" must be a list; got ' "spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose instead: " "SoftwarePurpose.FILE", 'SetterError File: type of argument "content_type" must be one of (str, ' diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 859ea7514..55bbc0405 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -61,8 +61,7 @@ def test_invalid_initialization(creation_information): "(datetime.datetime, NoneType); got str instead: 2022-03-04T00:00:00Z", 'SetterError Package: type of argument "content_identifier" must be one of ' "(str, NoneType); got int instead: 3", - 'SetterError Package: type of argument "package_purpose" must be one of ' - "(List[spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose], NoneType); got " + 'SetterError Package: type of argument "package_purpose" must be a list; got ' "spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose instead: " "SoftwarePurpose.FILE", 'SetterError Package: type of argument "package_version" must be one of ' diff --git a/tests/spdx3/model/test_bundle.py b/tests/spdx3/model/test_bundle.py index b3c58e77b..6071985b9 100644 --- a/tests/spdx3/model/test_bundle.py +++ b/tests/spdx3/model/test_bundle.py @@ -37,7 +37,6 @@ def test_invalid_initialization(creation_information): 'SetterError Bundle: type of argument "spdx_id" must be str; got int instead: 4', 'SetterError Bundle: type of argument "elements" must be a list; got str ' "instead: spdx_id1", 'SetterError Bundle: type of argument "root_elements"[0] must be str; got int ' "instead: [42]", - 'SetterError Bundle: type of argument "namespaces" must be one of ' - "(List[spdx_tools.spdx3.model.namespace_map.NamespaceMap], NoneType); got bool instead: True", + 'SetterError Bundle: type of argument "namespaces" must be a list; ' "got bool instead: True", 'SetterError Bundle: type of argument "context" must be one of (str, ' "NoneType); got list instead: ['yes']", ] From 822f5bf34e86d0836ed9e739abfca1bda0a39657 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 20 Apr 2023 14:21:04 +0200 Subject: [PATCH 182/354] [issue_602] fix package bump if originator is NOASSERTION or not provided Signed-off-by: Meret Behrens --- .../spdx3/bump_from_spdx2/package.py | 6 +++++- tests/spdx3/bump/test_package_bump.py | 19 ++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index 2aba0a172..226c556c7 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -16,6 +16,7 @@ ) from spdx_tools.spdx3.model.software import Package, SoftwarePurpose from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import Actor as Spdx2_Actor from spdx_tools.spdx.model.package import ExternalPackageRef from spdx_tools.spdx.model.package import Package as Spdx2_Package @@ -29,7 +30,10 @@ def bump_package( print_missing_conversion("package2.file_name", 0) # package.supplier -> Relationship, suppliedBy? print_missing_conversion("package2.supplier", 1, "of relationships") - originated_by_spdx_id = bump_actor(spdx2_package.originator, payload, creation_information, document_namespace) + if isinstance(spdx2_package.originator, Spdx2_Actor): + originated_by_spdx_id = bump_actor(spdx2_package.originator, payload, creation_information, document_namespace) + else: + originated_by_spdx_id = None # package.files_analyzed -> ? print_missing_conversion("package2.files_analyzed", 0) # package.verification_code -> package.verified_using diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index f5f6d59d2..a84a9fc80 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -3,26 +3,38 @@ # SPDX-License-Identifier: Apache-2.0 from unittest import TestCase, mock +import pytest + from spdx_tools.spdx3.bump_from_spdx2.package import bump_package from spdx_tools.spdx3.model import ExternalIdentifier, ExternalIdentifierType, ExternalReference, ExternalReferenceType from spdx_tools.spdx3.model.software import Package from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import SpdxNoAssertion from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory from spdx_tools.spdx.model.package import Package as Spdx2_Package -from tests.spdx.fixtures import package_fixture +from tests.spdx.fixtures import actor_fixture, package_fixture +@pytest.mark.parametrize( + "originator, expected_originator", + [ + (actor_fixture(name="originatorName"), "https://doc.namespace#SPDXRef-Actor-originatorName-some@mail.com"), + (None, None), + (SpdxNoAssertion(), None), + ], +) @mock.patch("spdx_tools.spdx3.model.CreationInformation") -def test_bump_package(creation_information): +def test_bump_package(creation_information, originator, expected_originator): payload = Payload() document_namespace = "https://doc.namespace" spdx2_package: Spdx2_Package = package_fixture( + originator=originator, external_references=[ ExternalPackageRef( ExternalPackageRefCategory.SECURITY, "advisory", "advisory_locator", "advisory_comment" ), ExternalPackageRef(ExternalPackageRefCategory.PERSISTENT_ID, "swh", "swh_locator", "swh_comment"), - ] + ], ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" @@ -40,6 +52,7 @@ def test_bump_package(creation_information): ] assert package.download_location == spdx2_package.download_location assert package.package_version == spdx2_package.version + assert package.originated_by == expected_originator assert package.homepage == spdx2_package.homepage assert package.source_info == spdx2_package.source_info assert package.built_time == spdx2_package.built_date From a3f3cee245c08d2f7bef5441ce7788185f286708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 20 Apr 2023 12:34:01 +0200 Subject: [PATCH 183/354] [issue-426] add Dataset class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../spdx3/model/dataset/__init__.py | 1 + src/spdx_tools/spdx3/model/dataset/dataset.py | 59 +++++++++++++++++++ tests/spdx3/model/dataset/__init__.py | 0 tests/spdx3/model/dataset/test_dataset.py | 48 +++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 src/spdx_tools/spdx3/model/dataset/__init__.py create mode 100644 src/spdx_tools/spdx3/model/dataset/dataset.py create mode 100644 tests/spdx3/model/dataset/__init__.py create mode 100644 tests/spdx3/model/dataset/test_dataset.py diff --git a/src/spdx_tools/spdx3/model/dataset/__init__.py b/src/spdx_tools/spdx3/model/dataset/__init__.py new file mode 100644 index 000000000..7ccfa13e7 --- /dev/null +++ b/src/spdx_tools/spdx3/model/dataset/__init__.py @@ -0,0 +1 @@ +from spdx_tools.spdx3.model.dataset.dataset import Dataset, DatasetAvailabilityType, ConfidentialityLevelType diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py new file mode 100644 index 000000000..ff9738702 --- /dev/null +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -0,0 +1,59 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from enum import Enum, auto +from typing import Dict, List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values + + +class ConfidentialityLevelType(Enum): + RED = auto() + AMBER = auto() + GREEN = auto() + CLEAR = auto() + + +class DatasetAvailabilityType(Enum): + DIRECT_DOWNLOAD = auto() + SCRAPING_SCRIPT = auto() + QUERY = auto() + CLICKTHROUGH = auto() + REGISTRATION = auto() + + +@dataclass_with_properties +class Dataset: + data_collection_process: Optional[str] = None + intended_use: Optional[str] = None + dataset_size: Optional[int] = None + dataset_noise: Optional[str] = None + data_preprocessing_steps: Optional[str] = None + sensors: Dict[str, Optional[str]] = field(default_factory=dict) + known_biases: Optional[str] = None + sensitive_personal_information: Optional[bool] = None + anonymization_method_used: List[str] = field(default_factory=list) + confidentiality_level: Optional[ConfidentialityLevelType] = None + dataset_update_mechanism: Optional[str] = None + dataset_availability: Optional[DatasetAvailabilityType] = None + + def __init__( + self, + data_collection_process: Optional[str] = None, + intended_use: Optional[str] = None, + dataset_size: Optional[int] = None, + dataset_noise: Optional[str] = None, + data_preprocessing_steps: Optional[str] = None, + sensors: Dict[str, Optional[str]] = None, + known_biases: Optional[str] = None, + sensitive_personal_information: Optional[bool] = None, + anonymization_method_used: List[str] = None, + confidentiality_level: Optional[ConfidentialityLevelType] = None, + dataset_update_mechanism: Optional[str] = None, + dataset_availability: Optional[DatasetAvailabilityType] = None, + ): + sensors = {} if sensors is None else sensors + anonymization_method_used = [] if anonymization_method_used is None else anonymization_method_used + check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/model/dataset/__init__.py b/tests/spdx3/model/dataset/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/model/dataset/test_dataset.py b/tests/spdx3/model/dataset/test_dataset.py new file mode 100644 index 000000000..b44bf97da --- /dev/null +++ b/tests/spdx3/model/dataset/test_dataset.py @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model.dataset import ConfidentialityLevelType, Dataset, DatasetAvailabilityType + + +def test_correct_initialization(): + dataset = Dataset( + "data collection process", + "intended use", + 420000, + "dataset noise", + "data preprocessing steps", + {"sensor1": "some value"}, + "known biases", + True, + ["anonymization method"], + ConfidentialityLevelType.RED, + "update mechanism", + DatasetAvailabilityType.QUERY, + ) + + assert dataset.data_collection_process == "data collection process" + assert dataset.intended_use == "intended use" + assert dataset.dataset_size == 420000 + assert dataset.dataset_noise == "dataset noise" + assert dataset.data_preprocessing_steps == "data preprocessing steps" + assert dataset.sensors == {"sensor1": "some value"} + assert dataset.known_biases == "known biases" + assert dataset.sensitive_personal_information + assert dataset.anonymization_method_used == ["anonymization method"] + assert dataset.confidentiality_level == ConfidentialityLevelType.RED + assert dataset.dataset_update_mechanism == "update mechanism" + assert dataset.dataset_availability == DatasetAvailabilityType.QUERY + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + Dataset(sensors={"sensor1": "value", "sensor2": 250}) + + assert err.value.args[0] == [ + ( + "SetterError Dataset: type of argument \"sensors\"['sensor2'] must be one of " + "(str, NoneType); got int instead: {'sensor1': 'value', 'sensor2': 250}" + ) + ] From 78bf4b73323339865c3cfc51a99916a450ffb884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 24 Apr 2023 14:54:02 +0200 Subject: [PATCH 184/354] [issue-426] make Dataset a subclass of Package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/model/dataset/dataset.py | 30 +++++++++++++- tests/spdx3/model/dataset/test_dataset.py | 40 +++++++++++++------ 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py index ff9738702..3a00232d5 100644 --- a/src/spdx_tools/spdx3/model/dataset/dataset.py +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -2,11 +2,14 @@ # # SPDX-License-Identifier: Apache-2.0 from dataclasses import field +from datetime import datetime from enum import Enum, auto from typing import Dict, List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model.software import Package, SoftwarePurpose class ConfidentialityLevelType(Enum): @@ -25,7 +28,7 @@ class DatasetAvailabilityType(Enum): @dataclass_with_properties -class Dataset: +class Dataset(Package): data_collection_process: Optional[str] = None intended_use: Optional[str] = None dataset_size: Optional[int] = None @@ -41,6 +44,27 @@ class Dataset: def __init__( self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + originated_by: Optional[str] = None, + content_identifier: Optional[str] = None, + built_time: Optional[datetime] = None, + release_time: Optional[datetime] = None, + valid_until_time: Optional[datetime] = None, + package_purpose: List[SoftwarePurpose] = None, + package_version: Optional[str] = None, + download_location: Optional[str] = None, + package_url: Optional[str] = None, + homepage: Optional[str] = None, + source_info: Optional[str] = None, data_collection_process: Optional[str] = None, intended_use: Optional[str] = None, dataset_size: Optional[int] = None, @@ -54,6 +78,10 @@ def __init__( dataset_update_mechanism: Optional[str] = None, dataset_availability: Optional[DatasetAvailabilityType] = None, ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + package_purpose = [] if package_purpose is None else package_purpose sensors = {} if sensors is None else sensors anonymization_method_used = [] if anonymization_method_used is None else anonymization_method_used check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/model/dataset/test_dataset.py b/tests/spdx3/model/dataset/test_dataset.py index b44bf97da..a821716d7 100644 --- a/tests/spdx3/model/dataset/test_dataset.py +++ b/tests/spdx3/model/dataset/test_dataset.py @@ -1,25 +1,33 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + import pytest +from semantic_version import Version +from spdx_tools.spdx3.model import CreationInformation from spdx_tools.spdx3.model.dataset import ConfidentialityLevelType, Dataset, DatasetAvailabilityType def test_correct_initialization(): dataset = Dataset( - "data collection process", - "intended use", - 420000, - "dataset noise", - "data preprocessing steps", - {"sensor1": "some value"}, - "known biases", - True, - ["anonymization method"], - ConfidentialityLevelType.RED, - "update mechanism", - DatasetAvailabilityType.QUERY, + "some_spdx_id", + CreationInformation( + Version("3.0.0"), datetime(2023, 1, 11, 16, 21), [], [], ["core", "software"], "CC0", "some comment" + ), + data_collection_process="data collection process", + intended_use="intended use", + dataset_size=420000, + dataset_noise="dataset noise", + data_preprocessing_steps="data preprocessing steps", + sensors={"sensor1": "some value"}, + known_biases="known biases", + sensitive_personal_information=True, + anonymization_method_used=["anonymization method"], + confidentiality_level=ConfidentialityLevelType.RED, + dataset_update_mechanism="update mechanism", + dataset_availability=DatasetAvailabilityType.QUERY, ) assert dataset.data_collection_process == "data collection process" @@ -38,7 +46,13 @@ def test_correct_initialization(): def test_invalid_initialization(): with pytest.raises(TypeError) as err: - Dataset(sensors={"sensor1": "value", "sensor2": 250}) + Dataset( + "some_spdx_id", + CreationInformation( + Version("3.0.0"), datetime(2023, 1, 11, 16, 21), [], [], ["core", "software"], "CC0", "some comment" + ), + sensors={"sensor1": "value", "sensor2": 250}, + ) assert err.value.args[0] == [ ( From 5c8120039a18ccee24b971d5dfad170b6c003884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 20 Apr 2023 16:29:12 +0200 Subject: [PATCH 185/354] [issue-426] add AIPackage class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/README.md | 2 +- src/spdx_tools/spdx3/model/ai/__init__.py | 4 + src/spdx_tools/spdx3/model/ai/ai_package.py | 89 +++++++++++++++++++ .../spdx3/writer/console/ai/__init__.py | 0 .../writer/console/ai/ai_package_writer.py | 29 ++++++ .../spdx3/writer/console/console.py | 5 ++ .../writer/console/software/package_writer.py | 5 +- tests/spdx3/model/ai/__init__.py | 0 tests/spdx3/model/ai/test_ai_package.py | 65 ++++++++++++++ 9 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 src/spdx_tools/spdx3/model/ai/__init__.py create mode 100644 src/spdx_tools/spdx3/model/ai/ai_package.py create mode 100644 src/spdx_tools/spdx3/writer/console/ai/__init__.py create mode 100644 src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py create mode 100644 tests/spdx3/model/ai/__init__.py create mode 100644 tests/spdx3/model/ai/test_ai_package.py diff --git a/src/spdx_tools/spdx3/README.md b/src/spdx_tools/spdx3/README.md index 2f0f9021c..1ffec5786 100644 --- a/src/spdx_tools/spdx3/README.md +++ b/src/spdx_tools/spdx3/README.md @@ -1 +1 @@ -This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: 5cc54f4d8a44d4082172940f6b81fdd0edc798df). +This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: b488a38a075349c90d9a5d085a5a14cf3c3b91f2). diff --git a/src/spdx_tools/spdx3/model/ai/__init__.py b/src/spdx_tools/spdx3/model/ai/__init__.py new file mode 100644 index 000000000..1f711abf6 --- /dev/null +++ b/src/spdx_tools/spdx3/model/ai/__init__.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.model.ai.ai_package import AIPackage diff --git a/src/spdx_tools/spdx3/model/ai/ai_package.py b/src/spdx_tools/spdx3/model/ai/ai_package.py new file mode 100644 index 000000000..3d818dcdf --- /dev/null +++ b/src/spdx_tools/spdx3/model/ai/ai_package.py @@ -0,0 +1,89 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from datetime import datetime +from enum import Enum, auto +from typing import Dict, List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model.software import Package, SoftwarePurpose + + +class SafetyRiskAssessmentType(Enum): + SERIOUS = auto() + HIGH = auto() + MEDIUM = auto() + LOW = auto() + + +@dataclass_with_properties +class AIPackage(Package): + energy_consumption: Optional[str] = None + standards_compliance: List[str] = field(default_factory=list) + limitations: Optional[str] = None + type_of_model: List[str] = field(default_factory=list) + information_about_training: Optional[str] = None + information_about_application: Optional[str] = None + hyperparameters: Dict[str, Optional[str]] = field(default_factory=dict) + data_preprocessing_steps: Optional[str] = None + model_explainability_mechanisms: Optional[str] = None + sensitive_personal_information: Optional[bool] = None + metrics_decision_thresholds: Dict[str, Optional[str]] = field(default_factory=dict) + metrics: Dict[str, Optional[str]] = field(default_factory=dict) + domain: List[str] = field(default_factory=list) + autonomy_type: Optional[bool] = None + safety_risk_assessment: Optional[SafetyRiskAssessmentType] = None + + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + originated_by: Optional[str] = None, + content_identifier: Optional[str] = None, + built_time: Optional[datetime] = None, + release_time: Optional[datetime] = None, + valid_until_time: Optional[datetime] = None, + package_purpose: List[SoftwarePurpose] = None, + package_version: Optional[str] = None, + download_location: Optional[str] = None, + package_url: Optional[str] = None, + homepage: Optional[str] = None, + source_info: Optional[str] = None, + energy_consumption: Optional[str] = None, + standards_compliance: List[str] = None, + limitations: Optional[str] = None, + type_of_model: List[str] = None, + information_about_training: Optional[str] = None, + information_about_application: Optional[str] = None, + hyperparameters: Dict[str, Optional[str]] = None, + data_preprocessing_steps: Optional[str] = None, + model_explainability_mechanisms: Optional[str] = None, + sensitive_personal_information: Optional[bool] = None, + metrics_decision_thresholds: Dict[str, Optional[str]] = None, + metrics: Dict[str, Optional[str]] = None, + domain: List[str] = None, + autonomy_type: Optional[bool] = None, + safety_risk_assessment: Optional[SafetyRiskAssessmentType] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + package_purpose = [] if package_purpose is None else package_purpose + standards_compliance = [] if standards_compliance is None else standards_compliance + type_of_model = [] if type_of_model is None else type_of_model + hyperparameters = {} if hyperparameters is None else hyperparameters + metrics_decision_thresholds = {} if metrics_decision_thresholds is None else metrics_decision_thresholds + metrics = {} if metrics is None else metrics + domain = [] if domain is None else domain + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/writer/console/ai/__init__.py b/src/spdx_tools/spdx3/writer/console/ai/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py b/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py new file mode 100644 index 000000000..353f805e3 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import TextIO + +from spdx_tools.spdx3.model.ai import AIPackage +from spdx_tools.spdx3.writer.console.console import write_dict, write_value +from spdx_tools.spdx3.writer.console.software.package_writer import write_package + + +def write_ai_package(ai_package: AIPackage, text_output: TextIO): + text_output.write("## AI Package\n") + write_package(ai_package, text_output, False) + + write_value("energy_consumption", ai_package.energy_consumption, text_output) + write_value("standards_compliance", ", ".join([entry for entry in ai_package.standards_compliance]), text_output) + write_value("limitations", ai_package.limitations, text_output) + write_value("type_of_model", ", ".join([entry for entry in ai_package.type_of_model]), text_output) + write_value("information_about_training", ai_package.information_about_training, text_output) + write_value("information_about_application", ai_package.information_about_application, text_output) + write_dict("hyperparameters", ai_package.hyperparameters, text_output) + write_value("data_preprocessing_steps", ai_package.data_preprocessing_steps, text_output) + write_value("model_explainability_mechanisms", ai_package.model_explainability_mechanisms, text_output) + write_value("sensitive_personal_information", ai_package.sensitive_personal_information, text_output) + write_dict("metrics_decision_thresholds", ai_package.metrics_decision_thresholds, text_output) + write_dict("metrics", ai_package.metrics, text_output) + write_value("domain", ", ".join([entry for entry in ai_package.domain]), text_output) + write_value("autonomy_type", ai_package.autonomy_type, text_output) + write_value("safety_risk_assessment", ai_package.safety_risk_assessment, text_output) diff --git a/src/spdx_tools/spdx3/writer/console/console.py b/src/spdx_tools/spdx3/writer/console/console.py index 4cb90b344..99000e36c 100644 --- a/src/spdx_tools/spdx3/writer/console/console.py +++ b/src/spdx_tools/spdx3/writer/console/console.py @@ -14,3 +14,8 @@ def write_value(tag: str, value: Optional[Union[bool, str]], out: TextIO, indent out.write(f"\t{tag}: {value}\n") else: out.write(f"{tag}: {value}\n") + + +def write_dict(tag: str, dictionary: dict, out: TextIO): + for key, value in dictionary: + out.write(f'{tag}: "{key}": "{value}"') diff --git a/src/spdx_tools/spdx3/writer/console/software/package_writer.py b/src/spdx_tools/spdx3/writer/console/software/package_writer.py index 2e7535c2a..6397ad303 100644 --- a/src/spdx_tools/spdx3/writer/console/software/package_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/package_writer.py @@ -8,8 +8,9 @@ from spdx_tools.spdx3.writer.console.console import write_value -def write_package(package: Package, text_output: TextIO): - text_output.write("## Package\n") +def write_package(package: Package, text_output: TextIO, heading: bool = True): + if heading: + text_output.write("## Package\n") write_artifact_properties(package, text_output) write_value("content_identifier", package.content_identifier, text_output) write_value("package_purpose", ", ".join([purpose.name for purpose in package.package_purpose]), text_output) diff --git a/tests/spdx3/model/ai/__init__.py b/tests/spdx3/model/ai/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/model/ai/test_ai_package.py b/tests/spdx3/model/ai/test_ai_package.py new file mode 100644 index 000000000..cc2fd3abe --- /dev/null +++ b/tests/spdx3/model/ai/test_ai_package.py @@ -0,0 +1,65 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import mock + +import pytest + +from spdx_tools.spdx3.model.ai import AIPackage +from spdx_tools.spdx3.model.ai.ai_package import SafetyRiskAssessmentType + + +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_correct_initialization(creation_information): + ai_package = AIPackage( + "some_spdx_id", + creation_information, + energy_consumption="energy consumption", + standards_compliance=["some standard"], + limitations="limitation", + type_of_model=["model type"], + information_about_training="training info", + information_about_application="app info", + hyperparameters={"param": "value"}, + data_preprocessing_steps="preprocessing steps", + model_explainability_mechanisms="mechanism", + sensitive_personal_information=True, + metrics_decision_thresholds={"metric1": "threshold", "metric2": None}, + metrics={"metric1": "value1", "metric2": None}, + domain=["domain"], + autonomy_type=True, + safety_risk_assessment=SafetyRiskAssessmentType.HIGH, + ) + + assert ai_package.energy_consumption == "energy consumption" + assert ai_package.standards_compliance == ["some standard"] + assert ai_package.limitations == "limitation" + assert ai_package.type_of_model == ["model type"] + assert ai_package.information_about_training == "training info" + assert ai_package.information_about_application == "app info" + assert ai_package.hyperparameters == {"param": "value"} + assert ai_package.data_preprocessing_steps == "preprocessing steps" + assert ai_package.model_explainability_mechanisms == "mechanism" + assert ai_package.sensitive_personal_information + assert ai_package.metrics_decision_thresholds == {"metric1": "threshold", "metric2": None} + assert ai_package.metrics == {"metric1": "value1", "metric2": None} + assert ai_package.domain == ["domain"] + assert ai_package.autonomy_type + assert ai_package.safety_risk_assessment == SafetyRiskAssessmentType.HIGH + + +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_invalid_initialization(creation_information): + with pytest.raises(TypeError) as err: + AIPackage( + "some_spdx_id", + creation_information, + metrics={"metric1": "value", "metric2": 250}, + ) + + assert err.value.args[0] == [ + ( + "SetterError AIPackage: type of argument \"metrics\"['metric2'] must be one of " + "(str, NoneType); got int instead: {'metric1': 'value', 'metric2': 250}" + ) + ] From 488df78d8364add6ccac2b501831fd99a8241b91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 24 Apr 2023 14:30:44 +0200 Subject: [PATCH 186/354] [issue-426] add Build class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/model/build/__init__.py | 4 ++ src/spdx_tools/spdx3/model/build/build.py | 63 ++++++++++++++++++++ tests/spdx3/model/build/__init__.py | 0 tests/spdx3/model/build/test_build.py | 55 +++++++++++++++++ tests/spdx3/model/dataset/test_dataset.py | 22 +++---- 5 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 src/spdx_tools/spdx3/model/build/__init__.py create mode 100644 src/spdx_tools/spdx3/model/build/build.py create mode 100644 tests/spdx3/model/build/__init__.py create mode 100644 tests/spdx3/model/build/test_build.py diff --git a/src/spdx_tools/spdx3/model/build/__init__.py b/src/spdx_tools/spdx3/model/build/__init__.py new file mode 100644 index 000000000..765cf3c2a --- /dev/null +++ b/src/spdx_tools/spdx3/model/build/__init__.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.model.build.build import Build diff --git a/src/spdx_tools/spdx3/model/build/build.py b/src/spdx_tools/spdx3/model/build/build.py new file mode 100644 index 000000000..21da4e261 --- /dev/null +++ b/src/spdx_tools/spdx3/model/build/build.py @@ -0,0 +1,63 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from datetime import datetime +from typing import Dict, List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInformation, + Element, + ExternalIdentifier, + ExternalReference, + Hash, + IntegrityMethod, +) + + +@dataclass_with_properties +class Build(Element): + build_type: str = None + build_id: Optional[str] = None + config_source_entrypoint: List[str] = field(default_factory=list) + config_source_uri: List[str] = field(default_factory=list) + config_source_digest: List[Hash] = field(default_factory=list) + parameters: Dict[str, str] = field(default_factory=dict) + build_start: Optional[datetime] = None + build_end: Optional[datetime] = None + environment: Dict[str, str] = field(default_factory=dict) + + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + build_type: str, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + build_id: Optional[str] = None, + config_source_entrypoint: List[str] = None, + config_source_uri: List[str] = None, + config_source_digest: List[Hash] = None, + parameters: Dict[str, str] = None, + build_start: Optional[datetime] = None, + build_end: Optional[datetime] = None, + environment: Dict[str, str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + config_source_entrypoint = [] if config_source_entrypoint is None else config_source_entrypoint + config_source_uri = [] if config_source_uri is None else config_source_uri + config_source_digest = [] if config_source_digest is None else config_source_digest + parameters = {} if parameters is None else parameters + environment = {} if environment is None else environment + + check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/model/build/__init__.py b/tests/spdx3/model/build/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/model/build/test_build.py b/tests/spdx3/model/build/test_build.py new file mode 100644 index 000000000..2e6e38b1c --- /dev/null +++ b/tests/spdx3/model/build/test_build.py @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from unittest import mock + +import pytest + +from spdx_tools.spdx3.model import Hash, HashAlgorithm +from spdx_tools.spdx3.model.build import Build + + +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_correct_initialization(creation_information): + build = Build( + "some_spdx_id", + creation_information, + build_type="build type", + build_id="build id", + config_source_entrypoint=["entrypoint"], + config_source_uri=["uri"], + config_source_digest=[Hash(HashAlgorithm.MD2, "abcdef")], + parameters={"param1": "value1"}, + build_start=datetime(2023, 1, 1), + build_end=datetime(2023, 2, 2), + environment={"param2": "value2"}, + ) + + assert build.build_type == "build type" + assert build.build_id == "build id" + assert build.config_source_entrypoint == ["entrypoint"] + assert build.config_source_uri == ["uri"] + assert build.config_source_digest == [Hash(HashAlgorithm.MD2, "abcdef")] + assert build.parameters == {"param1": "value1"} + assert build.build_start == datetime(2023, 1, 1) + assert build.build_end == datetime(2023, 2, 2) + assert build.environment == {"param2": "value2"} + + +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_invalid_initialization(creation_information): + with pytest.raises(TypeError) as err: + Build( + "some_spdx_id", + creation_information, + build_type="build type", + config_source_digest=["hash_value"], + ) + + assert err.value.args[0] == [ + ( + "SetterError Build: type of argument \"config_source_digest\"[0] must be spdx_tools.spdx3.model.hash.Hash;" + " got str instead: ['hash_value']" + ) + ] diff --git a/tests/spdx3/model/dataset/test_dataset.py b/tests/spdx3/model/dataset/test_dataset.py index a821716d7..a9b90c712 100644 --- a/tests/spdx3/model/dataset/test_dataset.py +++ b/tests/spdx3/model/dataset/test_dataset.py @@ -1,21 +1,18 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors +# SPDX-FileCopyrightText: 2023 spdx contributors # -# SPDX-License-Identifier: Apache-2.0 -from datetime import datetime +# SPDX-License-Identifier: Apache-2.0 +from unittest import mock import pytest -from semantic_version import Version -from spdx_tools.spdx3.model import CreationInformation from spdx_tools.spdx3.model.dataset import ConfidentialityLevelType, Dataset, DatasetAvailabilityType -def test_correct_initialization(): +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_correct_initialization(creation_information): dataset = Dataset( "some_spdx_id", - CreationInformation( - Version("3.0.0"), datetime(2023, 1, 11, 16, 21), [], [], ["core", "software"], "CC0", "some comment" - ), + creation_information, data_collection_process="data collection process", intended_use="intended use", dataset_size=420000, @@ -44,13 +41,12 @@ def test_correct_initialization(): assert dataset.dataset_availability == DatasetAvailabilityType.QUERY -def test_invalid_initialization(): +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Dataset( "some_spdx_id", - CreationInformation( - Version("3.0.0"), datetime(2023, 1, 11, 16, 21), [], [], ["core", "software"], "CC0", "some comment" - ), + creation_information, sensors={"sensor1": "value", "sensor2": 250}, ) From d257ed67b5d30027213200904854a56203efefd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 25 Apr 2023 12:10:31 +0200 Subject: [PATCH 187/354] [issue-434] add build writer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../spdx3/writer/console/build/__init__.py | 0 .../writer/console/build/build_writer.py | 28 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/spdx_tools/spdx3/writer/console/build/__init__.py create mode 100644 src/spdx_tools/spdx3/writer/console/build/build_writer.py diff --git a/src/spdx_tools/spdx3/writer/console/build/__init__.py b/src/spdx_tools/spdx3/writer/console/build/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/writer/console/build/build_writer.py b/src/spdx_tools/spdx3/writer/console/build/build_writer.py new file mode 100644 index 000000000..d621711a3 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/build/build_writer.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import TextIO + +from spdx_tools.spdx3.model.build import Build +from spdx_tools.spdx3.writer.console.console import write_dict, write_value +from spdx_tools.spdx3.writer.console.element_writer import write_element_properties +from spdx_tools.spdx3.writer.console.hash_writer import write_hash +from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading + + +def write_build(build: Build, text_output: TextIO): + text_output.write("## Build\n") + write_element_properties(build, text_output) + + write_value("build_type", build.build_type, text_output) + write_value("build_id", build.build_id, text_output) + write_value("config_source_entrypoint", ", ".join([entry for entry in build.config_source_entrypoint]), + text_output) + write_value("config_source_uri", ", ".join([entry for entry in build.config_source_uri]), text_output) + write_optional_heading(build.config_source_digest, "config_source_digest", text_output) + for digest_hash in build.config_source_digest: + write_hash(digest_hash, text_output, heading=False) + write_dict("parameters", build.parameters, text_output) + write_value("build_start", build.build_start, text_output) + write_value("build_end", build.build_end, text_output) + write_dict("environment", build.environment, text_output) From 098964c24c23b87fe390a2e112ae6b178866da68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 25 Apr 2023 17:06:38 +0200 Subject: [PATCH 188/354] [issue-434] add writer for Dataset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit also add AI, Dataset and Build to payload_writer.py Signed-off-by: Armin Tänzer --- .../spdx3/writer/console/dataset/__init__.py | 0 .../writer/console/dataset/dataset_writer.py | 28 +++++++++++++++++++ .../spdx3/writer/console/payload_writer.py | 9 ++++++ 3 files changed, 37 insertions(+) create mode 100644 src/spdx_tools/spdx3/writer/console/dataset/__init__.py create mode 100644 src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py diff --git a/src/spdx_tools/spdx3/writer/console/dataset/__init__.py b/src/spdx_tools/spdx3/writer/console/dataset/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py b/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py new file mode 100644 index 000000000..3e7b6ae23 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import TextIO + +from spdx_tools.spdx3.model.dataset import Dataset +from spdx_tools.spdx3.writer.console.console import write_dict, write_value +from spdx_tools.spdx3.writer.console.software.package_writer import write_package + + +def write_dataset(dataset: Dataset, text_output: TextIO): + text_output.write("## AI Package\n") + write_package(dataset, text_output, False) + + write_value("data_collection_process", dataset.data_collection_process, text_output) + write_value("intended_use", dataset.intended_use, text_output) + write_value("dataset_size", dataset.dataset_size, text_output) + write_value("dataset_noise", dataset.dataset_noise, text_output) + write_value("data_preprocessing_steps", dataset.data_preprocessing_steps, text_output) + write_dict("sensors", dataset.sensors, text_output) + write_value("known_biases", dataset.known_biases, text_output) + write_value("sensitive_personal_information", dataset.sensitive_personal_information, text_output) + write_value( + "anonymization_method_used", ", ".join([entry for entry in dataset.anonymization_method_used]), text_output + ) + write_value("confidentiality_level", dataset.confidentiality_level, text_output) + write_value("dataset_update_mechanism", dataset.dataset_update_mechanism, text_output) + write_value("dataset_availability", dataset.dataset_availability, text_output) diff --git a/src/spdx_tools/spdx3/writer/console/payload_writer.py b/src/spdx_tools/spdx3/writer/console/payload_writer.py index 2a91a4d90..49e4a4e62 100644 --- a/src/spdx_tools/spdx3/writer/console/payload_writer.py +++ b/src/spdx_tools/spdx3/writer/console/payload_writer.py @@ -14,12 +14,18 @@ SpdxDocument, Tool, ) +from spdx_tools.spdx3.model.ai import AIPackage +from spdx_tools.spdx3.model.build import Build +from spdx_tools.spdx3.model.dataset import Dataset from spdx_tools.spdx3.model.software import File, Package, Sbom, Snippet from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx3.writer.console.agent_writer import write_agent +from spdx_tools.spdx3.writer.console.ai.ai_package_writer import write_ai_package from spdx_tools.spdx3.writer.console.annotation_writer import write_annotation from spdx_tools.spdx3.writer.console.bom_writer import write_bom +from spdx_tools.spdx3.writer.console.build.build_writer import write_build from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle +from spdx_tools.spdx3.writer.console.dataset.dataset_writer import write_dataset from spdx_tools.spdx3.writer.console.relationship_writer import write_relationship from spdx_tools.spdx3.writer.console.software.file_writer import write_file from spdx_tools.spdx3.writer.console.software.package_writer import write_package @@ -42,6 +48,9 @@ Organization: write_agent, SoftwareAgent: write_agent, Tool: write_tool, + AIPackage: write_ai_package, + Dataset: write_dataset, + Build: write_build, } From 5e78c41174d460bdb26ee0481376db8d9aff5327 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 26 Apr 2023 10:45:59 +0200 Subject: [PATCH 189/354] generate output of missing conversion instead of raising an error to get the most possible information Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/bump_from_spdx2/annotation.py | 7 +++++-- .../spdx3/bump_from_spdx2/creation_information.py | 6 ++++-- src/spdx_tools/spdx3/bump_from_spdx2/package.py | 11 +++++++---- tests/spdx/data/SPDXJSONExample-v2.3.spdx.json | 2 +- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py index a43c89964..84e298cfb 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py @@ -4,6 +4,7 @@ from copy import deepcopy from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor +from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import Annotation, AnnotationType, CreationInformation from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.actor import ActorType @@ -28,9 +29,11 @@ def bump_annotation( if annotator.actor_type in [ActorType.PERSON, ActorType.ORGANIZATION]: creation_info.created_by = [creator_id] else: - raise NotImplementedError( + print_missing_conversion( + "Annotator", + 0, "The SPDX2 annotation is not of Type Person or Organization." - " This case leads to an invalid SPDX3 document and is currently not supported." + " This case leads to an invalid SPDX3 document and is currently not supported.", ) annotation_type: AnnotationType = AnnotationType[spdx2_annotation.annotation_type.name] diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py index 8694a695e..8d7b99db6 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py @@ -53,9 +53,11 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: tool_ids.append(bumped_actor_id) if not creator_ids: - raise NotImplementedError( + print_missing_conversion( + "Creators", + 0, "The SPDX2 creation_info does not contain creators of Type Person or Organization." - " This case leads to an invalid SPDX3 document and is currently not supported." + " This case leads to an invalid SPDX3 document and is currently not supported.", ) creation_information.created_by = creator_ids diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index 226c556c7..a7eef0e47 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Union +from typing import Optional, Union from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none @@ -112,15 +112,18 @@ def bump_package( } -def bump_external_package_ref(spdx2_external_ref: ExternalPackageRef) -> Union[ExternalReference, ExternalIdentifier]: +def bump_external_package_ref( + spdx2_external_ref: ExternalPackageRef, +) -> Optional[Union[ExternalReference, ExternalIdentifier]]: reference_type = spdx2_external_ref.reference_type locator = spdx2_external_ref.locator comment = spdx2_external_ref.comment if reference_type not in external_ref_type_map: - raise NotImplementedError( - f"Conversion of ExternalPackageRef of type {reference_type} is currently not supported." + print_missing_conversion( + reference_type, 0, f"Conversion of ExternalPackageRef of type {reference_type} is currently not supported." ) + return None id_or_ref_type = external_ref_type_map[reference_type] diff --git a/tests/spdx/data/SPDXJSONExample-v2.3.spdx.json b/tests/spdx/data/SPDXJSONExample-v2.3.spdx.json index 4b2057dfe..d4ee447de 100644 --- a/tests/spdx/data/SPDXJSONExample-v2.3.spdx.json +++ b/tests/spdx/data/SPDXJSONExample-v2.3.spdx.json @@ -286,4 +286,4 @@ "relationshipType" : "GENERATED_FROM", "relatedSpdxElement" : "SPDXRef-fromDoap-0" } ] -} \ No newline at end of file +} From b9e450cc3ee354df4b633c92294abd51227e9884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 26 Apr 2023 08:28:01 +0200 Subject: [PATCH 190/354] [issue-434] refactor debug writers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../writer/console/ai/ai_package_writer.py | 19 +++------------ .../spdx3/writer/console/annotation_writer.py | 7 +++--- .../spdx3/writer/console/artifact_writer.py | 7 +++--- .../writer/console/build/build_writer.py | 22 ++++++++---------- .../spdx3/writer/console/console.py | 23 +++++++++++-------- .../console/creation_information_writer.py | 2 +- .../writer/console/dataset/dataset_writer.py | 18 +++------------ .../spdx3/writer/console/element_writer.py | 4 ++-- .../console/external_identifier_writer.py | 5 ++-- .../console/external_reference_writer.py | 6 ++--- .../spdx3/writer/console/hash_writer.py | 2 +- .../writer/console/namespace_map_writer.py | 4 ++-- .../writer/console/relationship_writer.py | 6 ++--- .../writer/console/software/file_writer.py | 11 ++++++--- .../writer/console/software/package_writer.py | 14 ++++++----- .../writer/console/software/snippet_writer.py | 13 +++++++---- 16 files changed, 71 insertions(+), 92 deletions(-) diff --git a/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py b/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py index 353f805e3..0cebdf4f4 100644 --- a/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py +++ b/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py @@ -4,7 +4,7 @@ from typing import TextIO from spdx_tools.spdx3.model.ai import AIPackage -from spdx_tools.spdx3.writer.console.console import write_dict, write_value +from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx3.writer.console.software.package_writer import write_package @@ -12,18 +12,5 @@ def write_ai_package(ai_package: AIPackage, text_output: TextIO): text_output.write("## AI Package\n") write_package(ai_package, text_output, False) - write_value("energy_consumption", ai_package.energy_consumption, text_output) - write_value("standards_compliance", ", ".join([entry for entry in ai_package.standards_compliance]), text_output) - write_value("limitations", ai_package.limitations, text_output) - write_value("type_of_model", ", ".join([entry for entry in ai_package.type_of_model]), text_output) - write_value("information_about_training", ai_package.information_about_training, text_output) - write_value("information_about_application", ai_package.information_about_application, text_output) - write_dict("hyperparameters", ai_package.hyperparameters, text_output) - write_value("data_preprocessing_steps", ai_package.data_preprocessing_steps, text_output) - write_value("model_explainability_mechanisms", ai_package.model_explainability_mechanisms, text_output) - write_value("sensitive_personal_information", ai_package.sensitive_personal_information, text_output) - write_dict("metrics_decision_thresholds", ai_package.metrics_decision_thresholds, text_output) - write_dict("metrics", ai_package.metrics, text_output) - write_value("domain", ", ".join([entry for entry in ai_package.domain]), text_output) - write_value("autonomy_type", ai_package.autonomy_type, text_output) - write_value("safety_risk_assessment", ai_package.safety_risk_assessment, text_output) + for property_name in AIPackage.__annotations__.keys(): + write_value(property_name, getattr(ai_package, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/annotation_writer.py b/src/spdx_tools/spdx3/writer/console/annotation_writer.py index f5e4ac00b..8f5ce6c1d 100644 --- a/src/spdx_tools/spdx3/writer/console/annotation_writer.py +++ b/src/spdx_tools/spdx3/writer/console/annotation_writer.py @@ -11,7 +11,6 @@ def write_annotation(annotation: Annotation, text_output: TextIO): text_output.write("## Annotation\n") write_element_properties(annotation, text_output) - write_value("annotation_type", annotation.annotation_type.name, text_output) - write_value("subject", annotation.subject, text_output) - write_value("content_type", annotation.content_type, text_output) - write_value("statement", annotation.statement, text_output) + + for property_name in Annotation.__annotations__.keys(): + write_value(property_name, getattr(annotation, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/artifact_writer.py b/src/spdx_tools/spdx3/writer/console/artifact_writer.py index b873e4163..13467f289 100644 --- a/src/spdx_tools/spdx3/writer/console/artifact_writer.py +++ b/src/spdx_tools/spdx3/writer/console/artifact_writer.py @@ -10,7 +10,6 @@ def write_artifact_properties(artifact: Artifact, text_output: TextIO): write_element_properties(artifact, text_output) - write_value("originated_by", artifact.originated_by, text_output) - write_value("built_time", artifact.built_time, text_output) - write_value("release_time", artifact.release_time, text_output) - write_value("valid_until_time", artifact.valid_until_time, text_output) + + for property_name in Artifact.__annotations__.keys(): + write_value(property_name, getattr(artifact, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/build/build_writer.py b/src/spdx_tools/spdx3/writer/console/build/build_writer.py index d621711a3..77c3d47f7 100644 --- a/src/spdx_tools/spdx3/writer/console/build/build_writer.py +++ b/src/spdx_tools/spdx3/writer/console/build/build_writer.py @@ -4,7 +4,7 @@ from typing import TextIO from spdx_tools.spdx3.model.build import Build -from spdx_tools.spdx3.writer.console.console import write_dict, write_value +from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx3.writer.console.element_writer import write_element_properties from spdx_tools.spdx3.writer.console.hash_writer import write_hash from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading @@ -14,15 +14,11 @@ def write_build(build: Build, text_output: TextIO): text_output.write("## Build\n") write_element_properties(build, text_output) - write_value("build_type", build.build_type, text_output) - write_value("build_id", build.build_id, text_output) - write_value("config_source_entrypoint", ", ".join([entry for entry in build.config_source_entrypoint]), - text_output) - write_value("config_source_uri", ", ".join([entry for entry in build.config_source_uri]), text_output) - write_optional_heading(build.config_source_digest, "config_source_digest", text_output) - for digest_hash in build.config_source_digest: - write_hash(digest_hash, text_output, heading=False) - write_dict("parameters", build.parameters, text_output) - write_value("build_start", build.build_start, text_output) - write_value("build_end", build.build_end, text_output) - write_dict("environment", build.environment, text_output) + for property_name in Build.__annotations__.keys(): + if property_name == "config_source_digest": + write_optional_heading(build.config_source_digest, "config_source_digest", text_output) + for digest_hash in build.config_source_digest: + write_hash(digest_hash, text_output, heading=False) + continue + + write_value(property_name, getattr(build, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/console.py b/src/spdx_tools/spdx3/writer/console/console.py index 99000e36c..30bf024da 100644 --- a/src/spdx_tools/spdx3/writer/console/console.py +++ b/src/spdx_tools/spdx3/writer/console/console.py @@ -1,21 +1,26 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 - +from enum import Enum from typing import Optional, TextIO, Union -def write_value(tag: str, value: Optional[Union[bool, str]], out: TextIO, indent: bool = False): +def write_value(tag: str, value: Optional[Union[bool, str, dict, list, Enum]], out: TextIO, indent: bool = False): """This function is duplicated from spdx_tools.spdx.writer.tagvalue.tag_value_writer_helper_functions and slightly adapted to make indentation of output possible.""" if not value: return - if indent: - out.write(f"\t{tag}: {value}\n") - else: - out.write(f"{tag}: {value}\n") + if isinstance(value, dict): + value = ", ".join([f"{tag}: ({key}: {val})" for key, val in value.items()]) + if isinstance(value, list): + value = ", ".join([entry for entry in value]) + if isinstance(value, Enum): + value = value.name + write_and_possibly_indent(f"{tag}: {value}", indent, out) -def write_dict(tag: str, dictionary: dict, out: TextIO): - for key, value in dictionary: - out.write(f'{tag}: "{key}": "{value}"') +def write_and_possibly_indent(text: str, indent: bool, out: TextIO): + if indent: + out.write(f"\t{text}\n") + else: + out.write(f"{text}\n") diff --git a/src/spdx_tools/spdx3/writer/console/creation_information_writer.py b/src/spdx_tools/spdx3/writer/console/creation_information_writer.py index 25072ad3d..e935dcd97 100644 --- a/src/spdx_tools/spdx3/writer/console/creation_information_writer.py +++ b/src/spdx_tools/spdx3/writer/console/creation_information_writer.py @@ -16,6 +16,6 @@ def write_creation_info(creation_info: CreationInformation, text_output: TextIO, write_value("created by", created_by, text_output, indent) for created_using in creation_info.created_using: write_value("created using", created_using, text_output, indent) - write_value("profile", ", ".join(creation_info.profile), text_output, indent) + write_value("profile", creation_info.profile, text_output, indent) write_value("data license", creation_info.data_license, text_output, indent) write_value("comment", creation_info.comment, text_output, indent) diff --git a/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py b/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py index 3e7b6ae23..9871d251d 100644 --- a/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py +++ b/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py @@ -4,7 +4,7 @@ from typing import TextIO from spdx_tools.spdx3.model.dataset import Dataset -from spdx_tools.spdx3.writer.console.console import write_dict, write_value +from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx3.writer.console.software.package_writer import write_package @@ -12,17 +12,5 @@ def write_dataset(dataset: Dataset, text_output: TextIO): text_output.write("## AI Package\n") write_package(dataset, text_output, False) - write_value("data_collection_process", dataset.data_collection_process, text_output) - write_value("intended_use", dataset.intended_use, text_output) - write_value("dataset_size", dataset.dataset_size, text_output) - write_value("dataset_noise", dataset.dataset_noise, text_output) - write_value("data_preprocessing_steps", dataset.data_preprocessing_steps, text_output) - write_dict("sensors", dataset.sensors, text_output) - write_value("known_biases", dataset.known_biases, text_output) - write_value("sensitive_personal_information", dataset.sensitive_personal_information, text_output) - write_value( - "anonymization_method_used", ", ".join([entry for entry in dataset.anonymization_method_used]), text_output - ) - write_value("confidentiality_level", dataset.confidentiality_level, text_output) - write_value("dataset_update_mechanism", dataset.dataset_update_mechanism, text_output) - write_value("dataset_availability", dataset.dataset_availability, text_output) + for property_name in Dataset.__annotations__.keys(): + write_value(property_name, getattr(dataset, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/element_writer.py b/src/spdx_tools/spdx3/writer/console/element_writer.py index f3f14aa2c..c83e763b1 100644 --- a/src/spdx_tools/spdx3/writer/console/element_writer.py +++ b/src/spdx_tools/spdx3/writer/console/element_writer.py @@ -25,9 +25,9 @@ def write_element_properties(element: Element, text_output: TextIO): # as soon as there are more inherited classes we need to implement a logic # that determines the correct write function for the "integrity_method" object write_hash(integrity_method, text_output, heading=False) - write_optional_heading(element.external_references, "External References", text_output) + write_optional_heading(element.external_references, "External References\n", text_output) for external_reference in element.external_references: write_external_reference(external_reference, text_output) - write_optional_heading(element.external_identifier, "External Identifier", text_output) + write_optional_heading(element.external_identifier, "External Identifier\n", text_output) for external_identifier in element.external_identifier: write_external_identifier(external_identifier, text_output) diff --git a/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py b/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py index e197581be..90327b9e9 100644 --- a/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py +++ b/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py @@ -8,6 +8,5 @@ def write_external_identifier(external_identifier: ExternalIdentifier, text_output: TextIO): - write_value("type", external_identifier.external_identifier_type.name, text_output) - write_value("identifier", external_identifier.identifier, text_output) - write_value("comment", external_identifier.comment, text_output) + for property_name in ExternalIdentifier.__annotations__.keys(): + write_value(property_name, getattr(external_identifier, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/external_reference_writer.py b/src/spdx_tools/spdx3/writer/console/external_reference_writer.py index 64b8da2fd..7deb0b620 100644 --- a/src/spdx_tools/spdx3/writer/console/external_reference_writer.py +++ b/src/spdx_tools/spdx3/writer/console/external_reference_writer.py @@ -8,7 +8,5 @@ def write_external_reference(external_reference: ExternalReference, text_output: TextIO): - write_value("type", external_reference.external_reference_type.name, text_output) - write_value("locator", ", ".join(external_reference.locator), text_output) - write_value("content_type", external_reference.content_type, text_output) - write_value("comment", external_reference.comment, text_output) + for property_name in ExternalReference.__annotations__.keys(): + write_value(property_name, getattr(external_reference, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/hash_writer.py b/src/spdx_tools/spdx3/writer/console/hash_writer.py index cbc0a99ed..b3a722daa 100644 --- a/src/spdx_tools/spdx3/writer/console/hash_writer.py +++ b/src/spdx_tools/spdx3/writer/console/hash_writer.py @@ -11,6 +11,6 @@ def write_hash(hash_object: Hash, text_output: TextIO, heading: bool, indent: bool = True): if heading: text_output.write("## Hash\n") - write_value("algorithm", hash_object.algorithm.name, text_output, indent) + write_value("algorithm", hash_object.algorithm, text_output, indent) write_value("hash_value", hash_object.hash_value, text_output, indent) write_integrity_method(hash_object, text_output, indent) diff --git a/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py b/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py index d4adf12b5..8eeed3efe 100644 --- a/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py +++ b/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py @@ -8,5 +8,5 @@ def write_namespace_map(namespace_map: NamespaceMap, text_output: TextIO): - write_value("prefix", namespace_map.prefix, text_output) - write_value("namespace", namespace_map.namespace, text_output) + for property_name in NamespaceMap.__annotations__.keys(): + write_value(property_name, getattr(namespace_map, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/relationship_writer.py b/src/spdx_tools/spdx3/writer/console/relationship_writer.py index 738f45c4e..866619399 100644 --- a/src/spdx_tools/spdx3/writer/console/relationship_writer.py +++ b/src/spdx_tools/spdx3/writer/console/relationship_writer.py @@ -11,7 +11,5 @@ def write_relationship(relationship: Relationship, text_output: TextIO): text_output.write("## Relationship\n") write_element_properties(relationship, text_output) - write_value("from_element", relationship.from_element, text_output) - write_value("to", ", ".join(relationship.to), text_output) - write_value("relationship_type", relationship.relationship_type.name, text_output) - write_value("completeness", relationship.completeness.name if relationship.completeness else None, text_output) + for property_name in relationship.__annotations__.keys(): + write_value(property_name, getattr(relationship, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/software/file_writer.py b/src/spdx_tools/spdx3/writer/console/software/file_writer.py index bd0bdfa54..d76ca46b6 100644 --- a/src/spdx_tools/spdx3/writer/console/software/file_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/file_writer.py @@ -11,6 +11,11 @@ def write_file(file: File, text_output: TextIO): text_output.write("## File\n") write_artifact_properties(file, text_output) - write_value("content_identifier", file.content_identifier, text_output) - write_value("file_purpose", ", ".join([purpose.name for purpose in file.file_purpose]), text_output) - write_value("content_type", file.content_type, text_output) + + for property_name in File.__annotations__.keys(): + if property_name == "file_purpose": + write_value( + property_name, ", ".join([purpose.name for purpose in getattr(file, property_name)]), text_output + ) + continue + write_value(property_name, getattr(file, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/software/package_writer.py b/src/spdx_tools/spdx3/writer/console/software/package_writer.py index 6397ad303..83905de55 100644 --- a/src/spdx_tools/spdx3/writer/console/software/package_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/package_writer.py @@ -12,9 +12,11 @@ def write_package(package: Package, text_output: TextIO, heading: bool = True): if heading: text_output.write("## Package\n") write_artifact_properties(package, text_output) - write_value("content_identifier", package.content_identifier, text_output) - write_value("package_purpose", ", ".join([purpose.name for purpose in package.package_purpose]), text_output) - write_value("package_version", package.package_version, text_output) - write_value("download_location", package.download_location, text_output) - write_value("package_uri", package.package_url, text_output) - write_value("homepage", package.homepage, text_output) + + for property_name in Package.__annotations__.keys(): + if property_name == "package_purpose": + write_value( + property_name, ", ".join([purpose.name for purpose in getattr(package, property_name)]), text_output + ) + continue + write_value(property_name, getattr(package, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py b/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py index 0378b3aa0..19b7c6a27 100644 --- a/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py @@ -6,13 +6,16 @@ from spdx_tools.spdx3.model.software import Snippet from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties from spdx_tools.spdx3.writer.console.console import write_value -from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range def write_snippet(snippet: Snippet, text_output: TextIO): text_output.write("## Snippet\n") write_artifact_properties(snippet, text_output) - write_value("content_identifier", snippet.content_identifier, text_output) - write_value("snippet_purpose", ", ".join([purpose.name for purpose in snippet.snippet_purpose]), text_output) - write_range("byte_range", snippet.byte_range, text_output) - write_range("line_range", snippet.line_range, text_output) + + for property_name in Snippet.__annotations__.keys(): + if property_name == "snippet_purpose": + write_value( + property_name, ", ".join([purpose.name for purpose in getattr(snippet, property_name)]), text_output + ) + continue + write_value(property_name, getattr(snippet, property_name), text_output) From 0788b7b2ec7af1e0d7beae5bdd44aadbf9526f2a Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 26 Apr 2023 16:36:23 +0200 Subject: [PATCH 191/354] add links for GH issues tracking missing conversion rules Signed-off-by: Meret Behrens --- .../spdx3/bump_from_spdx2/annotation.py | 3 ++- .../bump_from_spdx2/creation_information.py | 11 ++++++++--- src/spdx_tools/spdx3/bump_from_spdx2/file.py | 4 +++- src/spdx_tools/spdx3/bump_from_spdx2/package.py | 17 +++++++++++------ src/spdx_tools/spdx3/bump_from_spdx2/snippet.py | 2 +- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py index 84e298cfb..0c2b4387d 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py @@ -33,7 +33,8 @@ def bump_annotation( "Annotator", 0, "The SPDX2 annotation is not of Type Person or Organization." - " This case leads to an invalid SPDX3 document and is currently not supported.", + " This case leads to an invalid SPDX3 document and is currently not supported." + "https://github.com/spdx/spdx-3-model/issues/180", ) annotation_type: AnnotationType = AnnotationType[spdx2_annotation.annotation_type.name] diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py index 8d7b99db6..7e8f86956 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py @@ -20,7 +20,7 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: spdx_id = f"{document_namespace}#{spdx2_creation_info.spdx_id}" # creation_info.document_namespace -> ? - print_missing_conversion("creation_info.document_namespace", 0) + print_missing_conversion("creation_info.document_namespace", 0, "https://github.com/spdx/spdx-3-model/issues/87") # creation_info.external_document_refs -> spdx_document.imports imports = [ @@ -28,7 +28,11 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: for external_document_ref in spdx2_creation_info.external_document_refs ] # creation_info.license_list_version -> ? - print_missing_conversion("creation_info.license_list_version", 0) + print_missing_conversion( + "creation_info.license_list_version", + 0, + "part of licensing profile, " "https://github.com/spdx/spdx-3-model/issues/131", + ) # creation_info.document_comment -> spdx_document.comment document_comment = spdx2_creation_info.document_comment creation_information = CreationInformation( @@ -57,7 +61,8 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: "Creators", 0, "The SPDX2 creation_info does not contain creators of Type Person or Organization." - " This case leads to an invalid SPDX3 document and is currently not supported.", + " This case leads to an invalid SPDX3 document and is currently not supported." + "https://github.com/spdx/spdx-3-model/issues/180", ) creation_information.created_by = creator_ids diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/file.py b/src/spdx_tools/spdx3/bump_from_spdx2/file.py index 8273d05eb..63ea26cd5 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/file.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/file.py @@ -16,7 +16,9 @@ def bump_file( integrity_methods = [bump_checksum(checksum) for checksum in spdx2_file.checksums] # file.checksums -> file.verifiedUsing # file.file_types -> file.content_type (MediaType with Cardinality 1) - print_missing_conversion("file.file_type", 0, "different cardinalities") + print_missing_conversion( + "file.file_type", 0, "different cardinalities, " "https://github.com/spdx/spdx-3-model/issues/82" + ) print_missing_conversion( "file.concluded_license, file.license_info_in_file, file.license_comment, file.copyright_text", 0, diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index a7eef0e47..f7d789ef8 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -27,17 +27,19 @@ def bump_package( spdx_id = "#".join([document_namespace, spdx2_package.spdx_id]) download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") # package.file_name -> ? - print_missing_conversion("package2.file_name", 0) + print_missing_conversion("package2.file_name", 0, "https://github.com/spdx/spdx-3-model/issues/83") # package.supplier -> Relationship, suppliedBy? - print_missing_conversion("package2.supplier", 1, "of relationships") + print_missing_conversion("package2.supplier", 0, "https://github.com/spdx/spdx-3-model/issues/113") if isinstance(spdx2_package.originator, Spdx2_Actor): originated_by_spdx_id = bump_actor(spdx2_package.originator, payload, creation_information, document_namespace) else: originated_by_spdx_id = None # package.files_analyzed -> ? - print_missing_conversion("package2.files_analyzed", 0) + print_missing_conversion("package2.files_analyzed", 0, "https://github.com/spdx/spdx-3-model/issues/84") # package.verification_code -> package.verified_using - print_missing_conversion("package2.verification_code", 1, "of IntegrityMethod") + print_missing_conversion( + "package2.verification_code", 1, "of IntegrityMethod, https://github.com/spdx/spdx-3-model/issues/85" + ) # package.checksums -> package.verified_using integrity_methods = [bump_checksum(checksum) for checksum in spdx2_package.checksums] print_missing_conversion( @@ -65,7 +67,7 @@ def bump_package( elif isinstance(id_or_ref, ExternalIdentifier): external_identifiers.append(id_or_ref) - print_missing_conversion("package2.attribution_texts", 0) + print_missing_conversion("package2.attribution_texts", 0, "missing definition of license profile") package_purpose = ( [SoftwarePurpose[spdx2_package.primary_package_purpose.name]] if spdx2_package.primary_package_purpose else [] ) @@ -121,7 +123,10 @@ def bump_external_package_ref( if reference_type not in external_ref_type_map: print_missing_conversion( - reference_type, 0, f"Conversion of ExternalPackageRef of type {reference_type} is currently not supported." + reference_type, + 0, + f"Conversion of ExternalPackageRef of type {reference_type} is currently not supported." + f"https://github.com/spdx/spdx-3-model/issues/81", ) return None diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index 1b41c9178..1a0a4e69d 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -12,7 +12,7 @@ def bump_snippet( spdx2_snippet: Spdx2_Snippet, payload: Payload, creation_information: CreationInformation, document_namespace: str ): spdx_id = "#".join([document_namespace, spdx2_snippet.spdx_id]) - print_missing_conversion("snippet.file_spdx_id", 0) + print_missing_conversion("snippet.file_spdx_id", 0, "https://github.com/spdx/spdx-3-model/issues/130") print_missing_conversion( "snippet.concluded_license, snippet.license_info_in_snippet, snippet.license_comment," "snippet.copyright_text", From 23f4d44c0214613ce146f1726c3eca9d871fcb85 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 26 Apr 2023 16:24:19 +0200 Subject: [PATCH 192/354] [issue_426] make name mandatory for package and file Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/model/software/file.py | 2 +- src/spdx_tools/spdx3/model/software/package.py | 2 +- tests/spdx3/model/software/test_file.py | 3 +++ tests/spdx3/model/software/test_package.py | 3 +++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py index 29f9bbba5..a138b0dc2 100644 --- a/src/spdx_tools/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -27,7 +27,7 @@ def __init__( self, spdx_id: str, creation_info: CreationInformation, - name: Optional[str] = None, + name: str, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py index 12b4875e7..bf7e5e85e 100644 --- a/src/spdx_tools/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -31,7 +31,7 @@ def __init__( self, spdx_id: str, creation_info: CreationInformation, - name: Optional[str] = None, + name: str, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index 5bd0aa594..495b4ea13 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -13,6 +13,7 @@ def test_correct_initialization(creation_information): file = File( "SPDXRef-File", creation_information, + "Test file", verified_using=None, content_identifier="https://any.uri", file_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE], @@ -21,6 +22,7 @@ def test_correct_initialization(creation_information): assert file.spdx_id == "SPDXRef-File" assert file.creation_info == creation_information + assert file.name == "Test file" assert file.content_identifier == "https://any.uri" assert file.file_purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE] assert file.content_type == "MediaType" @@ -32,6 +34,7 @@ def test_invalid_initialization(creation_information): File( 1, creation_information, + "test file", content_identifier=3, file_purpose=SoftwarePurpose.FILE, content_type=SoftwarePurpose.ARCHIVE, diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 55bbc0405..428b00367 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -14,6 +14,7 @@ def test_correct_initialization(creation_information): package = Package( "SPDXRef-Package", creation_information, + "Test package", content_identifier="https://any.uri", built_time=datetime(2022, 1, 1), release_time=datetime(2022, 1, 2), @@ -28,6 +29,7 @@ def test_correct_initialization(creation_information): assert package.spdx_id == "SPDXRef-Package" assert package.creation_info == creation_information + assert package.name == "Test package" assert package.content_identifier == "https://any.uri" assert package.built_time == datetime(2022, 1, 1) assert package.release_time == datetime(2022, 1, 2) @@ -46,6 +48,7 @@ def test_invalid_initialization(creation_information): Package( "SPDXRef-Package", creation_information, + "Test package", built_time="2022-03-04T00:00:00Z", content_identifier=3, package_purpose=SoftwarePurpose.FILE, From 862ac33bcb6e6b692e9ed1987a672b44ac71c6fc Mon Sep 17 00:00:00 2001 From: HarshvMahawar Date: Tue, 2 May 2023 18:23:49 +0530 Subject: [PATCH 193/354] Implemented fixtures for tests on the prototype spdx3 Signed-off-by: HarshvMahawar --- tests/spdx3/fixtures.py | 421 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 421 insertions(+) create mode 100644 tests/spdx3/fixtures.py diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py new file mode 100644 index 000000000..723f2bba0 --- /dev/null +++ b/tests/spdx3/fixtures.py @@ -0,0 +1,421 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +from semantic_version import Version + +from spdx_tools.spdx3.model.agent import Agent +from spdx_tools.spdx3.model.annotation import Annotation, AnnotationType +from spdx_tools.spdx3.model.bom import Bom +from spdx_tools.spdx3.model.bundle import Bundle +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType +from spdx_tools.spdx3.model.external_map import ExternalMap +from spdx_tools.spdx3.model.external_reference import ExternalReference, ExternalReferenceType +from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm +from spdx_tools.spdx3.model.namespace_map import NamespaceMap +from spdx_tools.spdx3.model.organization import Organization +from spdx_tools.spdx3.model.person import Person +from spdx_tools.spdx3.model.relationship import Relationship, RelationshipCompleteness, RelationshipType +from spdx_tools.spdx3.model.software_agent import SoftwareAgent +from spdx_tools.spdx3.model.spdx_document import SpdxDocument +from spdx_tools.spdx3.model.tool import Tool + +"""Utility methods to create data model instances. All properties have valid defaults, so they don't need to be +specified unless relevant for the test.""" + + +def creation_info_fixture( + spec_version=Version("3.0.0"), + created=datetime(2022, 12, 1), + created_by=["creatorCreationInfo"], + created_using=["createdCreationInfo"], + profile=["profileCreationInfo"], + data_license="CC0-1.0", + comment="commentCreationInfo", +) -> CreationInformation: + return CreationInformation( + spec_version=spec_version, + created=created, + created_by=created_by, + created_using=created_using, + profile=profile, + data_license=data_license, + comment=comment, + ) + + +def external_identifier_fixture( + external_identifier_type=ExternalIdentifierType.OTHER, identifier="identifier_ext_iden", comment="comment_ext_iden" +) -> ExternalIdentifier: + return ExternalIdentifier(external_identifier_type, identifier, comment) + + +def external_reference_fixture( + external_reference_type=ExternalReferenceType.OTHER, + locator=None, + content_type="content_type_exter_ref", + comment="comment_exter_ref", +) -> ExternalReference: + locator = ["locator for external reference"] if locator is None else locator + return ExternalReference(external_reference_type, locator, content_type, comment) + + +def hash_fixture(algorithm=HashAlgorithm.SHA1, hash_value="hash_value", comment="comment_hash_algorithm") -> Hash: + return Hash(algorithm=algorithm, hash_value=hash_value, comment=comment) + + +def external_map_fixture( + external_id="https://spdx.test/tools-python/ExternalMapFixture", + verified_using=None, + location_hint="https://spdx.test/tools-python/location_hint_ExternalMap", +) -> ExternalMap: + verified_using = [hash_fixture()] if verified_using is None else verified_using + return ExternalMap(external_id=external_id, verified_using=verified_using, location_hint=location_hint) + + +def namespace_map_fixture(prefix="prefix_namespace_map", namespace="namespace_namespace_map") -> NamespaceMap: + return NamespaceMap(prefix=prefix, namespace=namespace) + + +def agent_fixture( + spdx_id="https://spdx.test/tools-python/AgentFixture", + creation_info=creation_info_fixture(), + name="nameAgent", + summary="summaryAgent", + description="descriptionAgent", + comment="commentAgent", + verified_using=[hash_fixture()], + external_references=[external_reference_fixture()], + external_identifier=[external_identifier_fixture()], + extension=None, +) -> Agent: + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + return Agent( + spdx_id=spdx_id, + creation_info=creation_info, + name=name, + summary=summary, + description=description, + comment=comment, + verified_using=verified_using, + external_references=external_references, + external_identifier=external_identifier, + extension=extension, + ) + + +def annotation_fixture( + spdx_id="https://spdx.test/tools-python/AnnotationFixture", + creation_info=creation_info_fixture(), + annotation_type=AnnotationType.OTHER, + subject="subject_annotation", + name="name_annotation", + summary="summary_annotation", + description="description_annotation", + comment="comment_annotation", + verified_using=[hash_fixture()], + external_references=[external_reference_fixture()], + external_identifier=[external_identifier_fixture()], + extension=None, + content_type="content_type_annotation", + statement="statement_annotation", +) -> Annotation: + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + return Annotation( + spdx_id=spdx_id, + creation_info=creation_info, + annotation_type=annotation_type, + subject=subject, + name=name, + summary=summary, + description=description, + comment=comment, + verified_using=verified_using, + external_references=external_references, + external_identifier=external_identifier, + extension=extension, + content_type=content_type, + statement=statement, + ) + + +def bom_fixture( + spdx_id="https://spdx.test/tools-python/BomFixture", + creation_info=creation_info_fixture(), + elements=["elements_bom"], + root_elements=["root_elements_bom"], + name="name_bom", + summary="summary_bom", + description="description_bom", + comment="comment_bom", + verified_using=[hash_fixture()], + external_references=[external_reference_fixture()], + external_identifier=[external_identifier_fixture()], + extension=None, + namespaces=[namespace_map_fixture()], + imports=[external_map_fixture()], + context=None, +) -> Bom: + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + namespaces = [] if namespaces is None else namespaces + imports = [] if imports is None else imports + return Bom( + spdx_id=spdx_id, + creation_info=creation_info, + elements=elements, + root_elements=root_elements, + name=name, + summary=summary, + description=description, + comment=comment, + verified_using=verified_using, + external_references=external_references, + external_identifier=external_identifier, + extension=extension, + namespaces=namespaces, + imports=imports, + context=context, + ) + + +def bundle_fixture( + spdx_id="https://spdx.test/tools-python/BundleFixture", + creation_info=creation_info_fixture(), + elements=["elements_bundle"], + root_elements=["root_elements_bundle"], + name="name_bundle", + summary="summary_bundle", + description="description_bundle", + comment="comment_bundle", + verified_using=[hash_fixture()], + external_references=[external_reference_fixture()], + external_identifier=[external_identifier_fixture()], + extension=None, + namespaces=[namespace_map_fixture()], + imports=[external_map_fixture()], + context="context_bundle", +) -> Bundle: + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + namespaces = [] if namespaces is None else namespaces + imports = [] if imports is None else imports + return Bundle( + spdx_id=spdx_id, + creation_info=creation_info, + elements=elements, + root_elements=root_elements, + name=name, + summary=summary, + description=description, + comment=comment, + verified_using=verified_using, + external_references=external_references, + external_identifier=external_identifier, + extension=extension, + namespaces=namespaces, + imports=imports, + context=context, + ) + + +def organization_fixture( + spdx_id="https://spdx.test/tools-python/OrganizationFixture", + creation_info=creation_info_fixture(), + name="name_organization", + summary="summary_organization", + description="description_organization", + comment="comment_organization", + verified_using=[hash_fixture()], + external_references=[external_reference_fixture()], + external_identifier=[external_identifier_fixture()], + extension=None, +) -> Organization: + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + return Organization( + spdx_id=spdx_id, + creation_info=creation_info, + name=name, + summary=summary, + description=description, + comment=comment, + verified_using=verified_using, + external_references=external_references, + external_identifier=external_identifier, + extension=extension, + ) + + +def person_fixture( + spdx_id="https://spdx.test/tools-python/PersonFixture", + creation_info=creation_info_fixture(), + name="name_person", + summary="summary_person", + description="description_person", + comment="comment_person", + verified_using=[hash_fixture()], + external_references=[external_reference_fixture()], + external_identifier=[external_identifier_fixture()], + extension=None, +) -> Person: + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + return Person( + spdx_id=spdx_id, + creation_info=creation_info, + name=name, + summary=summary, + description=description, + comment=comment, + verified_using=verified_using, + external_references=external_references, + external_identifier=external_identifier, + extension=extension, + ) + + +def relationship_fixture( + spdx_id="https://spdx.test/tools-python/RelationshipFixture", + creation_info=creation_info_fixture(), + from_element="from_element_relationship", + to=["to_relationship"], + relationship_type=RelationshipType.OTHER, + name="name_relationship", + summary="summary_relationship", + description="description_relationship", + comment="comment_relationship", + verified_using=[hash_fixture()], + external_references=[external_reference_fixture()], + external_identifier=[external_identifier_fixture()], + extension=None, + completeness=RelationshipCompleteness.UNKNOWN, +) -> Relationship: + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + return Relationship( + spdx_id=spdx_id, + creation_info=creation_info, + from_element=from_element, + to=to, + relationship_type=relationship_type, + name=name, + summary=summary, + description=description, + comment=comment, + verified_using=verified_using, + external_references=external_references, + external_identifier=external_identifier, + extension=extension, + completeness=completeness, + ) + + +def software_agent_fixture( + spdx_id="https://spdx.test/tools-python/SoftwareAgentFixture", + creation_info=creation_info_fixture(), + name="name_software_agent", + summary="summary_software_agent", + description="description_software_agent", + comment="comment_software_agent", + verified_using=[hash_fixture()], + external_references=[external_reference_fixture()], + external_identifier=[external_identifier_fixture()], + extension=None, +) -> SoftwareAgent: + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + return SoftwareAgent( + spdx_id=spdx_id, + creation_info=creation_info, + name=name, + summary=summary, + description=description, + comment=comment, + verified_using=verified_using, + external_references=external_references, + external_identifier=external_identifier, + extension=extension, + ) + + +def spdx_document_fixture( + spdx_id="https://spdx.test/tools-python/SpdxDocumentFixture", + creation_info=creation_info_fixture(), + name="name_spdx_document", + elements=["elements_spdx_document"], + root_elements=["root_elements_spdx_document"], + summary="summary_spdx_document", + description="description_spdx_document", + comment="comment_spdx_document", + verified_using=[hash_fixture()], + external_references=[external_reference_fixture()], + external_identifier=[external_identifier_fixture()], + extension=None, + namespaces=[namespace_map_fixture()], + imports=[external_map_fixture()], + context="context_spdx_document", +) -> SpdxDocument: + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + namespaces = [] if namespaces is None else namespaces + imports = [] if imports is None else imports + return SpdxDocument( + spdx_id=spdx_id, + creation_info=creation_info, + name=name, + elements=elements, + root_elements=root_elements, + summary=summary, + description=description, + comment=comment, + verified_using=verified_using, + external_references=external_references, + external_identifier=external_identifier, + extension=extension, + namespaces=namespaces, + imports=imports, + context=context, + ) + + +def tool_fixture( + spdx_id="https://spdx.test/tools-python/ToolFixture", + creation_info=creation_info_fixture(), + name="name_tool", + summary="summary_tool", + description="description_tool", + comment="comment_tool", + verified_using=[hash_fixture()], + external_references=[external_reference_fixture()], + external_identifier=[external_identifier_fixture()], + extension=None, +) -> Tool: + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + return Tool( + spdx_id=spdx_id, + creation_info=creation_info, + name=name, + summary=summary, + description=description, + comment=comment, + verified_using=verified_using, + external_references=external_references, + external_identifier=external_identifier, + extension=extension, + ) From 9265153098006fa448de5468ad02cf38dcc2a159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 19 Apr 2023 09:27:50 +0200 Subject: [PATCH 194/354] [issue-426] add LifecycleScopedRelationship and SoftwareDependencyRelationship MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/model/__init__.py | 1 + .../model/lifecycle_scoped_relationship.py | 54 ++++++++++++++++ src/spdx_tools/spdx3/model/relationship.py | 4 +- .../spdx3/model/software/__init__.py | 5 ++ .../software_dependency_relationship.py | 64 +++++++++++++++++++ .../test_software_dependency_relationship.py | 54 ++++++++++++++++ .../test_lifecycle_scoped_relationship.py | 50 +++++++++++++++ tests/spdx3/model/test_relationship.py | 4 +- 8 files changed, 232 insertions(+), 4 deletions(-) create mode 100644 src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py create mode 100644 src/spdx_tools/spdx3/model/software/software_dependency_relationship.py create mode 100644 tests/spdx3/model/software/test_software_dependency_relationship.py create mode 100644 tests/spdx3/model/test_lifecycle_scoped_relationship.py diff --git a/src/spdx_tools/spdx3/model/__init__.py b/src/spdx_tools/spdx3/model/__init__.py index 64fd80e39..da137394d 100644 --- a/src/spdx_tools/spdx3/model/__init__.py +++ b/src/spdx_tools/spdx3/model/__init__.py @@ -18,4 +18,5 @@ from spdx_tools.spdx3.model.spdx_document import SpdxDocument from spdx_tools.spdx3.model.annotation import Annotation, AnnotationType from spdx_tools.spdx3.model.relationship import Relationship, RelationshipType, RelationshipCompleteness +from spdx_tools.spdx3.model.lifecycle_scoped_relationship import LifecycleScopedRelationship, LifecycleScopeType from spdx_tools.spdx3.model.artifact import Artifact diff --git a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py new file mode 100644 index 000000000..10f10ea53 --- /dev/null +++ b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum, auto +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInformation, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + Relationship, + RelationshipCompleteness, + RelationshipType, +) + + +class LifecycleScopeType(Enum): + DESIGN = auto() + BUILD = auto() + DEVELOPMENT = auto() + TEST = auto() + RUNTIME = auto() + OTHER = auto() + + +@dataclass_with_properties +class LifecycleScopedRelationship(Relationship): + scope: Optional[LifecycleScopeType] = None + + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + from_element: str, + to: List[str], + relationship_type: RelationshipType, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + completeness: Optional[RelationshipCompleteness] = None, + scope: Optional[LifecycleScopeType] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index 82f600a23..3448c6b1b 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -54,8 +54,8 @@ class RelationshipType(Enum): class RelationshipCompleteness(Enum): INCOMPLETE = auto() - KNOWN = auto() - UNKNOWN = auto() + COMPLETE = auto() + NOASSERTION = auto() @dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/software/__init__.py b/src/spdx_tools/spdx3/model/software/__init__.py index 61c798ade..6f1253a98 100644 --- a/src/spdx_tools/spdx3/model/software/__init__.py +++ b/src/spdx_tools/spdx3/model/software/__init__.py @@ -3,3 +3,8 @@ from spdx_tools.spdx3.model.software.package import Package from spdx_tools.spdx3.model.software.snippet import Snippet from spdx_tools.spdx3.model.software.sbom import Sbom +from spdx_tools.spdx3.model.software.software_dependency_relationship import ( + SoftwareDependencyRelationship, + SoftwareDependencyLinkType, + DependencyConditionalityType, +) diff --git a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py new file mode 100644 index 000000000..9d2c21dc7 --- /dev/null +++ b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py @@ -0,0 +1,64 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from enum import Enum, auto +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + CreationInformation, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, + LifecycleScopedRelationship, + LifecycleScopeType, + RelationshipCompleteness, + RelationshipType, +) + + +class SoftwareDependencyLinkType(Enum): + STATIC = auto() + DYNAMIC = auto() + TOOL = auto() + OTHER = auto() + + +class DependencyConditionalityType(Enum): + OPTIONAL = auto() + REQUIRED = auto() + PROVIDED = auto() + PREREQUISITE = auto() + OTHER = auto() + + +@dataclass_with_properties +class SoftwareDependencyRelationship(LifecycleScopedRelationship): + software_linkage: Optional[SoftwareDependencyLinkType] = None + conditionality: Optional[DependencyConditionalityType] = None + + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + from_element: str, + to: List[str], + relationship_type: RelationshipType, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + completeness: Optional[RelationshipCompleteness] = None, + scope: Optional[LifecycleScopeType] = None, + software_linkage: Optional[SoftwareDependencyLinkType] = None, + conditionality: Optional[DependencyConditionalityType] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/model/software/test_software_dependency_relationship.py b/tests/spdx3/model/software/test_software_dependency_relationship.py new file mode 100644 index 000000000..407bfd9c0 --- /dev/null +++ b/tests/spdx3/model/software/test_software_dependency_relationship.py @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import mock + +import pytest + +from spdx_tools.spdx3.model import LifecycleScopeType, RelationshipCompleteness, RelationshipType +from spdx_tools.spdx3.model.software import ( + DependencyConditionalityType, + SoftwareDependencyLinkType, + SoftwareDependencyRelationship, +) + + +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_correct_initialization(creation_information): + relationship = SoftwareDependencyRelationship( + "SPDXRef-Relationship", + creation_information, + "spdx_id1", + ["spdx_id2", "spdx_id3"], + RelationshipType.DESCRIBES, + completeness=RelationshipCompleteness.NOASSERTION, + scope=LifecycleScopeType.DESIGN, + software_linkage=SoftwareDependencyLinkType.STATIC, + conditionality=DependencyConditionalityType.PROVIDED, + ) + + assert relationship.spdx_id == "SPDXRef-Relationship" + assert relationship.creation_info == creation_information + assert relationship.from_element == "spdx_id1" + assert relationship.to == ["spdx_id2", "spdx_id3"] + assert relationship.relationship_type == RelationshipType.DESCRIBES + assert relationship.completeness == RelationshipCompleteness.NOASSERTION + assert relationship.scope == LifecycleScopeType.DESIGN + assert relationship.software_linkage == SoftwareDependencyLinkType.STATIC + assert relationship.conditionality == DependencyConditionalityType.PROVIDED + + +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_invalid_initialization(creation_information): + with pytest.raises(TypeError) as err: + SoftwareDependencyRelationship( + "SPDXRef-Relationship", + creation_information, + "spdx_id1", + 42, + RelationshipType.DESCRIBES, + ) + + assert err.value.args[0] == [ + 'SetterError SoftwareDependencyRelationship: type of argument "to" must be a ' "list; got int instead: 42" + ] diff --git a/tests/spdx3/model/test_lifecycle_scoped_relationship.py b/tests/spdx3/model/test_lifecycle_scoped_relationship.py new file mode 100644 index 000000000..495bbe4cc --- /dev/null +++ b/tests/spdx3/model/test_lifecycle_scoped_relationship.py @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import mock + +import pytest + +from spdx_tools.spdx3.model import ( + LifecycleScopedRelationship, + LifecycleScopeType, + RelationshipCompleteness, + RelationshipType, +) + + +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_correct_initialization(creation_information): + relationship = LifecycleScopedRelationship( + "SPDXRef-Relationship", + creation_information, + "spdx_id1", + ["spdx_id2", "spdx_id3"], + RelationshipType.DESCRIBES, + completeness=RelationshipCompleteness.NOASSERTION, + scope=LifecycleScopeType.DESIGN, + ) + + assert relationship.spdx_id == "SPDXRef-Relationship" + assert relationship.creation_info == creation_information + assert relationship.from_element == "spdx_id1" + assert relationship.to == ["spdx_id2", "spdx_id3"] + assert relationship.relationship_type == RelationshipType.DESCRIBES + assert relationship.completeness == RelationshipCompleteness.NOASSERTION + assert relationship.scope == LifecycleScopeType.DESIGN + + +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_invalid_initialization(creation_information): + with pytest.raises(TypeError) as err: + LifecycleScopedRelationship( + "SPDXRef-Relationship", + creation_information, + "spdx_id1", + 42, + RelationshipType.DESCRIBES, + ) + + assert err.value.args[0] == [ + 'SetterError LifecycleScopedRelationship: type of argument "to" must be a ' "list; got int instead: 42" + ] diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py index 27c127543..1c6d9c766 100644 --- a/tests/spdx3/model/test_relationship.py +++ b/tests/spdx3/model/test_relationship.py @@ -16,7 +16,7 @@ def test_correct_initialization(creation_information): "spdx_id1", ["spdx_id2", "spdx_id3"], RelationshipType.DESCRIBES, - completeness=RelationshipCompleteness.UNKNOWN, + completeness=RelationshipCompleteness.NOASSERTION, ) assert relationship.spdx_id == "SPDXRef-Relationship" @@ -24,7 +24,7 @@ def test_correct_initialization(creation_information): assert relationship.from_element == "spdx_id1" assert relationship.to == ["spdx_id2", "spdx_id3"] assert relationship.relationship_type == RelationshipType.DESCRIBES - assert relationship.completeness == RelationshipCompleteness.UNKNOWN + assert relationship.completeness == RelationshipCompleteness.NOASSERTION @mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) From 68539b8eefead9f8d220137f56dd48d07e5821be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 26 Apr 2023 12:03:29 +0200 Subject: [PATCH 195/354] [issue-434] add writers for new relationship classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../lifecycle_scoped_relationship_writer.py | 20 +++++++++++++++++++ .../writer/console/relationship_writer.py | 5 +++-- ...software_dependency_relationship_writer.py | 20 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 src/spdx_tools/spdx3/writer/console/lifecycle_scoped_relationship_writer.py create mode 100644 src/spdx_tools/spdx3/writer/console/software/software_dependency_relationship_writer.py diff --git a/src/spdx_tools/spdx3/writer/console/lifecycle_scoped_relationship_writer.py b/src/spdx_tools/spdx3/writer/console/lifecycle_scoped_relationship_writer.py new file mode 100644 index 000000000..e71ab6b9f --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/lifecycle_scoped_relationship_writer.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import TextIO + +from spdx_tools.spdx3.model import LifecycleScopedRelationship +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.relationship_writer import write_relationship + + +def write_lifecycle_scoped_relationship( + relationship: LifecycleScopedRelationship, text_output: TextIO, heading: bool = True +): + if heading: + text_output.write("## LifecycleScopedRelationship\n") + write_relationship(relationship, text_output, heading=False) + + for property_name in LifecycleScopedRelationship.__annotations__.keys(): + write_value(property_name, getattr(relationship, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/relationship_writer.py b/src/spdx_tools/spdx3/writer/console/relationship_writer.py index 866619399..c30f89a63 100644 --- a/src/spdx_tools/spdx3/writer/console/relationship_writer.py +++ b/src/spdx_tools/spdx3/writer/console/relationship_writer.py @@ -8,8 +8,9 @@ from spdx_tools.spdx3.writer.console.element_writer import write_element_properties -def write_relationship(relationship: Relationship, text_output: TextIO): - text_output.write("## Relationship\n") +def write_relationship(relationship: Relationship, text_output: TextIO, heading: bool = True): + if heading: + text_output.write("## Relationship\n") write_element_properties(relationship, text_output) for property_name in relationship.__annotations__.keys(): write_value(property_name, getattr(relationship, property_name), text_output) diff --git a/src/spdx_tools/spdx3/writer/console/software/software_dependency_relationship_writer.py b/src/spdx_tools/spdx3/writer/console/software/software_dependency_relationship_writer.py new file mode 100644 index 000000000..e05599525 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/console/software/software_dependency_relationship_writer.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from typing import TextIO + +from spdx_tools.spdx3.model.software import SoftwareDependencyRelationship +from spdx_tools.spdx3.writer.console.console import write_value +from spdx_tools.spdx3.writer.console.lifecycle_scoped_relationship_writer import write_lifecycle_scoped_relationship + + +def write_software_dependency_relationship( + relationship: SoftwareDependencyRelationship, text_output: TextIO, heading: bool = True +): + if heading: + text_output.write("## SoftwareDependencyRelationship\n") + write_lifecycle_scoped_relationship(relationship, text_output, heading=False) + + for property_name in SoftwareDependencyRelationship.__annotations__.keys(): + write_value(property_name, getattr(relationship, property_name), text_output) From e3057471bf2f771d1fb55066e3f0f767ff1065a4 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 2 May 2023 16:03:18 +0200 Subject: [PATCH 196/354] update model according to recent changes in spdx-3-model - adapt some field names to use singular - add identifier_locator and issuing_authority to ExternalIdentifier Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/README.md | 2 +- src/spdx_tools/spdx3/model/ai/ai_package.py | 36 +++++++++---------- src/spdx_tools/spdx3/model/dataset/dataset.py | 14 ++++---- .../spdx3/model/external_identifier.py | 13 +++++-- src/spdx_tools/spdx3/model/hash.py | 4 +++ tests/spdx3/model/ai/test_ai_package.py | 32 ++++++++--------- tests/spdx3/model/dataset/test_dataset.py | 16 ++++----- tests/spdx3/model/test_external_identifier.py | 16 +++++++-- 8 files changed, 79 insertions(+), 54 deletions(-) diff --git a/src/spdx_tools/spdx3/README.md b/src/spdx_tools/spdx3/README.md index 1ffec5786..4f1c3b54d 100644 --- a/src/spdx_tools/spdx3/README.md +++ b/src/spdx_tools/spdx3/README.md @@ -1 +1 @@ -This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: b488a38a075349c90d9a5d085a5a14cf3c3b91f2). +This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: 9dd167007fbf5fd127cc96ab98c9f28238ffb2a3). diff --git a/src/spdx_tools/spdx3/model/ai/ai_package.py b/src/spdx_tools/spdx3/model/ai/ai_package.py index 3d818dcdf..0a6811929 100644 --- a/src/spdx_tools/spdx3/model/ai/ai_package.py +++ b/src/spdx_tools/spdx3/model/ai/ai_package.py @@ -22,17 +22,17 @@ class SafetyRiskAssessmentType(Enum): @dataclass_with_properties class AIPackage(Package): energy_consumption: Optional[str] = None - standards_compliance: List[str] = field(default_factory=list) - limitations: Optional[str] = None + standard_compliance: List[str] = field(default_factory=list) + limitation: Optional[str] = None type_of_model: List[str] = field(default_factory=list) information_about_training: Optional[str] = None information_about_application: Optional[str] = None - hyperparameters: Dict[str, Optional[str]] = field(default_factory=dict) - data_preprocessing_steps: Optional[str] = None - model_explainability_mechanisms: Optional[str] = None + hyperparameter: Dict[str, Optional[str]] = field(default_factory=dict) + model_data_preprocessing: Optional[str] = None + model_explainability: Optional[str] = None sensitive_personal_information: Optional[bool] = None - metrics_decision_thresholds: Dict[str, Optional[str]] = field(default_factory=dict) - metrics: Dict[str, Optional[str]] = field(default_factory=dict) + metric_decision_threshold: Dict[str, Optional[str]] = field(default_factory=dict) + metric: Dict[str, Optional[str]] = field(default_factory=dict) domain: List[str] = field(default_factory=list) autonomy_type: Optional[bool] = None safety_risk_assessment: Optional[SafetyRiskAssessmentType] = None @@ -61,17 +61,17 @@ def __init__( homepage: Optional[str] = None, source_info: Optional[str] = None, energy_consumption: Optional[str] = None, - standards_compliance: List[str] = None, - limitations: Optional[str] = None, + standard_compliance: List[str] = None, + limitation: Optional[str] = None, type_of_model: List[str] = None, information_about_training: Optional[str] = None, information_about_application: Optional[str] = None, - hyperparameters: Dict[str, Optional[str]] = None, - data_preprocessing_steps: Optional[str] = None, - model_explainability_mechanisms: Optional[str] = None, + hyperparameter: Dict[str, Optional[str]] = None, + model_data_preprocessing: Optional[str] = None, + model_explainability: Optional[str] = None, sensitive_personal_information: Optional[bool] = None, - metrics_decision_thresholds: Dict[str, Optional[str]] = None, - metrics: Dict[str, Optional[str]] = None, + metric_decision_threshold: Dict[str, Optional[str]] = None, + metric: Dict[str, Optional[str]] = None, domain: List[str] = None, autonomy_type: Optional[bool] = None, safety_risk_assessment: Optional[SafetyRiskAssessmentType] = None, @@ -80,10 +80,10 @@ def __init__( external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier package_purpose = [] if package_purpose is None else package_purpose - standards_compliance = [] if standards_compliance is None else standards_compliance + standard_compliance = [] if standard_compliance is None else standard_compliance type_of_model = [] if type_of_model is None else type_of_model - hyperparameters = {} if hyperparameters is None else hyperparameters - metrics_decision_thresholds = {} if metrics_decision_thresholds is None else metrics_decision_thresholds - metrics = {} if metrics is None else metrics + hyperparameter = {} if hyperparameter is None else hyperparameter + metric_decision_threshold = {} if metric_decision_threshold is None else metric_decision_threshold + metric = {} if metric is None else metric domain = [] if domain is None else domain check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py index 3a00232d5..c6ec8c448 100644 --- a/src/spdx_tools/spdx3/model/dataset/dataset.py +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -33,9 +33,9 @@ class Dataset(Package): intended_use: Optional[str] = None dataset_size: Optional[int] = None dataset_noise: Optional[str] = None - data_preprocessing_steps: Optional[str] = None - sensors: Dict[str, Optional[str]] = field(default_factory=dict) - known_biases: Optional[str] = None + data_preprocessing: Optional[str] = None + sensor: Dict[str, Optional[str]] = field(default_factory=dict) + known_bias: Optional[str] = None sensitive_personal_information: Optional[bool] = None anonymization_method_used: List[str] = field(default_factory=list) confidentiality_level: Optional[ConfidentialityLevelType] = None @@ -69,9 +69,9 @@ def __init__( intended_use: Optional[str] = None, dataset_size: Optional[int] = None, dataset_noise: Optional[str] = None, - data_preprocessing_steps: Optional[str] = None, - sensors: Dict[str, Optional[str]] = None, - known_biases: Optional[str] = None, + data_preprocessing: Optional[str] = None, + sensor: Dict[str, Optional[str]] = None, + known_bias: Optional[str] = None, sensitive_personal_information: Optional[bool] = None, anonymization_method_used: List[str] = None, confidentiality_level: Optional[ConfidentialityLevelType] = None, @@ -82,6 +82,6 @@ def __init__( external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier package_purpose = [] if package_purpose is None else package_purpose - sensors = {} if sensors is None else sensors + sensors = {} if sensor is None else sensor anonymization_method_used = [] if anonymization_method_used is None else anonymization_method_used check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/external_identifier.py b/src/spdx_tools/spdx3/model/external_identifier.py index 9131bd888..e44d63d89 100644 --- a/src/spdx_tools/spdx3/model/external_identifier.py +++ b/src/spdx_tools/spdx3/model/external_identifier.py @@ -1,8 +1,9 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from dataclasses import field from enum import Enum, auto -from typing import Optional +from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values @@ -25,8 +26,16 @@ class ExternalIdentifier: external_identifier_type: ExternalIdentifierType identifier: str comment: Optional[str] = None + identifier_locator: List[str] = field(default_factory=list) + issuing_authority: Optional[str] = None def __init__( - self, external_identifier_type: ExternalIdentifierType, identifier: str, comment: Optional[str] = None + self, + external_identifier_type: ExternalIdentifierType, + identifier: str, + comment: Optional[str] = None, + identifier_locator: List[str] = None, + issuing_authority: Optional[str] = None, ): + identifier_locator = [] if identifier_locator is None else identifier_locator check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/hash.py b/src/spdx_tools/spdx3/model/hash.py index 6e050845f..611c04393 100644 --- a/src/spdx_tools/spdx3/model/hash.py +++ b/src/spdx_tools/spdx3/model/hash.py @@ -14,6 +14,9 @@ class HashAlgorithm(Enum): BLAKE2B384 = auto() BLAKE2B512 = auto() BLAKE3 = auto() + CRYSTALS_KYBER = auto() + CRYSTALS_DILITHIUM = auto() + FALCON = auto() MD2 = auto() MD4 = auto() MD5 = auto() @@ -30,6 +33,7 @@ class HashAlgorithm(Enum): SHA512 = auto() SPDXPVCSHA1 = auto() SPDXPVCSHA256 = auto() + SPHINCS_PLUS = auto() @dataclass_with_properties diff --git a/tests/spdx3/model/ai/test_ai_package.py b/tests/spdx3/model/ai/test_ai_package.py index cc2fd3abe..00b7e6da5 100644 --- a/tests/spdx3/model/ai/test_ai_package.py +++ b/tests/spdx3/model/ai/test_ai_package.py @@ -15,34 +15,34 @@ def test_correct_initialization(creation_information): "some_spdx_id", creation_information, energy_consumption="energy consumption", - standards_compliance=["some standard"], - limitations="limitation", + standard_compliance=["some standard"], + limitation="limitation", type_of_model=["model type"], information_about_training="training info", information_about_application="app info", - hyperparameters={"param": "value"}, - data_preprocessing_steps="preprocessing steps", - model_explainability_mechanisms="mechanism", + hyperparameter={"param": "value"}, + model_data_preprocessing="preprocessing steps", + model_explainability="mechanism", sensitive_personal_information=True, - metrics_decision_thresholds={"metric1": "threshold", "metric2": None}, - metrics={"metric1": "value1", "metric2": None}, + metric_decision_threshold={"metric1": "threshold", "metric2": None}, + metric={"metric1": "value1", "metric2": None}, domain=["domain"], autonomy_type=True, safety_risk_assessment=SafetyRiskAssessmentType.HIGH, ) assert ai_package.energy_consumption == "energy consumption" - assert ai_package.standards_compliance == ["some standard"] - assert ai_package.limitations == "limitation" + assert ai_package.standard_compliance == ["some standard"] + assert ai_package.limitation == "limitation" assert ai_package.type_of_model == ["model type"] assert ai_package.information_about_training == "training info" assert ai_package.information_about_application == "app info" - assert ai_package.hyperparameters == {"param": "value"} - assert ai_package.data_preprocessing_steps == "preprocessing steps" - assert ai_package.model_explainability_mechanisms == "mechanism" + assert ai_package.hyperparameter == {"param": "value"} + assert ai_package.model_data_preprocessing == "preprocessing steps" + assert ai_package.model_explainability == "mechanism" assert ai_package.sensitive_personal_information - assert ai_package.metrics_decision_thresholds == {"metric1": "threshold", "metric2": None} - assert ai_package.metrics == {"metric1": "value1", "metric2": None} + assert ai_package.metric_decision_threshold == {"metric1": "threshold", "metric2": None} + assert ai_package.metric == {"metric1": "value1", "metric2": None} assert ai_package.domain == ["domain"] assert ai_package.autonomy_type assert ai_package.safety_risk_assessment == SafetyRiskAssessmentType.HIGH @@ -54,12 +54,12 @@ def test_invalid_initialization(creation_information): AIPackage( "some_spdx_id", creation_information, - metrics={"metric1": "value", "metric2": 250}, + metric={"metric1": "value", "metric2": 250}, ) assert err.value.args[0] == [ ( - "SetterError AIPackage: type of argument \"metrics\"['metric2'] must be one of " + "SetterError AIPackage: type of argument \"metric\"['metric2'] must be one of " "(str, NoneType); got int instead: {'metric1': 'value', 'metric2': 250}" ) ] diff --git a/tests/spdx3/model/dataset/test_dataset.py b/tests/spdx3/model/dataset/test_dataset.py index a9b90c712..b442aa037 100644 --- a/tests/spdx3/model/dataset/test_dataset.py +++ b/tests/spdx3/model/dataset/test_dataset.py @@ -17,9 +17,9 @@ def test_correct_initialization(creation_information): intended_use="intended use", dataset_size=420000, dataset_noise="dataset noise", - data_preprocessing_steps="data preprocessing steps", - sensors={"sensor1": "some value"}, - known_biases="known biases", + data_preprocessing="data preprocessing steps", + sensor={"sensor1": "some value"}, + known_bias="known biases", sensitive_personal_information=True, anonymization_method_used=["anonymization method"], confidentiality_level=ConfidentialityLevelType.RED, @@ -31,9 +31,9 @@ def test_correct_initialization(creation_information): assert dataset.intended_use == "intended use" assert dataset.dataset_size == 420000 assert dataset.dataset_noise == "dataset noise" - assert dataset.data_preprocessing_steps == "data preprocessing steps" - assert dataset.sensors == {"sensor1": "some value"} - assert dataset.known_biases == "known biases" + assert dataset.data_preprocessing == "data preprocessing steps" + assert dataset.sensor == {"sensor1": "some value"} + assert dataset.known_bias == "known biases" assert dataset.sensitive_personal_information assert dataset.anonymization_method_used == ["anonymization method"] assert dataset.confidentiality_level == ConfidentialityLevelType.RED @@ -47,12 +47,12 @@ def test_invalid_initialization(creation_information): Dataset( "some_spdx_id", creation_information, - sensors={"sensor1": "value", "sensor2": 250}, + sensor={"sensor1": "value", "sensor2": 250}, ) assert err.value.args[0] == [ ( - "SetterError Dataset: type of argument \"sensors\"['sensor2'] must be one of " + "SetterError Dataset: type of argument \"sensor\"['sensor2'] must be one of " "(str, NoneType); got int instead: {'sensor1': 'value', 'sensor2': 250}" ) ] diff --git a/tests/spdx3/model/test_external_identifier.py b/tests/spdx3/model/test_external_identifier.py index ab37631fe..d25dad3bb 100644 --- a/tests/spdx3/model/test_external_identifier.py +++ b/tests/spdx3/model/test_external_identifier.py @@ -1,6 +1,8 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from unittest import TestCase + import pytest from spdx_tools.spdx3.model import ExternalIdentifier, ExternalIdentifierType @@ -8,16 +10,22 @@ def test_correct_initialization(): external_identifier = ExternalIdentifier( - ExternalIdentifierType.CPE22, "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", "This is a comment" + ExternalIdentifierType.CPE22, + "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", + "This is a comment", + ["first locator", "second locator"], + "authority", ) assert external_identifier.external_identifier_type == ExternalIdentifierType.CPE22 assert external_identifier.identifier == "cpe:/o:canonical:ubuntu_linux:10.04:-:lts" assert external_identifier.comment == "This is a comment" + TestCase().assertCountEqual(external_identifier.identifier_locator, ["first locator", "second locator"]) + assert external_identifier.issuing_authority == "authority" def test_invalid_initialization(): with pytest.raises(TypeError) as err: - ExternalIdentifier("CPE22", ["identifier", "another_identifier"], 34) + ExternalIdentifier("CPE22", ["identifier", "another_identifier"], 34, "locator", True) assert err.value.args[0] == [ 'SetterError ExternalIdentifier: type of argument "external_identifier_type" ' @@ -27,4 +35,8 @@ def test_invalid_initialization(): "got list instead: ['identifier', 'another_identifier']", 'SetterError ExternalIdentifier: type of argument "comment" must be one of ' "(str, NoneType); got int instead: 34", + 'SetterError ExternalIdentifier: type of argument "identifier_locator" must ' + "be a list; got str instead: locator", + 'SetterError ExternalIdentifier: type of argument "issuing_authority" must be ' + "one of (str, NoneType); got bool instead: True", ] From 582294d09f26125b67f9051b950838c72c87e155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 9 May 2023 07:57:48 +0200 Subject: [PATCH 197/354] [issue-426] update ExternalReferenceType MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/model/external_reference.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/spdx_tools/spdx3/model/external_reference.py b/src/spdx_tools/spdx3/model/external_reference.py index e1732ab33..127253595 100644 --- a/src/spdx_tools/spdx3/model/external_reference.py +++ b/src/spdx_tools/spdx3/model/external_reference.py @@ -12,10 +12,26 @@ class ExternalReferenceType(Enum): ALT_DOWNLOAD_LOCATION = auto() ALT_WEB_PAGE = auto() + BINARY_ARTIFACT = auto() + BUILD_META = auto() + BUILD_SYSTEM = auto() + CHAT = auto() + DOCUMENTATION = auto() + FUNDING = auto() + ISSUE_TRACKER = auto() + MAILING_LIST = auto() + METRICS = auto() + LICENSE = auto() OTHER = auto() + RELEASE_NOTES = auto() + RELEASE_HISTORY = auto() SECURITY_ADVISORY = auto() SECURITY_FIX = auto() SECURITY_OTHER = auto() + SOCIAL_MEDIA = auto() + SOURCE_ARTIFACT = auto() + SUPPORT = auto() + VCS = auto() @dataclass_with_properties From 738549ae46fdf4bef582a7bb15f2b5d2165c128a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 9 May 2023 07:49:58 +0200 Subject: [PATCH 198/354] [issue-426] update Relationship and RelationshipType MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../model/lifecycle_scoped_relationship.py | 3 ++ src/spdx_tools/spdx3/model/relationship.py | 30 ++++++++++++++++++- .../software_dependency_relationship.py | 3 ++ .../test_software_dependency_relationship.py | 5 ++++ .../test_lifecycle_scoped_relationship.py | 5 ++++ tests/spdx3/model/test_relationship.py | 5 ++++ 6 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py index 10f10ea53..7cb5927ad 100644 --- a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py +++ b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime from enum import Enum, auto from typing import List, Optional @@ -46,6 +47,8 @@ def __init__( external_identifier: List[ExternalIdentifier] = None, extension: None = None, completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, scope: Optional[LifecycleScopeType] = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index 3448c6b1b..61a73762c 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime from enum import Enum, auto from typing import List, Optional @@ -12,6 +13,7 @@ class RelationshipType(Enum): AMENDS = auto() ANCESTOR = auto() + AVAILABLE_FROM = auto() BUILD_DEPENDENCY = auto() BUILD_TOOL = auto() CONTAINS = auto() @@ -44,12 +46,34 @@ class RelationshipType(Enum): RUNTIME_DEPENDENCY = auto() SPECIFICATION_FOR = auto() STATIC_LINK = auto() - SUPPLIED_BY = auto() TEST = auto() TEST_CASE = auto() TEST_DEPENDENCY = auto() TEST_TOOL = auto() VARIANT = auto() + BUILD_INPUT_OF = auto() + BUILD_OUTPUT_OF = auto() + BUILD_CONFIG_OF = auto() + BUILD_INVOKED_BY = auto() + BUILD_ON_BEHALF_OF = auto() + BUILD_HOST_OF = auto() + HAS_ASSOCIATED_VULNERABILITY = auto() + COORDINATED_BY = auto() + HAS_CVSS_V2_ASSESSMENT_FOR = auto() + HAS_CVSS_V3_ASSESSMENT_FOR = auto() + HAS_EPSS_ASSESSMENT_FOR = auto() + HAS_EXPLOIT_CATALOG_ASSESSMENT_FOR = auto() + HAS_SSVC_ASSESSMENT_FOR = auto() + EXPLOIT_CREATED_BY = auto() + FIXED_BY = auto() + FOUND_BY = auto() + PUBLISHED_BY = auto() + REPORTED_BY = auto() + REPUBLISHED_BY = auto() + AFFECTS = auto() + DOES_NOT_AFFECT = auto() + FIXED_IN = auto() + UNDER_INVESTIGATION_FOR = auto() class RelationshipCompleteness(Enum): @@ -66,6 +90,8 @@ class Relationship(Element): to: List[str] = None relationship_type: RelationshipType = None completeness: Optional[RelationshipCompleteness] = None + start_time: Optional[datetime] = None + end_time: Optional[datetime] = None def __init__( self, @@ -83,6 +109,8 @@ def __init__( external_identifier: List[ExternalIdentifier] = None, extension: None = None, completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references diff --git a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py index 9d2c21dc7..9d6243c2f 100644 --- a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py +++ b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime from enum import Enum, auto from typing import List, Optional @@ -54,6 +55,8 @@ def __init__( external_identifier: List[ExternalIdentifier] = None, extension: None = None, completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, scope: Optional[LifecycleScopeType] = None, software_linkage: Optional[SoftwareDependencyLinkType] = None, conditionality: Optional[DependencyConditionalityType] = None, diff --git a/tests/spdx3/model/software/test_software_dependency_relationship.py b/tests/spdx3/model/software/test_software_dependency_relationship.py index 407bfd9c0..71ebc3931 100644 --- a/tests/spdx3/model/software/test_software_dependency_relationship.py +++ b/tests/spdx3/model/software/test_software_dependency_relationship.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime from unittest import mock import pytest @@ -22,6 +23,8 @@ def test_correct_initialization(creation_information): ["spdx_id2", "spdx_id3"], RelationshipType.DESCRIBES, completeness=RelationshipCompleteness.NOASSERTION, + start_time=datetime(11, 11, 11), + end_time=datetime(12, 12, 12), scope=LifecycleScopeType.DESIGN, software_linkage=SoftwareDependencyLinkType.STATIC, conditionality=DependencyConditionalityType.PROVIDED, @@ -33,6 +36,8 @@ def test_correct_initialization(creation_information): assert relationship.to == ["spdx_id2", "spdx_id3"] assert relationship.relationship_type == RelationshipType.DESCRIBES assert relationship.completeness == RelationshipCompleteness.NOASSERTION + assert relationship.start_time == datetime(11, 11, 11) + assert relationship.end_time == datetime(12, 12, 12) assert relationship.scope == LifecycleScopeType.DESIGN assert relationship.software_linkage == SoftwareDependencyLinkType.STATIC assert relationship.conditionality == DependencyConditionalityType.PROVIDED diff --git a/tests/spdx3/model/test_lifecycle_scoped_relationship.py b/tests/spdx3/model/test_lifecycle_scoped_relationship.py index 495bbe4cc..00c1adeee 100644 --- a/tests/spdx3/model/test_lifecycle_scoped_relationship.py +++ b/tests/spdx3/model/test_lifecycle_scoped_relationship.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime from unittest import mock import pytest @@ -22,6 +23,8 @@ def test_correct_initialization(creation_information): ["spdx_id2", "spdx_id3"], RelationshipType.DESCRIBES, completeness=RelationshipCompleteness.NOASSERTION, + start_time=datetime(11, 11, 11), + end_time=datetime(12, 12, 12), scope=LifecycleScopeType.DESIGN, ) @@ -31,6 +34,8 @@ def test_correct_initialization(creation_information): assert relationship.to == ["spdx_id2", "spdx_id3"] assert relationship.relationship_type == RelationshipType.DESCRIBES assert relationship.completeness == RelationshipCompleteness.NOASSERTION + assert relationship.start_time == datetime(11, 11, 11) + assert relationship.end_time == datetime(12, 12, 12) assert relationship.scope == LifecycleScopeType.DESIGN diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py index 1c6d9c766..64743de0b 100644 --- a/tests/spdx3/model/test_relationship.py +++ b/tests/spdx3/model/test_relationship.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime from unittest import mock import pytest @@ -17,6 +18,8 @@ def test_correct_initialization(creation_information): ["spdx_id2", "spdx_id3"], RelationshipType.DESCRIBES, completeness=RelationshipCompleteness.NOASSERTION, + start_time=datetime(11, 11, 11), + end_time=datetime(12, 12, 12), ) assert relationship.spdx_id == "SPDXRef-Relationship" @@ -25,6 +28,8 @@ def test_correct_initialization(creation_information): assert relationship.to == ["spdx_id2", "spdx_id3"] assert relationship.relationship_type == RelationshipType.DESCRIBES assert relationship.completeness == RelationshipCompleteness.NOASSERTION + assert relationship.start_time == datetime(11, 11, 11) + assert relationship.end_time == datetime(12, 12, 12) @mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) From 6884f87a57e806d3306f8d8aa1d1dc3361ad2772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 8 May 2023 16:27:33 +0200 Subject: [PATCH 199/354] [issue-426] add licensing profile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../spdx3/model/licensing/__init__.py | 17 ++++++++++ .../spdx3/model/licensing/any_license_info.py | 14 ++++++++ .../licensing/conjunctive_license_set.py | 16 +++++++++ .../spdx3/model/licensing/custom_license.py | 28 ++++++++++++++++ .../licensing/custom_license_addition.py | 25 ++++++++++++++ .../licensing/disjunctive_license_set.py | 16 +++++++++ .../spdx3/model/licensing/license.py | 28 ++++++++++++++++ .../spdx3/model/licensing/license_addition.py | 24 ++++++++++++++ .../spdx3/model/licensing/license_field.py | 13 ++++++++ .../spdx3/model/licensing/listed_license.py | 33 +++++++++++++++++++ .../licensing/listed_license_exception.py | 30 +++++++++++++++++ .../model/licensing/no_assertion_license.py | 11 +++++++ .../spdx3/model/licensing/none_license.py | 11 +++++++ .../model/licensing/or_later_operator.py | 15 +++++++++ .../model/licensing/with_addition_operator.py | 17 ++++++++++ 15 files changed, 298 insertions(+) create mode 100644 src/spdx_tools/spdx3/model/licensing/__init__.py create mode 100644 src/spdx_tools/spdx3/model/licensing/any_license_info.py create mode 100644 src/spdx_tools/spdx3/model/licensing/conjunctive_license_set.py create mode 100644 src/spdx_tools/spdx3/model/licensing/custom_license.py create mode 100644 src/spdx_tools/spdx3/model/licensing/custom_license_addition.py create mode 100644 src/spdx_tools/spdx3/model/licensing/disjunctive_license_set.py create mode 100644 src/spdx_tools/spdx3/model/licensing/license.py create mode 100644 src/spdx_tools/spdx3/model/licensing/license_addition.py create mode 100644 src/spdx_tools/spdx3/model/licensing/license_field.py create mode 100644 src/spdx_tools/spdx3/model/licensing/listed_license.py create mode 100644 src/spdx_tools/spdx3/model/licensing/listed_license_exception.py create mode 100644 src/spdx_tools/spdx3/model/licensing/no_assertion_license.py create mode 100644 src/spdx_tools/spdx3/model/licensing/none_license.py create mode 100644 src/spdx_tools/spdx3/model/licensing/or_later_operator.py create mode 100644 src/spdx_tools/spdx3/model/licensing/with_addition_operator.py diff --git a/src/spdx_tools/spdx3/model/licensing/__init__.py b/src/spdx_tools/spdx3/model/licensing/__init__.py new file mode 100644 index 000000000..073f36d06 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/__init__.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from any_license_info import AnyLicenseInfo +from conjunctive_license_set import ConjunctiveLicenseSet +from custom_license import CustomLicense +from custom_license_addition import CustomLicenseAddition +from disjunctive_license_set import DisjunctiveLicenseSet +from license import License +from license_addition import LicenseAddition +from license_field import LicenseField +from listed_license import ListedLicense +from listed_license_exception import ListedLicenseException +from no_assertion_license import NoAssertionLicense +from none_license import NoneLicense +from or_later_operator import OrLaterOperator +from with_addition_operator import WithAdditionOperator diff --git a/src/spdx_tools/spdx3/model/licensing/any_license_info.py b/src/spdx_tools/spdx3/model/licensing/any_license_info.py new file mode 100644 index 000000000..93afac591 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/any_license_info.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import ABC, abstractmethod + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model.licensing.license_field import LicenseField + + +@dataclass_with_properties +class AnyLicenseInfo(ABC, LicenseField): + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/conjunctive_license_set.py b/src/spdx_tools/spdx3/model/licensing/conjunctive_license_set.py new file mode 100644 index 000000000..e8e4f5611 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/conjunctive_license_set.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import List + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo + + +@dataclass_with_properties +class ConjunctiveLicenseSet(AnyLicenseInfo): + member: List[AnyLicenseInfo] + + def __init__(self, member: List[AnyLicenseInfo]): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/custom_license.py b/src/spdx_tools/spdx3/model/licensing/custom_license.py new file mode 100644 index 000000000..773081f8d --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/custom_license.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.license import License + + +@dataclass_with_properties +class CustomLicense(License): + def __init__( + self, + license_id: str, + license_name: str, + license_text: str, + license_comment: Optional[str] = None, + see_also: List[str] = None, + is_osi_approved: Optional[bool] = None, + is_fsf_libre: Optional[bool] = None, + standard_license_header: Optional[str] = None, + standard_license_template: Optional[str] = None, + is_deprecated_license_id: Optional[bool] = None, + obsoleted_by: Optional[str] = None, + ): + see_also = [] if see_also is None else see_also + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/custom_license_addition.py b/src/spdx_tools/spdx3/model/licensing/custom_license_addition.py new file mode 100644 index 000000000..707a28883 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/custom_license_addition.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.license_addition import LicenseAddition + + +@dataclass_with_properties +class CustomLicenseAddition(LicenseAddition): + def __init__( + self, + addition_id: str, + addition_name: str, + addition_text: str, + addition_comment: Optional[str] = None, + see_also: List[str] = None, + standard_addition_template: Optional[str] = None, + is_deprecated_addition_id: Optional[bool] = None, + obsoleted_by: Optional[str] = None, + ): + see_also = [] if see_also is None else see_also + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/disjunctive_license_set.py b/src/spdx_tools/spdx3/model/licensing/disjunctive_license_set.py new file mode 100644 index 000000000..00d63aee7 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/disjunctive_license_set.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import List + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo + + +@dataclass_with_properties +class DisjunctiveLicenseSet(AnyLicenseInfo): + member: List[AnyLicenseInfo] + + def __init__(self, member: List[AnyLicenseInfo]): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/license.py b/src/spdx_tools/spdx3/model/licensing/license.py new file mode 100644 index 000000000..5471eb806 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/license.py @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import ABC, abstractmethod +from dataclasses import field +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo + + +@dataclass_with_properties +class License(ABC, AnyLicenseInfo): + license_id: str + license_name: str + license_text: str + license_comment: Optional[str] = None + see_also: List[str] = field(default_factory=list) + is_osi_approved: Optional[bool] = None + is_fsf_libre: Optional[bool] = None + standard_license_header: Optional[str] = None + standard_license_template: Optional[str] = None + is_deprecated_license_id: Optional[bool] = None + obsoleted_by: Optional[str] = None + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/license_addition.py b/src/spdx_tools/spdx3/model/licensing/license_addition.py new file mode 100644 index 000000000..cb7e7d755 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/license_addition.py @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import ABC, abstractmethod +from dataclasses import field +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties + + +@dataclass_with_properties +class LicenseAddition(ABC): + addition_id: str + addition_name: str + addition_text: str + addition_comment: Optional[str] = None + see_also: List[str] = field(default_factory=list) + standard_addition_template: Optional[str] = None + is_deprecated_addition_id: Optional[bool] = None + obsoleted_by: Optional[str] = None + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/license_field.py b/src/spdx_tools/spdx3/model/licensing/license_field.py new file mode 100644 index 000000000..39e4aecf7 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/license_field.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import ABC, abstractmethod + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties + + +@dataclass_with_properties +class LicenseField(ABC): + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/listed_license.py b/src/spdx_tools/spdx3/model/licensing/listed_license.py new file mode 100644 index 000000000..e438ac4a0 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/listed_license.py @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.license import License + + +@dataclass_with_properties +class ListedLicense(License): + list_version_added: Optional[str] = None + deprecated_version: Optional[str] = None + + def __init__( + self, + license_id: str, + license_name: str, + license_text: str, + license_comment: Optional[str] = None, + see_also: List[str] = None, + is_osi_approved: Optional[bool] = None, + is_fsf_libre: Optional[bool] = None, + standard_license_header: Optional[str] = None, + standard_license_template: Optional[str] = None, + is_deprecated_license_id: Optional[bool] = None, + obsoleted_by: Optional[str] = None, + list_version_added: Optional[str] = None, + deprecated_version: Optional[str] = None, + ): + see_also = [] if see_also is None else see_also + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/listed_license_exception.py b/src/spdx_tools/spdx3/model/licensing/listed_license_exception.py new file mode 100644 index 000000000..56ddaa897 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/listed_license_exception.py @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.license_addition import LicenseAddition + + +@dataclass_with_properties +class ListedLicenseException(LicenseAddition): + list_version_added: Optional[str] = None + deprecated_version: Optional[str] = None + + def __init__( + self, + addition_id: str, + addition_name: str, + addition_text: str, + addition_comment: Optional[str] = None, + see_also: List[str] = None, + standard_addition_template: Optional[str] = None, + is_deprecated_addition_id: Optional[bool] = None, + obsoleted_by: Optional[str] = None, + list_version_added: Optional[str] = None, + deprecated_version: Optional[str] = None, + ): + see_also = [] if see_also is None else see_also + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/no_assertion_license.py b/src/spdx_tools/spdx3/model/licensing/no_assertion_license.py new file mode 100644 index 000000000..3ec518971 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/no_assertion_license.py @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model.licensing.license_field import LicenseField + + +@dataclass_with_properties +class NoAssertionLicense(LicenseField): + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/none_license.py b/src/spdx_tools/spdx3/model/licensing/none_license.py new file mode 100644 index 000000000..582c81033 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/none_license.py @@ -0,0 +1,11 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model.licensing.license_field import LicenseField + + +@dataclass_with_properties +class NoneLicense(LicenseField): + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/licensing/or_later_operator.py b/src/spdx_tools/spdx3/model/licensing/or_later_operator.py new file mode 100644 index 000000000..2aa204b98 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/or_later_operator.py @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo +from spdx_tools.spdx3.model.licensing.license import License + + +@dataclass_with_properties +class OrLaterOperator(AnyLicenseInfo): + subject_license: License + + def __init__(self, subject_license: License): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/licensing/with_addition_operator.py b/src/spdx_tools/spdx3/model/licensing/with_addition_operator.py new file mode 100644 index 000000000..9e79f8d98 --- /dev/null +++ b/src/spdx_tools/spdx3/model/licensing/with_addition_operator.py @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo +from spdx_tools.spdx3.model.licensing.license import License +from spdx_tools.spdx3.model.licensing.license_addition import LicenseAddition + + +@dataclass_with_properties +class WithAdditionOperator(AnyLicenseInfo): + subject_license: License + subject_addition: LicenseAddition + + def __init__(self, subject_license: License, subject_addition: LicenseAddition): + check_types_and_set_values(self, locals()) From 56028491ccaea89877f0460933cf51c344850317 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 9 May 2023 12:16:41 +0200 Subject: [PATCH 200/354] fix licensing profile - update import paths in __init__.py - remove dataclass annotation for classes without fields Signed-off-by: Meret Behrens --- .../spdx3/model/licensing/__init__.py | 28 +++++++++---------- .../spdx3/model/licensing/any_license_info.py | 6 ++-- .../spdx3/model/licensing/license.py | 4 +-- .../spdx3/model/licensing/license_field.py | 3 -- .../model/licensing/no_assertion_license.py | 2 -- .../spdx3/model/licensing/none_license.py | 2 -- 6 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/spdx_tools/spdx3/model/licensing/__init__.py b/src/spdx_tools/spdx3/model/licensing/__init__.py index 073f36d06..8d9b9c6af 100644 --- a/src/spdx_tools/spdx3/model/licensing/__init__.py +++ b/src/spdx_tools/spdx3/model/licensing/__init__.py @@ -1,17 +1,17 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from any_license_info import AnyLicenseInfo -from conjunctive_license_set import ConjunctiveLicenseSet -from custom_license import CustomLicense -from custom_license_addition import CustomLicenseAddition -from disjunctive_license_set import DisjunctiveLicenseSet -from license import License -from license_addition import LicenseAddition -from license_field import LicenseField -from listed_license import ListedLicense -from listed_license_exception import ListedLicenseException -from no_assertion_license import NoAssertionLicense -from none_license import NoneLicense -from or_later_operator import OrLaterOperator -from with_addition_operator import WithAdditionOperator +from .any_license_info import AnyLicenseInfo +from .conjunctive_license_set import ConjunctiveLicenseSet +from .custom_license import CustomLicense +from .custom_license_addition import CustomLicenseAddition +from .disjunctive_license_set import DisjunctiveLicenseSet +from .license import License +from .license_addition import LicenseAddition +from .license_field import LicenseField +from .listed_license import ListedLicense +from .listed_license_exception import ListedLicenseException +from .no_assertion_license import NoAssertionLicense +from .none_license import NoneLicense +from .or_later_operator import OrLaterOperator +from .with_addition_operator import WithAdditionOperator diff --git a/src/spdx_tools/spdx3/model/licensing/any_license_info.py b/src/spdx_tools/spdx3/model/licensing/any_license_info.py index 93afac591..1f1402427 100644 --- a/src/spdx_tools/spdx3/model/licensing/any_license_info.py +++ b/src/spdx_tools/spdx3/model/licensing/any_license_info.py @@ -1,14 +1,12 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from abc import ABC, abstractmethod +from abc import abstractmethod -from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.spdx3.model.licensing.license_field import LicenseField -@dataclass_with_properties -class AnyLicenseInfo(ABC, LicenseField): +class AnyLicenseInfo(LicenseField): @abstractmethod def __init__(self): pass diff --git a/src/spdx_tools/spdx3/model/licensing/license.py b/src/spdx_tools/spdx3/model/licensing/license.py index 5471eb806..3d1c87822 100644 --- a/src/spdx_tools/spdx3/model/licensing/license.py +++ b/src/spdx_tools/spdx3/model/licensing/license.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from abc import ABC, abstractmethod +from abc import abstractmethod from dataclasses import field from typing import List, Optional @@ -10,7 +10,7 @@ @dataclass_with_properties -class License(ABC, AnyLicenseInfo): +class License(AnyLicenseInfo): license_id: str license_name: str license_text: str diff --git a/src/spdx_tools/spdx3/model/licensing/license_field.py b/src/spdx_tools/spdx3/model/licensing/license_field.py index 39e4aecf7..babe141f2 100644 --- a/src/spdx_tools/spdx3/model/licensing/license_field.py +++ b/src/spdx_tools/spdx3/model/licensing/license_field.py @@ -3,10 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from abc import ABC, abstractmethod -from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties - -@dataclass_with_properties class LicenseField(ABC): @abstractmethod def __init__(self): diff --git a/src/spdx_tools/spdx3/model/licensing/no_assertion_license.py b/src/spdx_tools/spdx3/model/licensing/no_assertion_license.py index 3ec518971..66a00b261 100644 --- a/src/spdx_tools/spdx3/model/licensing/no_assertion_license.py +++ b/src/spdx_tools/spdx3/model/licensing/no_assertion_license.py @@ -1,11 +1,9 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.spdx3.model.licensing.license_field import LicenseField -@dataclass_with_properties class NoAssertionLicense(LicenseField): def __init__(self): pass diff --git a/src/spdx_tools/spdx3/model/licensing/none_license.py b/src/spdx_tools/spdx3/model/licensing/none_license.py index 582c81033..e34253608 100644 --- a/src/spdx_tools/spdx3/model/licensing/none_license.py +++ b/src/spdx_tools/spdx3/model/licensing/none_license.py @@ -1,11 +1,9 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.spdx3.model.licensing.license_field import LicenseField -@dataclass_with_properties class NoneLicense(LicenseField): def __init__(self): pass From 8c8c7b4984c3e487e8ee256591133091596bf465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 9 May 2023 12:37:33 +0200 Subject: [PATCH 201/354] [issue-426] add SoftwareArtifact MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../spdx3/bump_from_spdx2/package.py | 2 +- src/spdx_tools/spdx3/model/ai/ai_package.py | 13 +++++++--- src/spdx_tools/spdx3/model/dataset/dataset.py | 17 ++++++++----- src/spdx_tools/spdx3/model/software/file.py | 23 ++++++++--------- .../spdx3/model/software/package.py | 25 ++++++++----------- .../spdx3/model/software/snippet.py | 25 ++++++++----------- .../spdx3/model/software/software_artifact.py | 24 ++++++++++++++++++ tests/spdx3/model/ai/test_ai_package.py | 2 ++ tests/spdx3/model/dataset/test_dataset.py | 2 ++ tests/spdx3/model/software/test_file.py | 8 +++--- tests/spdx3/model/software/test_package.py | 8 +++--- tests/spdx3/model/software/test_snippet.py | 4 +-- 12 files changed, 91 insertions(+), 62 deletions(-) create mode 100644 src/spdx_tools/spdx3/model/software/software_artifact.py diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index f7d789ef8..2befb9fe9 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -87,7 +87,7 @@ def bump_package( built_time=spdx2_package.built_date, release_time=spdx2_package.release_date, valid_until_time=spdx2_package.valid_until_date, - package_purpose=package_purpose, + purpose=package_purpose, package_version=spdx2_package.version, download_location=download_location, package_url=package_url, diff --git a/src/spdx_tools/spdx3/model/ai/ai_package.py b/src/spdx_tools/spdx3/model/ai/ai_package.py index 0a6811929..9c2372618 100644 --- a/src/spdx_tools/spdx3/model/ai/ai_package.py +++ b/src/spdx_tools/spdx3/model/ai/ai_package.py @@ -9,6 +9,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model.licensing import LicenseField from spdx_tools.spdx3.model.software import Package, SoftwarePurpose @@ -41,7 +42,7 @@ def __init__( self, spdx_id: str, creation_info: CreationInformation, - name: Optional[str] = None, + name: str, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, @@ -50,11 +51,15 @@ def __init__( external_identifier: List[ExternalIdentifier] = None, extension: None = None, originated_by: Optional[str] = None, - content_identifier: Optional[str] = None, built_time: Optional[datetime] = None, release_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, - package_purpose: List[SoftwarePurpose] = None, + content_identifier: Optional[str] = None, + purpose: List[SoftwarePurpose] = None, + concluded_license: Optional[LicenseField] = None, + declared_license: Optional[LicenseField] = None, + copyright_text: Optional[str] = None, + attribution_text: Optional[str] = None, package_version: Optional[str] = None, download_location: Optional[str] = None, package_url: Optional[str] = None, @@ -79,7 +84,7 @@ def __init__( verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier - package_purpose = [] if package_purpose is None else package_purpose + purpose = [] if purpose is None else purpose standard_compliance = [] if standard_compliance is None else standard_compliance type_of_model = [] if type_of_model is None else type_of_model hyperparameter = {} if hyperparameter is None else hyperparameter diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py index c6ec8c448..187540eca 100644 --- a/src/spdx_tools/spdx3/model/dataset/dataset.py +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -1,6 +1,6 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors +# SPDX-FileCopyrightText: 2023 spdx contributors # -# SPDX-License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 from dataclasses import field from datetime import datetime from enum import Enum, auto @@ -9,6 +9,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model.licensing import LicenseField from spdx_tools.spdx3.model.software import Package, SoftwarePurpose @@ -46,7 +47,7 @@ def __init__( self, spdx_id: str, creation_info: CreationInformation, - name: Optional[str] = None, + name: str, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, @@ -55,11 +56,15 @@ def __init__( external_identifier: List[ExternalIdentifier] = None, extension: None = None, originated_by: Optional[str] = None, - content_identifier: Optional[str] = None, built_time: Optional[datetime] = None, release_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, - package_purpose: List[SoftwarePurpose] = None, + content_identifier: Optional[str] = None, + purpose: List[SoftwarePurpose] = None, + concluded_license: Optional[LicenseField] = None, + declared_license: Optional[LicenseField] = None, + copyright_text: Optional[str] = None, + attribution_text: Optional[str] = None, package_version: Optional[str] = None, download_location: Optional[str] = None, package_url: Optional[str] = None, @@ -81,7 +86,7 @@ def __init__( verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier - package_purpose = [] if package_purpose is None else package_purpose + purpose = [] if purpose is None else purpose sensors = {} if sensor is None else sensor anonymization_method_used = [] if anonymization_method_used is None else anonymization_method_used check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py index a138b0dc2..61e119f74 100644 --- a/src/spdx_tools/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -1,26 +1,19 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from dataclasses import field from datetime import datetime from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import ( - Artifact, - CreationInformation, - ExternalIdentifier, - ExternalReference, - IntegrityMethod, -) +from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model.licensing import LicenseField from spdx_tools.spdx3.model.software import SoftwarePurpose +from spdx_tools.spdx3.model.software.software_artifact import SoftwareArtifact @dataclass_with_properties -class File(Artifact): - content_identifier: Optional[str] = None # should be a valid URI - file_purpose: List[SoftwarePurpose] = field(default_factory=list) +class File(SoftwareArtifact): content_type: Optional[str] = None # placeholder for MediaType def __init__( @@ -40,11 +33,15 @@ def __init__( release_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, content_identifier: Optional[str] = None, - file_purpose: List[SoftwarePurpose] = None, + purpose: List[SoftwarePurpose] = None, + concluded_license: Optional[LicenseField] = None, + declared_license: Optional[LicenseField] = None, + copyright_text: Optional[str] = None, + attribution_text: Optional[str] = None, content_type: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier - file_purpose = [] if file_purpose is None else file_purpose + purpose = [] if purpose is None else purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py index bf7e5e85e..bb49a36a2 100644 --- a/src/spdx_tools/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -1,26 +1,19 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from dataclasses import field from datetime import datetime from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import ( - Artifact, - CreationInformation, - ExternalIdentifier, - ExternalReference, - IntegrityMethod, -) +from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model.licensing import LicenseField from spdx_tools.spdx3.model.software import SoftwarePurpose +from spdx_tools.spdx3.model.software.software_artifact import SoftwareArtifact @dataclass_with_properties -class Package(Artifact): - content_identifier: Optional[str] = None # anyURI - package_purpose: List[SoftwarePurpose] = field(default_factory=list) +class Package(SoftwareArtifact): package_version: Optional[str] = None download_location: Optional[str] = None # anyURI package_url: Optional[str] = None # anyURI @@ -40,11 +33,15 @@ def __init__( external_identifier: List[ExternalIdentifier] = None, extension: None = None, originated_by: Optional[str] = None, - content_identifier: Optional[str] = None, built_time: Optional[datetime] = None, release_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, - package_purpose: List[SoftwarePurpose] = None, + content_identifier: Optional[str] = None, + purpose: List[SoftwarePurpose] = None, + concluded_license: Optional[LicenseField] = None, + declared_license: Optional[LicenseField] = None, + copyright_text: Optional[str] = None, + attribution_text: Optional[str] = None, package_version: Optional[str] = None, download_location: Optional[str] = None, package_url: Optional[str] = None, @@ -54,5 +51,5 @@ def __init__( verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier - package_purpose = [] if package_purpose is None else package_purpose + purpose = [] if purpose is None else purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py index 160090ad4..d9f5621e5 100644 --- a/src/spdx_tools/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -1,26 +1,19 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from dataclasses import field from datetime import datetime from typing import List, Optional, Tuple from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import ( - Artifact, - CreationInformation, - ExternalIdentifier, - ExternalReference, - IntegrityMethod, -) +from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model.licensing import LicenseField from spdx_tools.spdx3.model.software import SoftwarePurpose +from spdx_tools.spdx3.model.software.software_artifact import SoftwareArtifact @dataclass_with_properties -class Snippet(Artifact): - content_identifier: Optional[str] = None # anyURI - snippet_purpose: List[SoftwarePurpose] = field(default_factory=list) +class Snippet(SoftwareArtifact): byte_range: Optional[Tuple[int, int]] = None line_range: Optional[Tuple[int, int]] = None @@ -37,16 +30,20 @@ def __init__( external_identifier: List[ExternalIdentifier] = None, extension: None = None, originated_by: Optional[str] = None, - content_identifier: Optional[str] = None, built_time: Optional[datetime] = None, release_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, - snippet_purpose: List[SoftwarePurpose] = None, + content_identifier: Optional[str] = None, + purpose: List[SoftwarePurpose] = None, + concluded_license: Optional[LicenseField] = None, + declared_license: Optional[LicenseField] = None, + copyright_text: Optional[str] = None, + attribution_text: Optional[str] = None, byte_range: Optional[Tuple[int, int]] = None, line_range: Optional[Tuple[int, int]] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier - snippet_purpose = [] if snippet_purpose is None else snippet_purpose + purpose = [] if purpose is None else purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/software_artifact.py b/src/spdx_tools/spdx3/model/software/software_artifact.py new file mode 100644 index 000000000..d3dd2f9e6 --- /dev/null +++ b/src/spdx_tools/spdx3/model/software/software_artifact.py @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import abstractmethod +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model import Artifact +from spdx_tools.spdx3.model.licensing import LicenseField +from spdx_tools.spdx3.model.software import SoftwarePurpose + + +@dataclass_with_properties +class SoftwareArtifact(Artifact): + content_identifier: Optional[str] = None + purpose: List[SoftwarePurpose] = None + concluded_license: Optional[LicenseField] = None + declared_license: Optional[LicenseField] = None + copyright_text: Optional[str] = None + attribution_text: Optional[str] = None + + @abstractmethod + def __init__(self): + pass diff --git a/tests/spdx3/model/ai/test_ai_package.py b/tests/spdx3/model/ai/test_ai_package.py index 00b7e6da5..61c272ba7 100644 --- a/tests/spdx3/model/ai/test_ai_package.py +++ b/tests/spdx3/model/ai/test_ai_package.py @@ -14,6 +14,7 @@ def test_correct_initialization(creation_information): ai_package = AIPackage( "some_spdx_id", creation_information, + "AI Package name", energy_consumption="energy consumption", standard_compliance=["some standard"], limitation="limitation", @@ -54,6 +55,7 @@ def test_invalid_initialization(creation_information): AIPackage( "some_spdx_id", creation_information, + "AI Package name", metric={"metric1": "value", "metric2": 250}, ) diff --git a/tests/spdx3/model/dataset/test_dataset.py b/tests/spdx3/model/dataset/test_dataset.py index b442aa037..da2f2b477 100644 --- a/tests/spdx3/model/dataset/test_dataset.py +++ b/tests/spdx3/model/dataset/test_dataset.py @@ -13,6 +13,7 @@ def test_correct_initialization(creation_information): dataset = Dataset( "some_spdx_id", creation_information, + "Dataset name", data_collection_process="data collection process", intended_use="intended use", dataset_size=420000, @@ -47,6 +48,7 @@ def test_invalid_initialization(creation_information): Dataset( "some_spdx_id", creation_information, + "Dataset name", sensor={"sensor1": "value", "sensor2": 250}, ) diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index 495b4ea13..cf454cc33 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -16,7 +16,7 @@ def test_correct_initialization(creation_information): "Test file", verified_using=None, content_identifier="https://any.uri", - file_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE], + purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE], content_type="MediaType", ) @@ -24,7 +24,7 @@ def test_correct_initialization(creation_information): assert file.creation_info == creation_information assert file.name == "Test file" assert file.content_identifier == "https://any.uri" - assert file.file_purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE] + assert file.purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE] assert file.content_type == "MediaType" @@ -36,7 +36,7 @@ def test_invalid_initialization(creation_information): creation_information, "test file", content_identifier=3, - file_purpose=SoftwarePurpose.FILE, + purpose=SoftwarePurpose.FILE, content_type=SoftwarePurpose.ARCHIVE, ) @@ -44,7 +44,7 @@ def test_invalid_initialization(creation_information): 'SetterError File: type of argument "spdx_id" must be str; got int instead: 1', 'SetterError File: type of argument "content_identifier" must be one of (str, ' "NoneType); got int instead: 3", - 'SetterError File: type of argument "file_purpose" must be a list; got ' + 'SetterError File: type of argument "purpose" must be a list; got ' "spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose instead: " "SoftwarePurpose.FILE", 'SetterError File: type of argument "content_type" must be one of (str, ' diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 428b00367..fd59b9762 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -19,7 +19,7 @@ def test_correct_initialization(creation_information): built_time=datetime(2022, 1, 1), release_time=datetime(2022, 1, 2), valid_until_time=datetime(2022, 1, 3), - package_purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH], + purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH], package_version="1:23a_bc", download_location="https://downloadlocation", package_url="https://package.uri", @@ -34,7 +34,7 @@ def test_correct_initialization(creation_information): assert package.built_time == datetime(2022, 1, 1) assert package.release_time == datetime(2022, 1, 2) assert package.valid_until_time == datetime(2022, 1, 3) - assert package.package_purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH] + assert package.purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH] assert package.package_version == "1:23a_bc" assert package.download_location == "https://downloadlocation" assert package.package_url == "https://package.uri" @@ -51,7 +51,7 @@ def test_invalid_initialization(creation_information): "Test package", built_time="2022-03-04T00:00:00Z", content_identifier=3, - package_purpose=SoftwarePurpose.FILE, + purpose=SoftwarePurpose.FILE, package_version=42, download_location=4, package_url=["uris"], @@ -64,7 +64,7 @@ def test_invalid_initialization(creation_information): "(datetime.datetime, NoneType); got str instead: 2022-03-04T00:00:00Z", 'SetterError Package: type of argument "content_identifier" must be one of ' "(str, NoneType); got int instead: 3", - 'SetterError Package: type of argument "package_purpose" must be a list; got ' + 'SetterError Package: type of argument "purpose" must be a list; got ' "spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose instead: " "SoftwarePurpose.FILE", 'SetterError Package: type of argument "package_version" must be one of ' diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index 4657cc635..d6c5599f7 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -14,7 +14,7 @@ def test_correct_initialization(creation_information): "SPDXRef-Snippet", creation_information, content_identifier="https://content.identifier", - snippet_purpose=[SoftwarePurpose.SOURCE], + purpose=[SoftwarePurpose.SOURCE], byte_range=(3, 4), line_range=(346, 456), ) @@ -22,7 +22,7 @@ def test_correct_initialization(creation_information): assert snippet.spdx_id == "SPDXRef-Snippet" assert snippet.creation_info == creation_information assert snippet.content_identifier == "https://content.identifier" - assert snippet.snippet_purpose == [SoftwarePurpose.SOURCE] + assert snippet.purpose == [SoftwarePurpose.SOURCE] assert snippet.byte_range == (3, 4) assert snippet.line_range == (346, 456) From 86be027acb207183d242bd4f77b1491baee28c9a Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 26 Apr 2023 08:41:13 +0200 Subject: [PATCH 202/354] [issue-602] fix relationship bump Signed-off-by: Meret Behrens --- .../spdx3/bump_from_spdx2/relationship.py | 289 +++++++++++++++--- .../spdx3/bump_from_spdx2/spdx_document.py | 5 +- .../spdx3/writer/console/payload_writer.py | 3 +- tests/spdx3/bump/test_relationship_bump.py | 97 ++++++ 4 files changed, 347 insertions(+), 47 deletions(-) create mode 100644 tests/spdx3/bump/test_relationship_bump.py diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py index 874721ee4..a60ea16e3 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -1,45 +1,221 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Optional, Tuple +from typing import Dict, List, Optional, Tuple, Union -from spdx_tools.spdx3.model import CreationInformation, Relationship, RelationshipCompleteness, RelationshipType +from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion +from spdx_tools.spdx3.model import ( + CreationInformation, + LifecycleScopeType, + Relationship, + RelationshipCompleteness, + RelationshipType, +) +from spdx_tools.spdx3.model.software import ( + DependencyConditionalityType, + SoftwareDependencyLinkType, + SoftwareDependencyRelationship, +) from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.relationship import Relationship as Spdx2_Relationship from spdx_tools.spdx.model.relationship import RelationshipType as Spdx2_RelationshipType from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx_tools.spdx.model.spdx_none import SpdxNone +# bump relationship type, map each relationship type to the corresponding class in 3.0, +# the relationship type, other arguments and if swapped +relationship_mapping: Dict[ + Spdx2_RelationshipType, + Tuple[ + bool, + RelationshipType, + Union[bool, LifecycleScopeType, None], + Optional[SoftwareDependencyLinkType], + Optional[DependencyConditionalityType], + ], +] = { + Spdx2_RelationshipType.AMENDS: (True, RelationshipType.AMENDS), + Spdx2_RelationshipType.ANCESTOR_OF: (True, RelationshipType.ANCESTOR), + Spdx2_RelationshipType.BUILD_DEPENDENCY_OF: ( + False, + RelationshipType.DEPENDS_ON, + LifecycleScopeType.BUILD, + SoftwareDependencyLinkType.TOOL, + None, + ), + Spdx2_RelationshipType.BUILD_TOOL_OF: ( + False, + RelationshipType.DEPENDS_ON, + LifecycleScopeType.BUILD, + SoftwareDependencyLinkType.TOOL, + None, + ), + Spdx2_RelationshipType.CONTAINED_BY: (True, RelationshipType.CONTAINS, True), + Spdx2_RelationshipType.CONTAINS: ( + True, + RelationshipType.CONTAINS, + ), # might be deleted in favor of depends on + Spdx2_RelationshipType.COPY_OF: (True, RelationshipType.COPY), + Spdx2_RelationshipType.DATA_FILE_OF: None, # not defined, probably input/ output + Spdx2_RelationshipType.DEPENDENCY_MANIFEST_OF: ( + False, + RelationshipType.DEPENDS_ON, + None, + None, + None, + ), # "expect purpose has been set to manifest" + Spdx2_RelationshipType.DEPENDENCY_OF: (False, RelationshipType.DEPENDS_ON, True), + Spdx2_RelationshipType.DEPENDS_ON: ( + False, + RelationshipType.DEPENDS_ON, + ), + Spdx2_RelationshipType.DESCENDANT_OF: (True, RelationshipType.ANCESTOR, True), + Spdx2_RelationshipType.DESCRIBED_BY: (True, RelationshipType.DESCRIBES, True), + Spdx2_RelationshipType.DESCRIBES: (True, RelationshipType.DESCRIBES), # might be deleted in favor of root + # property + Spdx2_RelationshipType.DEV_DEPENDENCY_OF: ( + False, + RelationshipType.DEPENDS_ON, + LifecycleScopeType.DEVELOPMENT, + None, + None, + ), + Spdx2_RelationshipType.DEV_TOOL_OF: ( + False, + RelationshipType.DEPENDS_ON, + LifecycleScopeType.DEVELOPMENT, + SoftwareDependencyLinkType.TOOL, + None, + ), + Spdx2_RelationshipType.DISTRIBUTION_ARTIFACT: None, # not defined yet, purpose? + Spdx2_RelationshipType.DOCUMENTATION_OF: (True, RelationshipType.DOCUMENTATION), + Spdx2_RelationshipType.DYNAMIC_LINK: ( + False, + RelationshipType.DEPENDS_ON, + None, + SoftwareDependencyLinkType.DYNAMIC, + None, + ), + Spdx2_RelationshipType.EXAMPLE_OF: (True, RelationshipType.EXAMPLE), + Spdx2_RelationshipType.EXPANDED_FROM_ARCHIVE: (True, RelationshipType.EXPANDED_FROM_ARCHIVE), + Spdx2_RelationshipType.FILE_ADDED: (True, RelationshipType.FILE_ADDED), + Spdx2_RelationshipType.FILE_DELETED: (True, RelationshipType.FILE_DELETED), + Spdx2_RelationshipType.FILE_MODIFIED: (True, RelationshipType.FILE_MODIFIED), + Spdx2_RelationshipType.GENERATED_FROM: (True, RelationshipType.GENERATES, True), + Spdx2_RelationshipType.GENERATES: (True, RelationshipType.GENERATES), + Spdx2_RelationshipType.HAS_PREREQUISITE: ( + False, + RelationshipType.DEPENDS_ON, + None, + None, + DependencyConditionalityType.PREREQUISITE, + ), + Spdx2_RelationshipType.METAFILE_OF: (True, RelationshipType.METAFILE), + Spdx2_RelationshipType.OPTIONAL_COMPONENT_OF: None, # converted to depends on and purpose? not clear + Spdx2_RelationshipType.OPTIONAL_DEPENDENCY_OF: ( + False, + RelationshipType.DEPENDS_ON, + None, + None, + DependencyConditionalityType.OPTIONAL, + ), + Spdx2_RelationshipType.OTHER: (True, RelationshipType.OTHER), + Spdx2_RelationshipType.PACKAGE_OF: (False, RelationshipType.DEPENDS_ON), + Spdx2_RelationshipType.PATCH_APPLIED: (True, RelationshipType.PATCH, True), + Spdx2_RelationshipType.PATCH_FOR: (True, RelationshipType.PATCH), + Spdx2_RelationshipType.PREREQUISITE_FOR: ( + False, + RelationshipType.DEPENDS_ON, + None, + None, + DependencyConditionalityType.PREREQUISITE, + ), + Spdx2_RelationshipType.PROVIDED_DEPENDENCY_OF: ( + False, + RelationshipType.DEPENDS_ON, + LifecycleScopeType.BUILD, + None, + DependencyConditionalityType.PROVIDED, + ), + Spdx2_RelationshipType.RUNTIME_DEPENDENCY_OF: ( + False, + RelationshipType.DEPENDS_ON, + LifecycleScopeType.RUNTIME, + None, + None, + ), + Spdx2_RelationshipType.STATIC_LINK: ( + False, + RelationshipType.DEPENDS_ON, + None, + SoftwareDependencyLinkType.STATIC, + None, + ), + Spdx2_RelationshipType.TEST_CASE_OF: (True, RelationshipType.TEST_CASE), + Spdx2_RelationshipType.TEST_DEPENDENCY_OF: ( + False, + RelationshipType.DEPENDS_ON, + LifecycleScopeType.TEST, + None, + None, + ), + Spdx2_RelationshipType.TEST_OF: (True, RelationshipType.TEST), + Spdx2_RelationshipType.TEST_TOOL_OF: ( + False, + RelationshipType.DEPENDS_ON, + LifecycleScopeType.TEST, + SoftwareDependencyLinkType.TOOL, + None, + ), + Spdx2_RelationshipType.VARIANT_OF: (True, RelationshipType.VARIANT), + Spdx2_RelationshipType.REQUIREMENT_DESCRIPTION_FOR: (True, RelationshipType.REQUIREMENT_FOR), + Spdx2_RelationshipType.SPECIFICATION_FOR: (True, RelationshipType.SPECIFICATION_FOR), +} -def bump_relationship( - spdx2_relationship: Spdx2_Relationship, + +def bump_relationships( + spdx2_relationships: List[Spdx2_Relationship], payload: Payload, creation_information: CreationInformation, document_namespace: str, - counter: int, ): - relationship_type, swap_direction = bump_relationship_type(spdx2_relationship.relationship_type) + generated_relationships: Dict[Tuple[str, str], List[Relationship]] = {} + for counter, spdx2_relationship in enumerate(spdx2_relationships): + relationship = bump_relationship(spdx2_relationship, creation_information, document_namespace, counter) + if relationship: + generated_relationships.setdefault( + (relationship.from_element, relationship.relationship_type.name), [] + ).append(relationship) - spdx_id = "#".join([document_namespace, f"SPDXRef-Relationship-{counter}"]) + for key, relationships in generated_relationships.items(): + if len(relationships) > 1: + merge_relationships_and_add_to_payload(payload, relationships) + else: + payload.add_element(relationships[0]) - if isinstance( - spdx2_relationship.related_spdx_element_id, SpdxNoAssertion - ): # how to translate none/ no assertion to element? - completeness = RelationshipCompleteness.UNKNOWN - elif isinstance(spdx2_relationship.related_spdx_element_id, SpdxNone): - completeness = RelationshipCompleteness.KNOWN - else: - completeness = None - if swap_direction: - from_element = spdx2_relationship.related_spdx_element_id - to = [spdx2_relationship.spdx_element_id] - else: +def bump_relationship( + spdx2_relationship: Spdx2_Relationship, + creation_information: CreationInformation, + document_namespace: str, + counter: int, +) -> Optional[Union[Relationship, SoftwareDependencyRelationship]]: + swap_direction = False + completeness, to = determine_completeness(spdx2_relationship.related_spdx_element_id) + spdx_id = "#".join([document_namespace, f"SPDXRef-Relationship-{counter}"]) + parameters_for_bump = relationship_mapping[spdx2_relationship.relationship_type] + if parameters_for_bump is None: + print_missing_conversion(spdx2_relationship.relationship_type.name, 0) + return + base_relationship = parameters_for_bump[0] + relationship_type = parameters_for_bump[1] + if not base_relationship: + scope = parameters_for_bump[2] + software_linkage = parameters_for_bump[3] + conditionality = parameters_for_bump[4] from_element = spdx2_relationship.spdx_element_id - to = [spdx2_relationship.related_spdx_element_id] - payload.add_element( - Relationship( + return SoftwareDependencyRelationship( spdx_id, creation_information, from_element, @@ -47,28 +223,55 @@ def bump_relationship( relationship_type, comment=spdx2_relationship.comment, completeness=completeness, + scope=scope, + software_linkage=software_linkage, + conditionality=conditionality, ) + + if base_relationship and (len(parameters_for_bump) == 3): + swap_direction = parameters_for_bump[2] + if swap_direction: + if not to: + print_missing_conversion("Swapped Relationship to NoAssertion/ None", 0) + return + from_element = to[0] + to = [spdx2_relationship.spdx_element_id] + else: + from_element = spdx2_relationship.spdx_element_id + + return Relationship( + spdx_id, + creation_information, + from_element, + to, + relationship_type, + comment=spdx2_relationship.comment, + completeness=completeness, ) -def bump_relationship_type(spdx2_relationship_type: Spdx2_RelationshipType) -> Optional[Tuple[RelationshipType, bool]]: - if spdx2_relationship_type == Spdx2_RelationshipType.DESCRIBED_BY: - return RelationshipType.DESCRIBES, True - if spdx2_relationship_type == Spdx2_RelationshipType.CONTAINED_BY: - return RelationshipType.CONTAINS, True - if spdx2_relationship_type == Spdx2_RelationshipType.DEPENDENCY_OF: - return RelationshipType.DEPENDS_ON, True - if spdx2_relationship_type == Spdx2_RelationshipType.GENERATED_FROM: - return RelationshipType.GENERATES, True - if spdx2_relationship_type == Spdx2_RelationshipType.HAS_PREREQUISITE: - return RelationshipType.PREREQUISITE, True - if spdx2_relationship_type.name.endswith("_OF"): - relationship_type = spdx2_relationship_type.name.replace("_OF", "") - return RelationshipType[relationship_type], False - if spdx2_relationship_type.name.endswith("_FOR"): - relationship_type = spdx2_relationship_type.name.replace("_FOR", "") - return RelationshipType[relationship_type], False - return RelationshipType[spdx2_relationship_type.name], False - # if spdx2_relationship_type == Spdx2_RelationshipType.PATCH_APPLIED: - # print_missing_conversion("RelationshipType.PATCH_APPLIED", 0) - # return None +def determine_completeness( + related_spdx_element_id: Union[str, SpdxNone, SpdxNoAssertion] +) -> Tuple[Optional[RelationshipCompleteness], List[str]]: + if isinstance(related_spdx_element_id, SpdxNoAssertion): + completeness = RelationshipCompleteness.NOASSERTION + to = [] + elif isinstance(related_spdx_element_id, SpdxNone): + completeness = RelationshipCompleteness.COMPLETE + to = [] + else: + completeness = None + to = [related_spdx_element_id] + return completeness, to + + +def merge_relationships_and_add_to_payload(payload: Payload, relationships: List[Relationship]): + merged_relationship = relationships[0] + for relationship in relationships[1:]: + merged_relationship.to += relationship.to + if merged_relationship.comment and relationship.comment: + merged_relationship.comment += ", " + relationship.comment + if not merged_relationship.comment and relationship.comment: + merged_relationship.comment = relationship.comment + + payload.add_element(merged_relationship) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py index b12204c5e..7e51a0473 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py @@ -5,7 +5,7 @@ from spdx_tools.spdx3.bump_from_spdx2.creation_information import bump_creation_information from spdx_tools.spdx3.bump_from_spdx2.file import bump_file from spdx_tools.spdx3.bump_from_spdx2.package import bump_package -from spdx_tools.spdx3.bump_from_spdx2.relationship import bump_relationship +from spdx_tools.spdx3.bump_from_spdx2.relationship import bump_relationships from spdx_tools.spdx3.bump_from_spdx2.snippet import bump_snippet from spdx_tools.spdx3.model import CreationInformation, SpdxDocument from spdx_tools.spdx3.payload import Payload @@ -33,8 +33,7 @@ def bump_spdx_document(document: Spdx2_Document) -> Payload: for spdx2_snippet in document.snippets: bump_snippet(spdx2_snippet, payload, creation_info, document_namespace) - for counter, spdx2_relationship in enumerate(document.relationships): - bump_relationship(spdx2_relationship, payload, creation_info, document_namespace, counter) + bump_relationships(document.relationships, payload, creation_info, document_namespace) for counter, spdx2_annotation in enumerate(document.annotations): bump_annotation(spdx2_annotation, payload, creation_info, document_namespace, counter) diff --git a/src/spdx_tools/spdx3/writer/console/payload_writer.py b/src/spdx_tools/spdx3/writer/console/payload_writer.py index 49e4a4e62..36f47093e 100644 --- a/src/spdx_tools/spdx3/writer/console/payload_writer.py +++ b/src/spdx_tools/spdx3/writer/console/payload_writer.py @@ -17,7 +17,7 @@ from spdx_tools.spdx3.model.ai import AIPackage from spdx_tools.spdx3.model.build import Build from spdx_tools.spdx3.model.dataset import Dataset -from spdx_tools.spdx3.model.software import File, Package, Sbom, Snippet +from spdx_tools.spdx3.model.software import File, Package, Sbom, Snippet, SoftwareDependencyRelationship from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx3.writer.console.agent_writer import write_agent from spdx_tools.spdx3.writer.console.ai.ai_package_writer import write_ai_package @@ -37,6 +37,7 @@ MAP_CLASS_TO_WRITE_METHOD = { Annotation: write_annotation, Relationship: write_relationship, + SoftwareDependencyRelationship: write_relationship, # needs to be adapted as soon as base PR is changed Bundle: write_bundle, SpdxDocument: write_spdx_document, Bom: write_bom, diff --git a/tests/spdx3/bump/test_relationship_bump.py b/tests/spdx3/bump/test_relationship_bump.py new file mode 100644 index 000000000..e2713b6f5 --- /dev/null +++ b/tests/spdx3/bump/test_relationship_bump.py @@ -0,0 +1,97 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from unittest import mock + +from spdx_tools.spdx3.bump_from_spdx2.relationship import bump_relationship, bump_relationships +from spdx_tools.spdx3.model import Relationship, RelationshipCompleteness, RelationshipType +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import RelationshipType as Spdx2_RelationshipType +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from tests.spdx.fixtures import relationship_fixture + + +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_relationship_bump(creation_info): + spdx2_relationship = relationship_fixture() + document_namespace = "https://doc.namespace" + relationship = bump_relationship(spdx2_relationship, creation_info, document_namespace, 1) + + assert relationship == Relationship( + f"{document_namespace}#SPDXRef-Relationship-1", + creation_info, + spdx2_relationship.spdx_element_id, + [spdx2_relationship.related_spdx_element_id], + RelationshipType.DESCRIBES, + comment=spdx2_relationship.comment, + ) + + +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_relationships_bump(creation_info): + relationships = [relationship_fixture(), relationship_fixture(related_spdx_element_id="SPDXRef-Package")] + payload = Payload() + document_namespace = "https://doc.namespace" + bump_relationships(relationships, payload, creation_info, document_namespace) + + assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-0") == Relationship( + f"{document_namespace}#SPDXRef-Relationship-0", + creation_info, + relationships[0].spdx_element_id, + [relationships[0].related_spdx_element_id, relationships[1].related_spdx_element_id], + RelationshipType.DESCRIBES, + comment=relationships[0].comment + ", " + relationships[1].comment, + ) + + +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_relationships_bump_with_setting_completeness(creation_info): + relationships = [ + relationship_fixture(related_spdx_element_id=SpdxNoAssertion()), + relationship_fixture(related_spdx_element_id="SPDXRef-Package"), + relationship_fixture( + relationship_type=Spdx2_RelationshipType.SPECIFICATION_FOR, + related_spdx_element_id=SpdxNone(), + comment=None, + ), + ] + payload = Payload() + document_namespace = "https://doc.namespace" + bump_relationships(relationships, payload, creation_info, document_namespace) + + assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-0") == Relationship( + f"{document_namespace}#SPDXRef-Relationship-0", + creation_info, + relationships[0].spdx_element_id, + [relationships[1].related_spdx_element_id], + RelationshipType.DESCRIBES, + comment=relationships[0].comment + ", " + relationships[1].comment, + completeness=RelationshipCompleteness.NOASSERTION, + ) + assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-2") == Relationship( + f"{document_namespace}#SPDXRef-Relationship-2", + creation_info, + relationships[2].spdx_element_id, + [], + RelationshipType.SPECIFICATION_FOR, + completeness=RelationshipCompleteness.COMPLETE, + ) + + +@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +def test_undefined_relationship_bump(creation_info, capsys): + relationships = [ + relationship_fixture( + related_spdx_element_id=SpdxNoAssertion(), relationship_type=Spdx2_RelationshipType.CONTAINED_BY + ), + relationship_fixture(relationship_type=Spdx2_RelationshipType.OPTIONAL_COMPONENT_OF), + ] + payload = Payload() + document_namespace = "https://doc.namespace" + bump_relationships(relationships, payload, creation_info, document_namespace) + + captured = capsys.readouterr() + assert ( + captured.err == "Swapped Relationship to NoAssertion/ None not converted: missing conversion rule \n" + "OPTIONAL_COMPONENT_OF not converted: missing conversion rule \n" + ) From 0f314d0ce1fc95d4543e6f4c1f772a104955926c Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 26 Apr 2023 13:20:05 +0200 Subject: [PATCH 203/354] [issue_602] implement review comments Signed-off-by: Meret Behrens --- .../spdx3/bump_from_spdx2/relationship.py | 24 +++++++++---------- .../spdx3/writer/console/payload_writer.py | 5 +++- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py index a60ea16e3..6c1f47168 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -187,9 +187,10 @@ def bump_relationships( (relationship.from_element, relationship.relationship_type.name), [] ).append(relationship) - for key, relationships in generated_relationships.items(): + for relationships in generated_relationships.values(): if len(relationships) > 1: - merge_relationships_and_add_to_payload(payload, relationships) + merged_relationship = merge_relationships_and_add_to_payload(relationships) + payload.add_element(merged_relationship) else: payload.add_element(relationships[0]) @@ -201,7 +202,7 @@ def bump_relationship( counter: int, ) -> Optional[Union[Relationship, SoftwareDependencyRelationship]]: swap_direction = False - completeness, to = determine_completeness(spdx2_relationship.related_spdx_element_id) + completeness, to = determine_completeness_and_to(spdx2_relationship.related_spdx_element_id) spdx_id = "#".join([document_namespace, f"SPDXRef-Relationship-{counter}"]) parameters_for_bump = relationship_mapping[spdx2_relationship.relationship_type] if parameters_for_bump is None: @@ -210,9 +211,6 @@ def bump_relationship( base_relationship = parameters_for_bump[0] relationship_type = parameters_for_bump[1] if not base_relationship: - scope = parameters_for_bump[2] - software_linkage = parameters_for_bump[3] - conditionality = parameters_for_bump[4] from_element = spdx2_relationship.spdx_element_id return SoftwareDependencyRelationship( @@ -223,12 +221,12 @@ def bump_relationship( relationship_type, comment=spdx2_relationship.comment, completeness=completeness, - scope=scope, - software_linkage=software_linkage, - conditionality=conditionality, + scope=(parameters_for_bump[2]), + software_linkage=(parameters_for_bump[3]), + conditionality=(parameters_for_bump[4]), ) - if base_relationship and (len(parameters_for_bump) == 3): + if len(parameters_for_bump) == 3: swap_direction = parameters_for_bump[2] if swap_direction: if not to: @@ -250,7 +248,7 @@ def bump_relationship( ) -def determine_completeness( +def determine_completeness_and_to( related_spdx_element_id: Union[str, SpdxNone, SpdxNoAssertion] ) -> Tuple[Optional[RelationshipCompleteness], List[str]]: if isinstance(related_spdx_element_id, SpdxNoAssertion): @@ -265,7 +263,7 @@ def determine_completeness( return completeness, to -def merge_relationships_and_add_to_payload(payload: Payload, relationships: List[Relationship]): +def merge_relationships_and_add_to_payload(relationships: List[Relationship]) -> Relationship: merged_relationship = relationships[0] for relationship in relationships[1:]: merged_relationship.to += relationship.to @@ -274,4 +272,4 @@ def merge_relationships_and_add_to_payload(payload: Payload, relationships: List if not merged_relationship.comment and relationship.comment: merged_relationship.comment = relationship.comment - payload.add_element(merged_relationship) + return merged_relationship diff --git a/src/spdx_tools/spdx3/writer/console/payload_writer.py b/src/spdx_tools/spdx3/writer/console/payload_writer.py index 36f47093e..95ea3f21a 100644 --- a/src/spdx_tools/spdx3/writer/console/payload_writer.py +++ b/src/spdx_tools/spdx3/writer/console/payload_writer.py @@ -31,13 +31,16 @@ from spdx_tools.spdx3.writer.console.software.package_writer import write_package from spdx_tools.spdx3.writer.console.software.sbom_writer import write_sbom from spdx_tools.spdx3.writer.console.software.snippet_writer import write_snippet +from spdx_tools.spdx3.writer.console.software.software_dependency_relationship_writer import ( + write_software_dependency_relationship, +) from spdx_tools.spdx3.writer.console.spdx_document_writer import write_spdx_document from spdx_tools.spdx3.writer.console.tool_writer import write_tool MAP_CLASS_TO_WRITE_METHOD = { Annotation: write_annotation, Relationship: write_relationship, - SoftwareDependencyRelationship: write_relationship, # needs to be adapted as soon as base PR is changed + SoftwareDependencyRelationship: write_software_dependency_relationship, Bundle: write_bundle, SpdxDocument: write_spdx_document, Bom: write_bom, From d5db1626b82d1536ab919a50bea87a1d2b2ad3d7 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 26 Apr 2023 15:16:09 +0200 Subject: [PATCH 204/354] [issue_602] refactor relationship mapping Signed-off-by: Meret Behrens --- .../spdx3/bump_from_spdx2/relationship.py | 237 +++++++++--------- tests/spdx3/bump/test_relationship_bump.py | 24 +- 2 files changed, 132 insertions(+), 129 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py index 6c1f47168..79cee5e0a 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -1,6 +1,8 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +import logging +import sys from typing import Dict, List, Optional, Tuple, Union from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion @@ -27,149 +29,128 @@ relationship_mapping: Dict[ Spdx2_RelationshipType, Tuple[ - bool, + Union[Relationship, SoftwareDependencyRelationship], RelationshipType, - Union[bool, LifecycleScopeType, None], - Optional[SoftwareDependencyLinkType], - Optional[DependencyConditionalityType], + Dict[str, Union[bool, LifecycleScopeType, SoftwareDependencyLinkType, DependencyConditionalityType]], ], ] = { - Spdx2_RelationshipType.AMENDS: (True, RelationshipType.AMENDS), - Spdx2_RelationshipType.ANCESTOR_OF: (True, RelationshipType.ANCESTOR), + Spdx2_RelationshipType.AMENDS: (Relationship, RelationshipType.AMENDS, {}), + Spdx2_RelationshipType.ANCESTOR_OF: (Relationship, RelationshipType.ANCESTOR, {}), Spdx2_RelationshipType.BUILD_DEPENDENCY_OF: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - LifecycleScopeType.BUILD, - SoftwareDependencyLinkType.TOOL, - None, + { + "scope": LifecycleScopeType.BUILD, + "linkage": SoftwareDependencyLinkType.TOOL, + }, ), Spdx2_RelationshipType.BUILD_TOOL_OF: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - LifecycleScopeType.BUILD, - SoftwareDependencyLinkType.TOOL, - None, + {"scope": LifecycleScopeType.BUILD, "linkage": SoftwareDependencyLinkType.TOOL}, ), - Spdx2_RelationshipType.CONTAINED_BY: (True, RelationshipType.CONTAINS, True), + Spdx2_RelationshipType.CONTAINED_BY: (Relationship, RelationshipType.CONTAINS, {"swap": True}), Spdx2_RelationshipType.CONTAINS: ( - True, + Relationship, RelationshipType.CONTAINS, + {}, ), # might be deleted in favor of depends on - Spdx2_RelationshipType.COPY_OF: (True, RelationshipType.COPY), - Spdx2_RelationshipType.DATA_FILE_OF: None, # not defined, probably input/ output + Spdx2_RelationshipType.COPY_OF: (Relationship, RelationshipType.COPY, {}), + Spdx2_RelationshipType.DATA_FILE_OF: (None, None, {}), # not defined, probably input/ output Spdx2_RelationshipType.DEPENDENCY_MANIFEST_OF: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - None, - None, - None, + {}, ), # "expect purpose has been set to manifest" - Spdx2_RelationshipType.DEPENDENCY_OF: (False, RelationshipType.DEPENDS_ON, True), - Spdx2_RelationshipType.DEPENDS_ON: ( - False, + Spdx2_RelationshipType.DEPENDENCY_OF: ( + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, + {"swap": True}, ), - Spdx2_RelationshipType.DESCENDANT_OF: (True, RelationshipType.ANCESTOR, True), - Spdx2_RelationshipType.DESCRIBED_BY: (True, RelationshipType.DESCRIBES, True), - Spdx2_RelationshipType.DESCRIBES: (True, RelationshipType.DESCRIBES), # might be deleted in favor of root + Spdx2_RelationshipType.DEPENDS_ON: (SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, {}), + Spdx2_RelationshipType.DESCENDANT_OF: (Relationship, RelationshipType.ANCESTOR, {"swap": True}), + Spdx2_RelationshipType.DESCRIBED_BY: (Relationship, RelationshipType.DESCRIBES, {"swap": True}), + Spdx2_RelationshipType.DESCRIBES: ( + Relationship, + RelationshipType.DESCRIBES, + {}, + ), # might be deleted in favor of root # property Spdx2_RelationshipType.DEV_DEPENDENCY_OF: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - LifecycleScopeType.DEVELOPMENT, - None, - None, + {"scope": LifecycleScopeType.DEVELOPMENT}, ), Spdx2_RelationshipType.DEV_TOOL_OF: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - LifecycleScopeType.DEVELOPMENT, - SoftwareDependencyLinkType.TOOL, - None, + {"scope": LifecycleScopeType.DEVELOPMENT, "linkage": SoftwareDependencyLinkType.TOOL}, ), - Spdx2_RelationshipType.DISTRIBUTION_ARTIFACT: None, # not defined yet, purpose? - Spdx2_RelationshipType.DOCUMENTATION_OF: (True, RelationshipType.DOCUMENTATION), + Spdx2_RelationshipType.DISTRIBUTION_ARTIFACT: (None, None, {}), # not defined yet, purpose? + Spdx2_RelationshipType.DOCUMENTATION_OF: (Relationship, RelationshipType.DOCUMENTATION, {}), Spdx2_RelationshipType.DYNAMIC_LINK: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - None, - SoftwareDependencyLinkType.DYNAMIC, - None, + {"linkage": SoftwareDependencyLinkType.DYNAMIC}, ), - Spdx2_RelationshipType.EXAMPLE_OF: (True, RelationshipType.EXAMPLE), - Spdx2_RelationshipType.EXPANDED_FROM_ARCHIVE: (True, RelationshipType.EXPANDED_FROM_ARCHIVE), - Spdx2_RelationshipType.FILE_ADDED: (True, RelationshipType.FILE_ADDED), - Spdx2_RelationshipType.FILE_DELETED: (True, RelationshipType.FILE_DELETED), - Spdx2_RelationshipType.FILE_MODIFIED: (True, RelationshipType.FILE_MODIFIED), - Spdx2_RelationshipType.GENERATED_FROM: (True, RelationshipType.GENERATES, True), - Spdx2_RelationshipType.GENERATES: (True, RelationshipType.GENERATES), + Spdx2_RelationshipType.EXAMPLE_OF: (Relationship, RelationshipType.EXAMPLE, {}), + Spdx2_RelationshipType.EXPANDED_FROM_ARCHIVE: (Relationship, RelationshipType.EXPANDED_FROM_ARCHIVE, {}), + Spdx2_RelationshipType.FILE_ADDED: (Relationship, RelationshipType.FILE_ADDED, {}), + Spdx2_RelationshipType.FILE_DELETED: (Relationship, RelationshipType.FILE_DELETED, {}), + Spdx2_RelationshipType.FILE_MODIFIED: (Relationship, RelationshipType.FILE_MODIFIED, {}), + Spdx2_RelationshipType.GENERATED_FROM: (Relationship, RelationshipType.GENERATES, {"swap": True}), + Spdx2_RelationshipType.GENERATES: (Relationship, RelationshipType.GENERATES, {}), Spdx2_RelationshipType.HAS_PREREQUISITE: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - None, - None, - DependencyConditionalityType.PREREQUISITE, + {"conditionality": DependencyConditionalityType.PREREQUISITE}, ), - Spdx2_RelationshipType.METAFILE_OF: (True, RelationshipType.METAFILE), - Spdx2_RelationshipType.OPTIONAL_COMPONENT_OF: None, # converted to depends on and purpose? not clear + Spdx2_RelationshipType.METAFILE_OF: (Relationship, RelationshipType.METAFILE, {}), + Spdx2_RelationshipType.OPTIONAL_COMPONENT_OF: (None, None, {}), # converted to depends on and purpose? not clear Spdx2_RelationshipType.OPTIONAL_DEPENDENCY_OF: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - None, - None, - DependencyConditionalityType.OPTIONAL, + {"conditionality": DependencyConditionalityType.OPTIONAL}, ), - Spdx2_RelationshipType.OTHER: (True, RelationshipType.OTHER), - Spdx2_RelationshipType.PACKAGE_OF: (False, RelationshipType.DEPENDS_ON), - Spdx2_RelationshipType.PATCH_APPLIED: (True, RelationshipType.PATCH, True), - Spdx2_RelationshipType.PATCH_FOR: (True, RelationshipType.PATCH), + Spdx2_RelationshipType.OTHER: (Relationship, RelationshipType.OTHER, {}), + Spdx2_RelationshipType.PACKAGE_OF: (SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, {}), + Spdx2_RelationshipType.PATCH_APPLIED: (Relationship, RelationshipType.PATCH, {"swap": True}), + Spdx2_RelationshipType.PATCH_FOR: (Relationship, RelationshipType.PATCH, {}), Spdx2_RelationshipType.PREREQUISITE_FOR: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - None, - None, - DependencyConditionalityType.PREREQUISITE, + {"conditionality": DependencyConditionalityType.PREREQUISITE}, ), Spdx2_RelationshipType.PROVIDED_DEPENDENCY_OF: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - LifecycleScopeType.BUILD, - None, - DependencyConditionalityType.PROVIDED, + {"scope": LifecycleScopeType.BUILD, "conditionality": DependencyConditionalityType.PROVIDED}, ), Spdx2_RelationshipType.RUNTIME_DEPENDENCY_OF: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - LifecycleScopeType.RUNTIME, - None, - None, + {"scope": LifecycleScopeType.RUNTIME}, ), Spdx2_RelationshipType.STATIC_LINK: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - None, - SoftwareDependencyLinkType.STATIC, - None, + {"linkage": SoftwareDependencyLinkType.STATIC}, ), - Spdx2_RelationshipType.TEST_CASE_OF: (True, RelationshipType.TEST_CASE), + Spdx2_RelationshipType.TEST_CASE_OF: (Relationship, RelationshipType.TEST_CASE, {}), Spdx2_RelationshipType.TEST_DEPENDENCY_OF: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - LifecycleScopeType.TEST, - None, - None, + {"scope": LifecycleScopeType.TEST}, ), - Spdx2_RelationshipType.TEST_OF: (True, RelationshipType.TEST), + Spdx2_RelationshipType.TEST_OF: (Relationship, RelationshipType.TEST, {}), Spdx2_RelationshipType.TEST_TOOL_OF: ( - False, + SoftwareDependencyRelationship, RelationshipType.DEPENDS_ON, - LifecycleScopeType.TEST, - SoftwareDependencyLinkType.TOOL, - None, + {"scope": LifecycleScopeType.TEST, "linkage": SoftwareDependencyLinkType.TOOL}, ), - Spdx2_RelationshipType.VARIANT_OF: (True, RelationshipType.VARIANT), - Spdx2_RelationshipType.REQUIREMENT_DESCRIPTION_FOR: (True, RelationshipType.REQUIREMENT_FOR), - Spdx2_RelationshipType.SPECIFICATION_FOR: (True, RelationshipType.SPECIFICATION_FOR), + Spdx2_RelationshipType.VARIANT_OF: (Relationship, RelationshipType.VARIANT, {}), + Spdx2_RelationshipType.REQUIREMENT_DESCRIPTION_FOR: (Relationship, RelationshipType.REQUIREMENT_FOR, {}), + Spdx2_RelationshipType.SPECIFICATION_FOR: (Relationship, RelationshipType.SPECIFICATION_FOR, {}), } @@ -189,8 +170,7 @@ def bump_relationships( for relationships in generated_relationships.values(): if len(relationships) > 1: - merged_relationship = merge_relationships_and_add_to_payload(relationships) - payload.add_element(merged_relationship) + _merge_relationships_and_add_to_payload(relationships, payload) else: payload.add_element(relationships[0]) @@ -201,16 +181,25 @@ def bump_relationship( document_namespace: str, counter: int, ) -> Optional[Union[Relationship, SoftwareDependencyRelationship]]: - swap_direction = False completeness, to = determine_completeness_and_to(spdx2_relationship.related_spdx_element_id) spdx_id = "#".join([document_namespace, f"SPDXRef-Relationship-{counter}"]) - parameters_for_bump = relationship_mapping[spdx2_relationship.relationship_type] - if parameters_for_bump is None: + relationship_class, relationship_type, parameters = relationship_mapping[spdx2_relationship.relationship_type] + if relationship_class is None: print_missing_conversion(spdx2_relationship.relationship_type.name, 0) return - base_relationship = parameters_for_bump[0] - relationship_type = parameters_for_bump[1] - if not base_relationship: + + swap_direction = parameters.get("swap", False) + + if swap_direction: + if not to: + print_missing_conversion("Swapped Relationship to NoAssertion/None", 0) + return + from_element = to[0] + to = [spdx2_relationship.spdx_element_id] + else: + from_element = spdx2_relationship.spdx_element_id + + if relationship_class == SoftwareDependencyRelationship: from_element = spdx2_relationship.spdx_element_id return SoftwareDependencyRelationship( @@ -221,22 +210,11 @@ def bump_relationship( relationship_type, comment=spdx2_relationship.comment, completeness=completeness, - scope=(parameters_for_bump[2]), - software_linkage=(parameters_for_bump[3]), - conditionality=(parameters_for_bump[4]), + scope=parameters.get("scope"), + software_linkage=parameters.get("linkage"), + conditionality=parameters.get("conditionality"), ) - if len(parameters_for_bump) == 3: - swap_direction = parameters_for_bump[2] - if swap_direction: - if not to: - print_missing_conversion("Swapped Relationship to NoAssertion/ None", 0) - return - from_element = to[0] - to = [spdx2_relationship.spdx_element_id] - else: - from_element = spdx2_relationship.spdx_element_id - return Relationship( spdx_id, creation_information, @@ -263,13 +241,28 @@ def determine_completeness_and_to( return completeness, to -def merge_relationships_and_add_to_payload(relationships: List[Relationship]) -> Relationship: +def _merge_relationships_and_add_to_payload(relationships: List[Relationship], payload: Payload): + to = [] + completeness = None + spdx_id = None merged_relationship = relationships[0] - for relationship in relationships[1:]: - merged_relationship.to += relationship.to - if merged_relationship.comment and relationship.comment: - merged_relationship.comment += ", " + relationship.comment - if not merged_relationship.comment and relationship.comment: - merged_relationship.comment = relationship.comment + for merged_relationship in relationships: + if merged_relationship.comment: + payload.add_element(merged_relationship) + continue + if merged_relationship.completeness: + if completeness and completeness != merged_relationship.completeness: + logging.warning( + f"Contradicting information about completeness of relationship: {merged_relationship}", sys.stderr + ) + else: + completeness = merged_relationship.completeness - return merged_relationship + to += merged_relationship.to + spdx_id = merged_relationship.spdx_id + if to: + merged_relationship.spdx_id = spdx_id + merged_relationship.to = to + merged_relationship.completeness = completeness + merged_relationship.comment = None + payload.add_element(merged_relationship) diff --git a/tests/spdx3/bump/test_relationship_bump.py b/tests/spdx3/bump/test_relationship_bump.py index e2713b6f5..79143497e 100644 --- a/tests/spdx3/bump/test_relationship_bump.py +++ b/tests/spdx3/bump/test_relationship_bump.py @@ -29,18 +29,20 @@ def test_relationship_bump(creation_info): @mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_relationships_bump(creation_info): - relationships = [relationship_fixture(), relationship_fixture(related_spdx_element_id="SPDXRef-Package")] + relationships = [ + relationship_fixture(comment=None), + relationship_fixture(related_spdx_element_id="SPDXRef-Package", comment=None), + ] payload = Payload() document_namespace = "https://doc.namespace" bump_relationships(relationships, payload, creation_info, document_namespace) - assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-0") == Relationship( - f"{document_namespace}#SPDXRef-Relationship-0", + assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-1") == Relationship( + f"{document_namespace}#SPDXRef-Relationship-1", creation_info, relationships[0].spdx_element_id, [relationships[0].related_spdx_element_id, relationships[1].related_spdx_element_id], RelationshipType.DESCRIBES, - comment=relationships[0].comment + ", " + relationships[1].comment, ) @@ -63,11 +65,19 @@ def test_relationships_bump_with_setting_completeness(creation_info): f"{document_namespace}#SPDXRef-Relationship-0", creation_info, relationships[0].spdx_element_id, - [relationships[1].related_spdx_element_id], + [], RelationshipType.DESCRIBES, - comment=relationships[0].comment + ", " + relationships[1].comment, + comment=relationships[0].comment, completeness=RelationshipCompleteness.NOASSERTION, ) + assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-1") == Relationship( + f"{document_namespace}#SPDXRef-Relationship-1", + creation_info, + relationships[1].spdx_element_id, + [relationships[1].related_spdx_element_id], + RelationshipType.DESCRIBES, + comment=relationships[1].comment, + ) assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-2") == Relationship( f"{document_namespace}#SPDXRef-Relationship-2", creation_info, @@ -92,6 +102,6 @@ def test_undefined_relationship_bump(creation_info, capsys): captured = capsys.readouterr() assert ( - captured.err == "Swapped Relationship to NoAssertion/ None not converted: missing conversion rule \n" + captured.err == "Swapped Relationship to NoAssertion/None not converted: missing conversion rule \n" "OPTIONAL_COMPONENT_OF not converted: missing conversion rule \n" ) From 16a8b6340409e41dbee50485d0132444ef3a4b9c Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 9 May 2023 13:15:38 +0200 Subject: [PATCH 205/354] add conversion for license expressions Signed-off-by: Meret Behrens --- .../bump_from_spdx2/license_expression.py | 68 +++++++++++++++ .../bump/test_license_expression_bump.py | 85 +++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py create mode 100644 tests/spdx3/bump/test_license_expression_bump.py diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py b/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py new file mode 100644 index 000000000..75406af2a --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py @@ -0,0 +1,68 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import Union + +from license_expression import ( + AND, + OR, + LicenseExpression, + LicenseSymbol, + LicenseWithExceptionSymbol, + get_spdx_licensing, +) + +from spdx_tools.spdx3.model.licensing import ( + AnyLicenseInfo, + ConjunctiveLicenseSet, + CustomLicense, + CustomLicenseAddition, + DisjunctiveLicenseSet, + License, + LicenseAddition, + LicenseField, + ListedLicense, + ListedLicenseException, + NoAssertionLicense, + NoneLicense, + WithAdditionOperator, +) +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone + + +def bump_license_expression_or_none_or_no_assertion( + element: Union[LicenseExpression, SpdxNoAssertion, SpdxNone] +) -> LicenseField: + if isinstance(element, SpdxNone): + return NoneLicense() + elif isinstance(element, SpdxNoAssertion): + return NoAssertionLicense() + else: + return bump_license_expression(element) + + +def bump_license_expression(license_expression: LicenseExpression) -> AnyLicenseInfo: + if isinstance(license_expression, AND): + return ConjunctiveLicenseSet(member=[bump_license_expression(element) for element in license_expression.args]) + if isinstance(license_expression, OR): + return DisjunctiveLicenseSet(member=[bump_license_expression(element) for element in license_expression.args]) + if isinstance(license_expression, LicenseWithExceptionSymbol): + subject_license = bump_license_expression(license_expression.license_symbol) + if not isinstance(subject_license, License): + raise ValueError("Subject of LicenseException couldn't be converted to License.") + return WithAdditionOperator( + subject_license=subject_license, + subject_addition=bump_license_exception(license_expression.exception_symbol), + ) + if isinstance(license_expression, LicenseSymbol): + if not get_spdx_licensing().validate(license_expression).invalid_symbols: + return ListedLicense(license_expression.key, license_expression.obj, "") + else: + return CustomLicense(license_expression.key, "", "") + + +def bump_license_exception(license_exception: LicenseSymbol) -> LicenseAddition: + if not get_spdx_licensing().validate(license_exception).invalid_symbols: + return ListedLicenseException(license_exception.key, "", "") + else: + return CustomLicenseAddition(license_exception.key, "", "") diff --git a/tests/spdx3/bump/test_license_expression_bump.py b/tests/spdx3/bump/test_license_expression_bump.py new file mode 100644 index 000000000..a775279f8 --- /dev/null +++ b/tests/spdx3/bump/test_license_expression_bump.py @@ -0,0 +1,85 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest +from license_expression import LicenseExpression, get_spdx_licensing + +from spdx_tools.spdx3.bump_from_spdx2.license_expression import ( + bump_license_expression, + bump_license_expression_or_none_or_no_assertion, +) +from spdx_tools.spdx3.model.licensing import ( + ConjunctiveLicenseSet, + CustomLicense, + CustomLicenseAddition, + DisjunctiveLicenseSet, + ListedLicense, + ListedLicenseException, + NoAssertionLicense, + NoneLicense, + WithAdditionOperator, +) +from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone + + +@pytest.mark.parametrize( + "element, expected_class", + [ + (SpdxNoAssertion(), NoAssertionLicense), + (SpdxNone(), NoneLicense), + (get_spdx_licensing().parse("MIT"), ListedLicense), + ], +) +def test_license_expression_or_none_or_no_assertion(element, expected_class): + license_info = bump_license_expression_or_none_or_no_assertion(element) + + assert isinstance(license_info, expected_class) + + +@pytest.mark.parametrize( + "license_expression, expected_element", + [ + (get_spdx_licensing().parse("MIT"), ListedLicense("MIT", "MIT", "")), + (get_spdx_licensing().parse("LGPL-2.0"), ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "")), + (get_spdx_licensing().parse("LicenseRef-1"), CustomLicense("LicenseRef-1", "", "")), + ( + get_spdx_licensing().parse("MIT AND LGPL-2.0"), + ConjunctiveLicenseSet( + [ListedLicense("MIT", "MIT", ""), ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "")] + ), + ), + ( + get_spdx_licensing().parse("LicenseRef-1 OR LGPL-2.0"), + DisjunctiveLicenseSet( + [CustomLicense("LicenseRef-1", "", ""), ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "")] + ), + ), + ( + get_spdx_licensing().parse("LGPL-2.0 WITH 389-exception"), + WithAdditionOperator( + ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", ""), ListedLicenseException("389-exception", "", "") + ), + ), + ( + get_spdx_licensing().parse("LicenseRef-1 WITH custom-exception"), + WithAdditionOperator( + CustomLicense("LicenseRef-1", "", ""), CustomLicenseAddition("custom-exception", "", "") + ), + ), + ( + get_spdx_licensing().parse("MIT AND LicenseRef-1 WITH custom-exception"), + ConjunctiveLicenseSet( + [ + ListedLicense("MIT", "MIT", ""), + WithAdditionOperator( + CustomLicense("LicenseRef-1", "", ""), CustomLicenseAddition("custom-exception", "", "") + ), + ] + ), + ), + ], +) +def test_license_expression_bump(license_expression: LicenseExpression, expected_element): + license_info = bump_license_expression(license_expression) + + assert license_info == expected_element From f90e6a8f81c2d458d722d983b4c18f7f436146b6 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 9 May 2023 14:06:15 +0200 Subject: [PATCH 206/354] add conversion for license expressions to package, file and snippet Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/bump_from_spdx2/file.py | 25 +++++++--- .../bump_from_spdx2/license_expression.py | 48 +++++++++++++++---- .../spdx3/bump_from_spdx2/package.py | 29 +++++++++-- .../spdx3/bump_from_spdx2/snippet.py | 26 ++++++++-- .../spdx3/bump_from_spdx2/spdx_document.py | 6 +-- tests/spdx3/bump/test_file_bump.py | 8 +++- .../bump/test_license_expression_bump.py | 41 ++++++++++++---- tests/spdx3/bump/test_package_bump.py | 17 +++++-- tests/spdx3/bump/test_snippet_bump.py | 8 +++- 9 files changed, 163 insertions(+), 45 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/file.py b/src/spdx_tools/spdx3/bump_from_spdx2/file.py index 63ea26cd5..88a0d7f75 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/file.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/file.py @@ -2,15 +2,21 @@ # # SPDX-License-Identifier: Apache-2.0 from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import CreationInformation from spdx_tools.spdx3.model.software import File from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import SpdxNoAssertion from spdx_tools.spdx.model.file import File as Spdx2_File def bump_file( - spdx2_file: Spdx2_File, payload: Payload, creation_information: CreationInformation, document_namespace: str + spdx2_file: Spdx2_File, + payload: Payload, + creation_information: CreationInformation, + document_namespace: str, + extracted_licensing_info, ): spdx_id = "#".join([document_namespace, spdx2_file.spdx_id]) integrity_methods = [bump_checksum(checksum) for checksum in spdx2_file.checksums] @@ -19,16 +25,20 @@ def bump_file( print_missing_conversion( "file.file_type", 0, "different cardinalities, " "https://github.com/spdx/spdx-3-model/issues/82" ) + license_concluded = bump_license_expression_or_none_or_no_assertion( + spdx2_file.license_concluded, extracted_licensing_info + ) + copyright_text = None + if isinstance(spdx2_file.copyright_text, str): + copyright_text = spdx2_file.copyright_text + elif isinstance(spdx2_file.copyright_text, SpdxNoAssertion): + print_missing_conversion("package2.copyright_text", 0) print_missing_conversion( - "file.concluded_license, file.license_info_in_file, file.license_comment, file.copyright_text", + "file.notice, file.contributors, file.license_info_in_file, file.license_comment", 0, "missing definition for license profile", ) - print_missing_conversion( - "file.notice, file.contributors, file.attribution_texts", 0, "missing definition for license profile" - ) - payload.add_element( File( spdx_id, @@ -36,5 +46,8 @@ def bump_file( name=spdx2_file.name, comment=spdx2_file.comment, verified_using=integrity_methods, + concluded_license=license_concluded, + copyright_text=copyright_text, + attribution_text=", ".join(spdx2_file.attribution_texts), ) ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py b/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py index 75406af2a..30dc0814e 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Union +from typing import List, Union from license_expression import ( AND, @@ -27,42 +27,70 @@ NoneLicense, WithAdditionOperator, ) -from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.model import ExtractedLicensingInfo, SpdxNoAssertion, SpdxNone def bump_license_expression_or_none_or_no_assertion( - element: Union[LicenseExpression, SpdxNoAssertion, SpdxNone] + element: Union[LicenseExpression, SpdxNoAssertion, SpdxNone], + extracted_licensing_info: List[ExtractedLicensingInfo], ) -> LicenseField: if isinstance(element, SpdxNone): return NoneLicense() elif isinstance(element, SpdxNoAssertion): return NoAssertionLicense() else: - return bump_license_expression(element) + return bump_license_expression(element, extracted_licensing_info) -def bump_license_expression(license_expression: LicenseExpression) -> AnyLicenseInfo: +def bump_license_expression( + license_expression: LicenseExpression, extracted_licensing_info: List[ExtractedLicensingInfo] +) -> AnyLicenseInfo: if isinstance(license_expression, AND): - return ConjunctiveLicenseSet(member=[bump_license_expression(element) for element in license_expression.args]) + return ConjunctiveLicenseSet( + member=[bump_license_expression(element, extracted_licensing_info) for element in license_expression.args] + ) if isinstance(license_expression, OR): - return DisjunctiveLicenseSet(member=[bump_license_expression(element) for element in license_expression.args]) + return DisjunctiveLicenseSet( + member=[bump_license_expression(element, extracted_licensing_info) for element in license_expression.args] + ) if isinstance(license_expression, LicenseWithExceptionSymbol): - subject_license = bump_license_expression(license_expression.license_symbol) + subject_license = bump_license_expression(license_expression.license_symbol, extracted_licensing_info) if not isinstance(subject_license, License): raise ValueError("Subject of LicenseException couldn't be converted to License.") return WithAdditionOperator( subject_license=subject_license, - subject_addition=bump_license_exception(license_expression.exception_symbol), + subject_addition=bump_license_exception(license_expression.exception_symbol, extracted_licensing_info), ) if isinstance(license_expression, LicenseSymbol): if not get_spdx_licensing().validate(license_expression).invalid_symbols: return ListedLicense(license_expression.key, license_expression.obj, "") else: + for licensing_info in extracted_licensing_info: + if licensing_info.license_id == license_expression.key: + # the fields are optional in ExtractedLicensingInfo, to prevent type errors we use a type + # conversion to str as a quick fix + return CustomLicense( + str(licensing_info.license_id), + str(licensing_info.license_name), + str(licensing_info.extracted_text), + ) + return CustomLicense(license_expression.key, "", "") -def bump_license_exception(license_exception: LicenseSymbol) -> LicenseAddition: +def bump_license_exception( + license_exception: LicenseSymbol, extracted_licensing_info: List[ExtractedLicensingInfo] +) -> LicenseAddition: if not get_spdx_licensing().validate(license_exception).invalid_symbols: return ListedLicenseException(license_exception.key, "", "") else: + for licensing_info in extracted_licensing_info: + if licensing_info.license_id == license_exception.key: + # the fields are optional in ExtractedLicensingInfo, to prevent type errors we use a type conversion + # to str as a quick fix + return CustomLicenseAddition( + str(licensing_info.license_id), + str(licensing_info.license_name), + str(licensing_info.extracted_text), + ) return CustomLicenseAddition(license_exception.key, "", "") diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index 2befb9fe9..bb35f5e3e 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -1,11 +1,12 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Optional, Union +from typing import List, Optional, Union from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import ( CreationInformation, @@ -17,12 +18,17 @@ from spdx_tools.spdx3.model.software import Package, SoftwarePurpose from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model import Actor as Spdx2_Actor +from spdx_tools.spdx.model import ExtractedLicensingInfo, SpdxNoAssertion from spdx_tools.spdx.model.package import ExternalPackageRef from spdx_tools.spdx.model.package import Package as Spdx2_Package def bump_package( - spdx2_package: Spdx2_Package, payload: Payload, creation_information: CreationInformation, document_namespace: str + spdx2_package: Spdx2_Package, + payload: Payload, + creation_information: CreationInformation, + document_namespace: str, + extracted_licensing_info: List[ExtractedLicensingInfo], ): spdx_id = "#".join([document_namespace, spdx2_package.spdx_id]) download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") @@ -42,9 +48,19 @@ def bump_package( ) # package.checksums -> package.verified_using integrity_methods = [bump_checksum(checksum) for checksum in spdx2_package.checksums] + declared_license = bump_license_expression_or_none_or_no_assertion( + spdx2_package.license_declared, extracted_licensing_info + ) + concluded_license = bump_license_expression_or_none_or_no_assertion( + spdx2_package.license_concluded, extracted_licensing_info + ) + copyright_text = None + if isinstance(spdx2_package.copyright_text, str): + copyright_text = spdx2_package.copyright_text + elif isinstance(spdx2_package.copyright_text, SpdxNoAssertion): + print_missing_conversion("package2.copyright_text", 0) print_missing_conversion( - "package2.license_concluded, package2.license_info_from_files, package2.license_declared, " - "package2.license_comment, package2.copyright_text", + "package2.license_info_from_files, package2.license_comment", 0, "and missing definition of license profile", ) @@ -67,7 +83,6 @@ def bump_package( elif isinstance(id_or_ref, ExternalIdentifier): external_identifiers.append(id_or_ref) - print_missing_conversion("package2.attribution_texts", 0, "missing definition of license profile") package_purpose = ( [SoftwarePurpose[spdx2_package.primary_package_purpose.name]] if spdx2_package.primary_package_purpose else [] ) @@ -93,6 +108,10 @@ def bump_package( package_url=package_url, homepage=spdx2_package.homepage, source_info=spdx2_package.source_info, + copyright_text=copyright_text, + attribution_text=", ".join(spdx2_package.attribution_texts), + concluded_license=concluded_license, + declared_license=declared_license, ) ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index 1a0a4e69d..27fa5d475 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -1,27 +1,40 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from typing import List + +from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import CreationInformation from spdx_tools.spdx3.model.software import Snippet from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import ExtractedLicensingInfo, SpdxNoAssertion from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet def bump_snippet( - spdx2_snippet: Spdx2_Snippet, payload: Payload, creation_information: CreationInformation, document_namespace: str + spdx2_snippet: Spdx2_Snippet, + payload: Payload, + creation_information: CreationInformation, + document_namespace: str, + extracted_licensing_info: List[ExtractedLicensingInfo], ): spdx_id = "#".join([document_namespace, spdx2_snippet.spdx_id]) print_missing_conversion("snippet.file_spdx_id", 0, "https://github.com/spdx/spdx-3-model/issues/130") + concluded_license = bump_license_expression_or_none_or_no_assertion( + spdx2_snippet.license_concluded, extracted_licensing_info + ) + copyright_text = None + if isinstance(spdx2_snippet.copyright_text, str): + copyright_text = spdx2_snippet.copyright_text + elif isinstance(spdx2_snippet.copyright_text, SpdxNoAssertion): + print_missing_conversion("package2.copyright_text", 0) print_missing_conversion( - "snippet.concluded_license, snippet.license_info_in_snippet, snippet.license_comment," - "snippet.copyright_text", + "snippet.license_info_in_snippet, snippet.license_comment,", 0, "missing definitions for license profile", ) - print_missing_conversion("snippet.attribution_texts", 0, "missing definitions for license profile") - payload.add_element( Snippet( spdx_id=spdx_id, @@ -30,5 +43,8 @@ def bump_snippet( comment=spdx2_snippet.comment, byte_range=spdx2_snippet.byte_range, line_range=spdx2_snippet.line_range, + copyright_text=copyright_text, + attribution_text=", ".join(spdx2_snippet.attribution_texts), + concluded_license=concluded_license, ) ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py index 7e51a0473..9267dc7e8 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py @@ -25,13 +25,13 @@ def bump_spdx_document(document: Spdx2_Document) -> Payload: payload.add_element(spdx_document) for spdx2_package in document.packages: - bump_package(spdx2_package, payload, creation_info, document_namespace) + bump_package(spdx2_package, payload, creation_info, document_namespace, document.extracted_licensing_info) for spdx2_file in document.files: - bump_file(spdx2_file, payload, creation_info, document_namespace) + bump_file(spdx2_file, payload, creation_info, document_namespace, document.extracted_licensing_info) for spdx2_snippet in document.snippets: - bump_snippet(spdx2_snippet, payload, creation_info, document_namespace) + bump_snippet(spdx2_snippet, payload, creation_info, document_namespace, document.extracted_licensing_info) bump_relationships(document.relationships, payload, creation_info, document_namespace) diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index 7e63e6dd3..a3e1acddf 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -5,6 +5,7 @@ from spdx_tools.spdx3.bump_from_spdx2.file import bump_file from spdx_tools.spdx3.model import Hash, HashAlgorithm +from spdx_tools.spdx3.model.licensing import ConjunctiveLicenseSet, ListedLicense from spdx_tools.spdx3.model.software import File from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.file import File as Spdx2_File @@ -19,9 +20,14 @@ def test_bump_file(creation_information): integrity_method: Hash = Hash(HashAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c") expected_new_file_id = f"{document_namespace}#{spdx2_file.spdx_id}" - bump_file(spdx2_file, payload, creation_information, document_namespace) + bump_file(spdx2_file, payload, creation_information, document_namespace, None) file = payload.get_element(expected_new_file_id) assert isinstance(file, File) assert file.spdx_id == expected_new_file_id assert file.verified_using == [integrity_method] + assert file.concluded_license == ConjunctiveLicenseSet( + [ListedLicense("MIT", "MIT", ""), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "")] + ) + assert file.copyright_text == spdx2_file.copyright_text + assert file.attribution_text == spdx2_file.attribution_texts[0] diff --git a/tests/spdx3/bump/test_license_expression_bump.py b/tests/spdx3/bump/test_license_expression_bump.py index a775279f8..3e6fbcc6f 100644 --- a/tests/spdx3/bump/test_license_expression_bump.py +++ b/tests/spdx3/bump/test_license_expression_bump.py @@ -20,6 +20,7 @@ WithAdditionOperator, ) from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone +from tests.spdx.fixtures import extracted_licensing_info_fixture @pytest.mark.parametrize( @@ -31,55 +32,75 @@ ], ) def test_license_expression_or_none_or_no_assertion(element, expected_class): - license_info = bump_license_expression_or_none_or_no_assertion(element) + license_info = bump_license_expression_or_none_or_no_assertion(element, []) assert isinstance(license_info, expected_class) @pytest.mark.parametrize( - "license_expression, expected_element", + "license_expression, extracted_licensing_info, expected_element", [ - (get_spdx_licensing().parse("MIT"), ListedLicense("MIT", "MIT", "")), - (get_spdx_licensing().parse("LGPL-2.0"), ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "")), - (get_spdx_licensing().parse("LicenseRef-1"), CustomLicense("LicenseRef-1", "", "")), + (get_spdx_licensing().parse("MIT"), [], ListedLicense("MIT", "MIT", "")), + (get_spdx_licensing().parse("LGPL-2.0"), [], ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "")), + ( + get_spdx_licensing().parse("LicenseRef-1"), + [extracted_licensing_info_fixture()], + CustomLicense("LicenseRef-1", "licenseName", "extractedText"), + ), ( get_spdx_licensing().parse("MIT AND LGPL-2.0"), + [], ConjunctiveLicenseSet( [ListedLicense("MIT", "MIT", ""), ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "")] ), ), ( get_spdx_licensing().parse("LicenseRef-1 OR LGPL-2.0"), + [extracted_licensing_info_fixture()], DisjunctiveLicenseSet( - [CustomLicense("LicenseRef-1", "", ""), ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "")] + [ + CustomLicense("LicenseRef-1", "licenseName", "extractedText"), + ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", ""), + ] ), ), ( get_spdx_licensing().parse("LGPL-2.0 WITH 389-exception"), + [], WithAdditionOperator( ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", ""), ListedLicenseException("389-exception", "", "") ), ), ( get_spdx_licensing().parse("LicenseRef-1 WITH custom-exception"), + [ + extracted_licensing_info_fixture(), + extracted_licensing_info_fixture("custom-exception", "This is a custom exception", "exceptionName"), + ], WithAdditionOperator( - CustomLicense("LicenseRef-1", "", ""), CustomLicenseAddition("custom-exception", "", "") + CustomLicense("LicenseRef-1", "licenseName", "extractedText"), + CustomLicenseAddition("custom-exception", "exceptionName", "This is a custom exception"), ), ), ( get_spdx_licensing().parse("MIT AND LicenseRef-1 WITH custom-exception"), + [ + extracted_licensing_info_fixture(), + extracted_licensing_info_fixture("custom-exception", "This is a custom exception", "exceptionName"), + ], ConjunctiveLicenseSet( [ ListedLicense("MIT", "MIT", ""), WithAdditionOperator( - CustomLicense("LicenseRef-1", "", ""), CustomLicenseAddition("custom-exception", "", "") + CustomLicense("LicenseRef-1", "licenseName", "extractedText"), + CustomLicenseAddition("custom-exception", "exceptionName", "This is a custom exception"), ), ] ), ), ], ) -def test_license_expression_bump(license_expression: LicenseExpression, expected_element): - license_info = bump_license_expression(license_expression) +def test_license_expression_bump(license_expression: LicenseExpression, extracted_licensing_info, expected_element): + license_info = bump_license_expression(license_expression, extracted_licensing_info) assert license_info == expected_element diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index a84a9fc80..f0d68c7c3 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -7,6 +7,7 @@ from spdx_tools.spdx3.bump_from_spdx2.package import bump_package from spdx_tools.spdx3.model import ExternalIdentifier, ExternalIdentifierType, ExternalReference, ExternalReferenceType +from spdx_tools.spdx3.model.licensing import ConjunctiveLicenseSet, ListedLicense from spdx_tools.spdx3.model.software import Package from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model import SpdxNoAssertion @@ -38,7 +39,7 @@ def test_bump_package(creation_information, originator, expected_originator): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_information, document_namespace) + bump_package(spdx2_package, payload, creation_information, document_namespace, []) package = payload.get_element(expected_new_package_id) assert isinstance(package, Package) @@ -58,6 +59,14 @@ def test_bump_package(creation_information, originator, expected_originator): assert package.built_time == spdx2_package.built_date assert package.release_time == spdx2_package.release_date assert package.valid_until_time == spdx2_package.valid_until_date + assert package.copyright_text == spdx2_package.copyright_text + assert package.attribution_text == spdx2_package.attribution_texts[0] + assert package.concluded_license == ConjunctiveLicenseSet( + [ListedLicense("MIT", "MIT", ""), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "")] + ) + assert package.declared_license == ConjunctiveLicenseSet( + [ListedLicense("MIT", "MIT", ""), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "")] + ) @mock.patch("spdx_tools.spdx3.model.CreationInformation") @@ -71,7 +80,7 @@ def test_bump_of_single_purl_without_comment(creation_information): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_information, document_namespace) + bump_package(spdx2_package, payload, creation_information, document_namespace, []) package = payload.get_element(expected_new_package_id) assert package.package_url == "purl_locator" @@ -90,7 +99,7 @@ def test_bump_of_single_purl_with_comment(creation_information): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_information, document_namespace) + bump_package(spdx2_package, payload, creation_information, document_namespace, []) package = payload.get_element(expected_new_package_id) assert package.package_url is None @@ -112,7 +121,7 @@ def test_bump_of_multiple_purls(creation_information): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_information, document_namespace) + bump_package(spdx2_package, payload, creation_information, document_namespace, []) package = payload.get_element(expected_new_package_id) assert package.package_url is None diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index 9c9ecb72e..f5cc8178f 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -4,6 +4,7 @@ from unittest import mock from spdx_tools.spdx3.bump_from_spdx2.snippet import bump_snippet +from spdx_tools.spdx3.model.licensing import ConjunctiveLicenseSet, ListedLicense from spdx_tools.spdx3.model.software import Snippet from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet @@ -17,8 +18,13 @@ def test_bump_snippet(creation_information): spdx2_snippet: Spdx2_Snippet = snippet_fixture() expected_new_snippet_id = f"{document_namespace}#{spdx2_snippet.spdx_id}" - bump_snippet(spdx2_snippet, payload, creation_information, document_namespace) + bump_snippet(spdx2_snippet, payload, creation_information, document_namespace, []) snippet = payload.get_element(expected_new_snippet_id) assert isinstance(snippet, Snippet) assert snippet.spdx_id == expected_new_snippet_id + assert snippet.copyright_text == spdx2_snippet.copyright_text + assert snippet.attribution_text == spdx2_snippet.attribution_texts[0] + assert snippet.concluded_license == ConjunctiveLicenseSet( + [ListedLicense("MIT", "MIT", ""), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "")] + ) From 4f0674e81f9797536dda8685fa6bf4bd1a251a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 9 May 2023 15:29:28 +0200 Subject: [PATCH 207/354] [issue-426] add SBOMType MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/model/software/__init__.py | 2 +- src/spdx_tools/spdx3/model/software/sbom.py | 15 +++++++++++++++ tests/spdx3/model/software/test_sbom.py | 11 +++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/spdx_tools/spdx3/model/software/__init__.py b/src/spdx_tools/spdx3/model/software/__init__.py index 6f1253a98..df338b385 100644 --- a/src/spdx_tools/spdx3/model/software/__init__.py +++ b/src/spdx_tools/spdx3/model/software/__init__.py @@ -2,7 +2,7 @@ from spdx_tools.spdx3.model.software.file import File from spdx_tools.spdx3.model.software.package import Package from spdx_tools.spdx3.model.software.snippet import Snippet -from spdx_tools.spdx3.model.software.sbom import Sbom +from spdx_tools.spdx3.model.software.sbom import Sbom, SBOMType from spdx_tools.spdx3.model.software.software_dependency_relationship import ( SoftwareDependencyRelationship, SoftwareDependencyLinkType, diff --git a/src/spdx_tools/spdx3/model/software/sbom.py b/src/spdx_tools/spdx3/model/software/sbom.py index bbe1cb9ea..227d68f74 100644 --- a/src/spdx_tools/spdx3/model/software/sbom.py +++ b/src/spdx_tools/spdx3/model/software/sbom.py @@ -1,6 +1,8 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from enum import Enum, auto from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties @@ -16,8 +18,19 @@ ) +class SBOMType(Enum): + DESIGN = auto() + SOURCE = auto() + BUILD = auto() + DEPLOYED = auto() + RUNTIME = auto() + ANALYZED = auto() + + @dataclass_with_properties class Sbom(Bom): + sbom_type: List[SBOMType] = field(default_factory=list) + # We overwrite the super-__init__ as check_types_and_set_values() # takes care of all fields (including inherited ones). def __init__( @@ -37,10 +50,12 @@ def __init__( namespaces: List[NamespaceMap] = None, imports: List[ExternalMap] = None, context: Optional[str] = None, + sbom_type: List[SBOMType] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports + sbom_type = [] if sbom_type is None else sbom_type check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index 9e2c304ca..9a8a889ef 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -5,17 +5,24 @@ import pytest -from spdx_tools.spdx3.model.software import Sbom +from spdx_tools.spdx3.model.software import Sbom, SBOMType @mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_correct_initialization(creation_information): - sbom = Sbom("SPDXRef-Sbom", creation_information, elements=["spdx_id1", "spdx_id2"], root_elements=["spdx_id3"]) + sbom = Sbom( + "SPDXRef-Sbom", + creation_information, + elements=["spdx_id1", "spdx_id2"], + root_elements=["spdx_id3"], + sbom_type=[SBOMType.DESIGN], + ) assert sbom.spdx_id == "SPDXRef-Sbom" assert sbom.creation_info == creation_information assert sbom.elements == ["spdx_id1", "spdx_id2"] assert sbom.root_elements == ["spdx_id3"] + assert sbom.sbom_type == [SBOMType.DESIGN] def test_invalid_initialization(): From 72aacd1285136cb569d79574dd7b47ab65967dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 8 May 2023 15:50:48 +0200 Subject: [PATCH 208/354] [issue-426] add security profile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../spdx3/model/security/__init__.py | 18 ++++++ .../cvss_v2_vuln_assessment_relationship.py | 50 +++++++++++++++ .../cvss_v3_vuln_assessment_relationship.py | 50 +++++++++++++++ .../epss_vuln_assessment_relationship.py | 48 +++++++++++++++ ...it_catalog_vuln_assessment_relationship.py | 56 +++++++++++++++++ .../ssvc_vuln_assessment_relationship.py | 54 ++++++++++++++++ ...x_affected_vuln_assessment_relationship.py | 52 ++++++++++++++++ .../vex_fixed_vuln_assessment_relationship.py | 45 ++++++++++++++ ...t_affected_vuln_assessment_relationship.py | 61 +++++++++++++++++++ ...estigation_vuln_assessment_relationship.py | 45 ++++++++++++++ .../vex_vuln_assessment_relationship.py | 18 ++++++ .../security/vuln_assessment_relationship.py | 22 +++++++ .../spdx3/model/security/vulnerability.py | 37 +++++++++++ 13 files changed, 556 insertions(+) create mode 100644 src/spdx_tools/spdx3/model/security/__init__.py create mode 100644 src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py create mode 100644 src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py create mode 100644 src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py create mode 100644 src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py create mode 100644 src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py create mode 100644 src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py create mode 100644 src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py create mode 100644 src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py create mode 100644 src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py create mode 100644 src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py create mode 100644 src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py create mode 100644 src/spdx_tools/spdx3/model/security/vulnerability.py diff --git a/src/spdx_tools/spdx3/model/security/__init__.py b/src/spdx_tools/spdx3/model/security/__init__.py new file mode 100644 index 000000000..db283be7e --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/__init__.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from cvss_v2_vuln_assessment_relationship import CvssV2VulnAssessmentRelationship +from cvss_v3_vuln_assessment_relationship import CvssV3VulnAssessmentRelationship +from epss_vuln_assessment_relationship import EpssVulnAssessmentRelationship +from exploit_catalog_vuln_assessment_relationship import ExploitCatalogVulnAssessmentRelationship, ExploitCatalogType +from ssvc_vuln_assessment_relationship import SsvcVulnAssessmentRelationship, SsvcDecisionType +from vex_affected_vuln_assessment_relationship import VexAffectedVulnAssessmentRelationship +from vex_fixed_vuln_assessment_relationship import VexFixedVulnAssessmentRelationship +from vex_not_affected_vuln_assessment_relationship import ( + VexNotAffectedVulnAssessmentRelationship, + VexJustificationType, +) +from vex_under_investigation_vuln_assessment_relationship import VexUnderInvestigationVulnAssessmentRelationship +from vex_vuln_assessment_relationship import VexVulnAssessmentRelationship +from vuln_assessment_relationship import VulnAssessmentRelationship +from vulnerability import Vulnerability diff --git a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py new file mode 100644 index 000000000..5e370bef7 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + Agent, + CreationInformation, + Element, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, +) +from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship + + +@dataclass_with_properties +class CvssV2VulnAssessmentRelationship(VulnAssessmentRelationship): + score: float + severity: Optional[str] = None + vector: Optional[str] = None + + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + score: float, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + assessed_element: Optional[Element] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[Agent] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + severity: Optional[str] = None, + vector: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py new file mode 100644 index 000000000..dc487bddf --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + Agent, + CreationInformation, + Element, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, +) +from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship + + +@dataclass_with_properties +class CvssV3VulnAssessmentRelationship(VulnAssessmentRelationship): + score: float + severity: Optional[str] = None + vector: Optional[str] = None + + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + score: float, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + assessed_element: Optional[Element] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[Agent] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + severity: Optional[str] = None, + vector: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py new file mode 100644 index 000000000..475f6d9f2 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + Agent, + CreationInformation, + Element, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, +) +from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship + + +@dataclass_with_properties +class EpssVulnAssessmentRelationship(VulnAssessmentRelationship): + probability: int + severity: Optional[str] = None + + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + probability: int, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + assessed_element: Optional[Element] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[Agent] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + severity: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py new file mode 100644 index 000000000..99bb47040 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py @@ -0,0 +1,56 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from enum import Enum, auto +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + Agent, + CreationInformation, + Element, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, +) +from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship + + +class ExploitCatalogType(Enum): + KEV = auto() + OTHER = auto() + + +@dataclass_with_properties +class ExploitCatalogVulnAssessmentRelationship(VulnAssessmentRelationship): + catalog_type: ExploitCatalogType + exploited: bool + locator: str + + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + catalog_type: ExploitCatalogType, + exploited: bool, + locator: str, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + assessed_element: Optional[Element] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[Agent] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py new file mode 100644 index 000000000..09f992a1a --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from enum import auto +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + Agent, + CreationInformation, + Element, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, +) +from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship + + +class SsvcDecisionType: + ACT = auto() + ATTEND = auto() + TRACK = auto() + TRACK_STAR = auto() + + +@dataclass_with_properties +class SsvcVulnAssessmentRelationship(VulnAssessmentRelationship): + decision: SsvcDecisionType + + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + decision: SsvcDecisionType, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + assessed_element: Optional[Element] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[Agent] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py new file mode 100644 index 000000000..87b57d669 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py @@ -0,0 +1,52 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from dataclasses import field +from datetime import datetime +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + Agent, + CreationInformation, + Element, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, +) +from spdx_tools.spdx3.model.security.vex_vuln_assessment_relationship import VexVulnAssessmentRelationship + + +@dataclass_with_properties +class VexAffectedVulnAssessmentRelationship(VexVulnAssessmentRelationship): + action_statement: Optional[str] = None + action_statement_time: List[str] = field(default_factory=list) + + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + assessed_element: Optional[Element] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[Agent] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + vex_version: Optional[str] = None, + status_notes: Optional[str] = None, + action_statement: Optional[str] = None, + action_statement_time: List[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + action_statement_time = [] if action_statement_time is None else action_statement_time + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py new file mode 100644 index 000000000..6cd754e10 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + Agent, + CreationInformation, + Element, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, +) +from spdx_tools.spdx3.model.security.vex_vuln_assessment_relationship import VexVulnAssessmentRelationship + + +@dataclass_with_properties +class VexFixedVulnAssessmentRelationship(VexVulnAssessmentRelationship): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + assessed_element: Optional[Element] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[Agent] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + vex_version: Optional[str] = None, + status_notes: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py new file mode 100644 index 000000000..9faac1fdc --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from enum import auto +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + Agent, + CreationInformation, + Element, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, +) +from spdx_tools.spdx3.model.security.vex_vuln_assessment_relationship import VexVulnAssessmentRelationship + + +class VexJustificationType: + COMPONENT_NOT_PRESENT = auto() + VULNERABLE_CODE_NOT_PRESENT = auto() + VULNERABLE_CODE_CANNOT_BE_CONTROLLED_BY_ADVERSARY = auto() + VULNERABLE_CODE_NOT_IN_EXECUTE_PATH = auto() + INLINE_MITIGATIONS_ALREADY_EXIST = auto() + + +@dataclass_with_properties +class VexNotAffectedVulnAssessmentRelationship(VexVulnAssessmentRelationship): + justification: Optional[VexJustificationType] = None + impact_statement: Optional[str] = None + impact_statement_time: Optional[datetime] = None + + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + assessed_element: Optional[Element] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[Agent] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + vex_version: Optional[str] = None, + status_notes: Optional[str] = None, + justification: Optional[VexJustificationType] = None, + impact_statement: Optional[str] = None, + impact_statement_time: Optional[datetime] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py new file mode 100644 index 000000000..b3a5986f4 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py @@ -0,0 +1,45 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ( + Agent, + CreationInformation, + Element, + ExternalIdentifier, + ExternalReference, + IntegrityMethod, +) +from spdx_tools.spdx3.model.security.vex_vuln_assessment_relationship import VexVulnAssessmentRelationship + + +@dataclass_with_properties +class VexUnderInvestigationVulnAssessmentRelationship(VexVulnAssessmentRelationship): + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + assessed_element: Optional[Element] = None, + published_time: Optional[datetime] = None, + supplied_by: Optional[Agent] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + vex_version: Optional[str] = None, + status_notes: Optional[str] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py new file mode 100644 index 000000000..2ef0bd24e --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import ABC, abstractmethod +from typing import Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship + + +@dataclass_with_properties +class VexVulnAssessmentRelationship(VulnAssessmentRelationship, ABC): + vex_version: Optional[str] = None + status_notes: Optional[str] = None + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py new file mode 100644 index 000000000..0b6e19d95 --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from abc import ABC, abstractmethod +from datetime import datetime +from typing import Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.spdx3.model import Agent, Element, Relationship + + +@dataclass_with_properties +class VulnAssessmentRelationship(Relationship, ABC): + assessed_element: Optional[Element] = None + published_time: Optional[datetime] = None + supplied_by: Optional[Agent] = None + modified_time: Optional[datetime] = None + withdrawn_time: Optional[datetime] = None + + @abstractmethod + def __init__(self): + pass diff --git a/src/spdx_tools/spdx3/model/security/vulnerability.py b/src/spdx_tools/spdx3/model/security/vulnerability.py new file mode 100644 index 000000000..0760fe75d --- /dev/null +++ b/src/spdx_tools/spdx3/model/security/vulnerability.py @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from typing import List, Optional + +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import CreationInformation, Element, ExternalIdentifier, ExternalReference, IntegrityMethod + + +@dataclass_with_properties +class Vulnerability(Element): + published_time: Optional[datetime] = None + modified_time: Optional[datetime] = None + withdrawn_time: Optional[datetime] = None + + def __init__( + self, + spdx_id: str, + creation_info: CreationInformation, + name: Optional[str] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + comment: Optional[str] = None, + verified_using: List[IntegrityMethod] = None, + external_references: List[ExternalReference] = None, + external_identifier: List[ExternalIdentifier] = None, + extension: None = None, + published_time: Optional[datetime] = None, + modified_time: Optional[datetime] = None, + withdrawn_time: Optional[datetime] = None, + ): + verified_using = [] if verified_using is None else verified_using + external_references = [] if external_references is None else external_references + external_identifier = [] if external_identifier is None else external_identifier + check_types_and_set_values(self, locals()) From 196a0bd1d2d354ca170e451b880a5229e5a02568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 9 May 2023 11:24:43 +0200 Subject: [PATCH 209/354] [issue-426] include Relationship properties in security relationships MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../cvss_v2_vuln_assessment_relationship.py | 10 +++++++++- .../cvss_v3_vuln_assessment_relationship.py | 10 +++++++++- .../security/epss_vuln_assessment_relationship.py | 10 +++++++++- ...exploit_catalog_vuln_assessment_relationship.py | 14 +++++++++++--- .../security/ssvc_vuln_assessment_relationship.py | 10 +++++++++- .../vex_affected_vuln_assessment_relationship.py | 8 ++++++++ .../vex_fixed_vuln_assessment_relationship.py | 8 ++++++++ ...ex_not_affected_vuln_assessment_relationship.py | 8 ++++++++ ...r_investigation_vuln_assessment_relationship.py | 8 ++++++++ 9 files changed, 79 insertions(+), 7 deletions(-) diff --git a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py index 5e370bef7..65deebfdc 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py @@ -13,13 +13,15 @@ ExternalIdentifier, ExternalReference, IntegrityMethod, + RelationshipCompleteness, ) from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType @dataclass_with_properties class CvssV2VulnAssessmentRelationship(VulnAssessmentRelationship): - score: float + score: float = None severity: Optional[str] = None vector: Optional[str] = None @@ -27,6 +29,9 @@ def __init__( self, spdx_id: str, creation_info: CreationInformation, + from_element: str, + to: List[str], + relationship_type: RelationshipType, score: float, name: Optional[str] = None, summary: Optional[str] = None, @@ -36,6 +41,9 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, assessed_element: Optional[Element] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, diff --git a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py index dc487bddf..b81d6ab71 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py @@ -13,13 +13,15 @@ ExternalIdentifier, ExternalReference, IntegrityMethod, + RelationshipCompleteness, ) from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType @dataclass_with_properties class CvssV3VulnAssessmentRelationship(VulnAssessmentRelationship): - score: float + score: float = None severity: Optional[str] = None vector: Optional[str] = None @@ -27,6 +29,9 @@ def __init__( self, spdx_id: str, creation_info: CreationInformation, + from_element: str, + to: List[str], + relationship_type: RelationshipType, score: float, name: Optional[str] = None, summary: Optional[str] = None, @@ -36,6 +41,9 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, assessed_element: Optional[Element] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, diff --git a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py index 475f6d9f2..10f279fcd 100644 --- a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py @@ -13,19 +13,24 @@ ExternalIdentifier, ExternalReference, IntegrityMethod, + RelationshipCompleteness, ) from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType @dataclass_with_properties class EpssVulnAssessmentRelationship(VulnAssessmentRelationship): - probability: int + probability: int = None severity: Optional[str] = None def __init__( self, spdx_id: str, creation_info: CreationInformation, + from_element: str, + to: List[str], + relationship_type: RelationshipType, probability: int, name: Optional[str] = None, summary: Optional[str] = None, @@ -35,6 +40,9 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, assessed_element: Optional[Element] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, diff --git a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py index 99bb47040..99079d3f0 100644 --- a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py @@ -14,8 +14,10 @@ ExternalIdentifier, ExternalReference, IntegrityMethod, + RelationshipCompleteness, ) from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType class ExploitCatalogType(Enum): @@ -25,14 +27,17 @@ class ExploitCatalogType(Enum): @dataclass_with_properties class ExploitCatalogVulnAssessmentRelationship(VulnAssessmentRelationship): - catalog_type: ExploitCatalogType - exploited: bool - locator: str + catalog_type: ExploitCatalogType = None + exploited: bool = None + locator: str = None def __init__( self, spdx_id: str, creation_info: CreationInformation, + from_element: str, + to: List[str], + relationship_type: RelationshipType, catalog_type: ExploitCatalogType, exploited: bool, locator: str, @@ -44,6 +49,9 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, assessed_element: Optional[Element] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, diff --git a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py index 09f992a1a..b1cb98859 100644 --- a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py @@ -14,8 +14,10 @@ ExternalIdentifier, ExternalReference, IntegrityMethod, + RelationshipCompleteness, ) from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType class SsvcDecisionType: @@ -27,12 +29,15 @@ class SsvcDecisionType: @dataclass_with_properties class SsvcVulnAssessmentRelationship(VulnAssessmentRelationship): - decision: SsvcDecisionType + decision: SsvcDecisionType = None def __init__( self, spdx_id: str, creation_info: CreationInformation, + from_element: str, + to: List[str], + relationship_type: RelationshipType, decision: SsvcDecisionType, name: Optional[str] = None, summary: Optional[str] = None, @@ -42,6 +47,9 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, assessed_element: Optional[Element] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py index 87b57d669..9c497b563 100644 --- a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py @@ -14,8 +14,10 @@ ExternalIdentifier, ExternalReference, IntegrityMethod, + RelationshipCompleteness, ) from spdx_tools.spdx3.model.security.vex_vuln_assessment_relationship import VexVulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType @dataclass_with_properties @@ -27,6 +29,9 @@ def __init__( self, spdx_id: str, creation_info: CreationInformation, + from_element: str, + to: List[str], + relationship_type: RelationshipType, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, @@ -35,6 +40,9 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, assessed_element: Optional[Element] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py index 6cd754e10..acbaefe1f 100644 --- a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py @@ -13,8 +13,10 @@ ExternalIdentifier, ExternalReference, IntegrityMethod, + RelationshipCompleteness, ) from spdx_tools.spdx3.model.security.vex_vuln_assessment_relationship import VexVulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType @dataclass_with_properties @@ -23,6 +25,9 @@ def __init__( self, spdx_id: str, creation_info: CreationInformation, + from_element: str, + to: List[str], + relationship_type: RelationshipType, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, @@ -31,6 +36,9 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, assessed_element: Optional[Element] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py index 9faac1fdc..ffb440108 100644 --- a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py @@ -14,8 +14,10 @@ ExternalIdentifier, ExternalReference, IntegrityMethod, + RelationshipCompleteness, ) from spdx_tools.spdx3.model.security.vex_vuln_assessment_relationship import VexVulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType class VexJustificationType: @@ -36,6 +38,9 @@ def __init__( self, spdx_id: str, creation_info: CreationInformation, + from_element: str, + to: List[str], + relationship_type: RelationshipType, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, @@ -44,6 +49,9 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, assessed_element: Optional[Element] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py index b3a5986f4..a946a4744 100644 --- a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py @@ -13,8 +13,10 @@ ExternalIdentifier, ExternalReference, IntegrityMethod, + RelationshipCompleteness, ) from spdx_tools.spdx3.model.security.vex_vuln_assessment_relationship import VexVulnAssessmentRelationship +from spdx_tools.spdx.model import RelationshipType @dataclass_with_properties @@ -23,6 +25,9 @@ def __init__( self, spdx_id: str, creation_info: CreationInformation, + from_element: str, + to: List[str], + relationship_type: RelationshipType, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, @@ -31,6 +36,9 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, + completeness: Optional[RelationshipCompleteness] = None, + start_time: Optional[datetime] = None, + end_time: Optional[datetime] = None, assessed_element: Optional[Element] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, From c8890f4215ca19ac0203325cf96b8c37e481f8e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 9 May 2023 11:27:48 +0200 Subject: [PATCH 210/354] [issue-426] Security profile: fix types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../spdx3/model/security/__init__.py | 24 +++++++++---------- .../cvss_v2_vuln_assessment_relationship.py | 3 +-- .../cvss_v3_vuln_assessment_relationship.py | 3 +-- .../epss_vuln_assessment_relationship.py | 3 +-- ...it_catalog_vuln_assessment_relationship.py | 3 +-- .../ssvc_vuln_assessment_relationship.py | 3 +-- ...x_affected_vuln_assessment_relationship.py | 7 +++--- .../vex_fixed_vuln_assessment_relationship.py | 3 +-- ...t_affected_vuln_assessment_relationship.py | 3 +-- ...estigation_vuln_assessment_relationship.py | 3 +-- .../vex_vuln_assessment_relationship.py | 4 ++-- .../security/vuln_assessment_relationship.py | 8 +++---- 12 files changed, 29 insertions(+), 38 deletions(-) diff --git a/src/spdx_tools/spdx3/model/security/__init__.py b/src/spdx_tools/spdx3/model/security/__init__.py index db283be7e..3407981c8 100644 --- a/src/spdx_tools/spdx3/model/security/__init__.py +++ b/src/spdx_tools/spdx3/model/security/__init__.py @@ -1,18 +1,18 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from cvss_v2_vuln_assessment_relationship import CvssV2VulnAssessmentRelationship -from cvss_v3_vuln_assessment_relationship import CvssV3VulnAssessmentRelationship -from epss_vuln_assessment_relationship import EpssVulnAssessmentRelationship -from exploit_catalog_vuln_assessment_relationship import ExploitCatalogVulnAssessmentRelationship, ExploitCatalogType -from ssvc_vuln_assessment_relationship import SsvcVulnAssessmentRelationship, SsvcDecisionType -from vex_affected_vuln_assessment_relationship import VexAffectedVulnAssessmentRelationship -from vex_fixed_vuln_assessment_relationship import VexFixedVulnAssessmentRelationship -from vex_not_affected_vuln_assessment_relationship import ( +from .cvss_v2_vuln_assessment_relationship import CvssV2VulnAssessmentRelationship +from .cvss_v3_vuln_assessment_relationship import CvssV3VulnAssessmentRelationship +from .epss_vuln_assessment_relationship import EpssVulnAssessmentRelationship +from .exploit_catalog_vuln_assessment_relationship import ExploitCatalogVulnAssessmentRelationship, ExploitCatalogType +from .ssvc_vuln_assessment_relationship import SsvcVulnAssessmentRelationship, SsvcDecisionType +from .vex_affected_vuln_assessment_relationship import VexAffectedVulnAssessmentRelationship +from .vex_fixed_vuln_assessment_relationship import VexFixedVulnAssessmentRelationship +from .vex_not_affected_vuln_assessment_relationship import ( VexNotAffectedVulnAssessmentRelationship, VexJustificationType, ) -from vex_under_investigation_vuln_assessment_relationship import VexUnderInvestigationVulnAssessmentRelationship -from vex_vuln_assessment_relationship import VexVulnAssessmentRelationship -from vuln_assessment_relationship import VulnAssessmentRelationship -from vulnerability import Vulnerability +from .vex_under_investigation_vuln_assessment_relationship import VexUnderInvestigationVulnAssessmentRelationship +from .vex_vuln_assessment_relationship import VexVulnAssessmentRelationship +from .vuln_assessment_relationship import VulnAssessmentRelationship +from .vulnerability import Vulnerability diff --git a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py index 65deebfdc..e45d33ac9 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py @@ -9,7 +9,6 @@ from spdx_tools.spdx3.model import ( Agent, CreationInformation, - Element, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -44,7 +43,7 @@ def __init__( completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, - assessed_element: Optional[Element] = None, + assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, modified_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py index b81d6ab71..1f913861d 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py @@ -9,7 +9,6 @@ from spdx_tools.spdx3.model import ( Agent, CreationInformation, - Element, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -44,7 +43,7 @@ def __init__( completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, - assessed_element: Optional[Element] = None, + assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, modified_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py index 10f279fcd..64375a340 100644 --- a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py @@ -9,7 +9,6 @@ from spdx_tools.spdx3.model import ( Agent, CreationInformation, - Element, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -43,7 +42,7 @@ def __init__( completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, - assessed_element: Optional[Element] = None, + assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, modified_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py index 99079d3f0..f916220ea 100644 --- a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py @@ -10,7 +10,6 @@ from spdx_tools.spdx3.model import ( Agent, CreationInformation, - Element, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -52,7 +51,7 @@ def __init__( completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, - assessed_element: Optional[Element] = None, + assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, modified_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py index b1cb98859..eaf37233a 100644 --- a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py @@ -10,7 +10,6 @@ from spdx_tools.spdx3.model import ( Agent, CreationInformation, - Element, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -50,7 +49,7 @@ def __init__( completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, - assessed_element: Optional[Element] = None, + assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, modified_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py index 9c497b563..61296ea13 100644 --- a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py @@ -10,7 +10,6 @@ from spdx_tools.spdx3.model import ( Agent, CreationInformation, - Element, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -23,7 +22,7 @@ @dataclass_with_properties class VexAffectedVulnAssessmentRelationship(VexVulnAssessmentRelationship): action_statement: Optional[str] = None - action_statement_time: List[str] = field(default_factory=list) + action_statement_time: List[datetime] = field(default_factory=list) def __init__( self, @@ -43,7 +42,7 @@ def __init__( completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, - assessed_element: Optional[Element] = None, + assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, modified_time: Optional[datetime] = None, @@ -51,7 +50,7 @@ def __init__( vex_version: Optional[str] = None, status_notes: Optional[str] = None, action_statement: Optional[str] = None, - action_statement_time: List[str] = None, + action_statement_time: List[datetime] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references diff --git a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py index acbaefe1f..5695f7682 100644 --- a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py @@ -9,7 +9,6 @@ from spdx_tools.spdx3.model import ( Agent, CreationInformation, - Element, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -39,7 +38,7 @@ def __init__( completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, - assessed_element: Optional[Element] = None, + assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, modified_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py index ffb440108..e934aa195 100644 --- a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py @@ -10,7 +10,6 @@ from spdx_tools.spdx3.model import ( Agent, CreationInformation, - Element, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -52,7 +51,7 @@ def __init__( completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, - assessed_element: Optional[Element] = None, + assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, modified_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py index a946a4744..def62ce3a 100644 --- a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py @@ -9,7 +9,6 @@ from spdx_tools.spdx3.model import ( Agent, CreationInformation, - Element, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -39,7 +38,7 @@ def __init__( completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, - assessed_element: Optional[Element] = None, + assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, supplied_by: Optional[Agent] = None, modified_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py index 2ef0bd24e..342ff3fd4 100644 --- a/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from abc import ABC, abstractmethod +from abc import abstractmethod from typing import Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties @@ -9,7 +9,7 @@ @dataclass_with_properties -class VexVulnAssessmentRelationship(VulnAssessmentRelationship, ABC): +class VexVulnAssessmentRelationship(VulnAssessmentRelationship): vex_version: Optional[str] = None status_notes: Optional[str] = None diff --git a/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py index 0b6e19d95..d93befbe2 100644 --- a/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py @@ -1,17 +1,17 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from abc import ABC, abstractmethod +from abc import abstractmethod from datetime import datetime from typing import Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties -from spdx_tools.spdx3.model import Agent, Element, Relationship +from spdx_tools.spdx3.model import Agent, Relationship @dataclass_with_properties -class VulnAssessmentRelationship(Relationship, ABC): - assessed_element: Optional[Element] = None +class VulnAssessmentRelationship(Relationship): + assessed_element: Optional[str] = None # id of the element published_time: Optional[datetime] = None supplied_by: Optional[Agent] = None modified_time: Optional[datetime] = None From bd45cdd2119d1882bed3534e2b7dc4ed468e9b47 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 10 May 2023 10:12:34 +0200 Subject: [PATCH 211/354] update implementation according to recent changes - update AIPackage according to restrictions to external properties - update model_data_explainability and model_data_preprocessing to be lists - rename buildStart and buildEnd in Build Class - add supplied_by and standard in Artifact - add profileIdentifier in CreationInfo and update the Enum class accordingly - make property "to" optional in relationship - update Dataset according to restrictions to external properties - add property datasetType - change type hint for supplied_by to str in security relationships Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/README.md | 2 +- .../bump_from_spdx2/creation_information.py | 8 +++--- .../spdx3/bump_from_spdx2/package.py | 4 ++- .../spdx3/bump_from_spdx2/relationship.py | 4 +-- .../spdx3/bump_from_spdx2/spdx_document.py | 2 +- src/spdx_tools/spdx3/model/__init__.py | 2 +- src/spdx_tools/spdx3/model/ai/ai_package.py | 25 ++++++++++------- src/spdx_tools/spdx3/model/annotation.py | 6 ++-- src/spdx_tools/spdx3/model/artifact.py | 7 +++-- src/spdx_tools/spdx3/model/bom.py | 4 +-- src/spdx_tools/spdx3/model/build/build.py | 8 +++--- src/spdx_tools/spdx3/model/bundle.py | 8 +++--- .../spdx3/model/creation_information.py | 5 ++-- src/spdx_tools/spdx3/model/dataset/dataset.py | 28 ++++++++++++------- .../model/lifecycle_scoped_relationship.py | 3 +- .../spdx3/model/profile_identifier.py | 6 ++++ src/spdx_tools/spdx3/model/relationship.py | 6 ++-- .../cvss_v2_vuln_assessment_relationship.py | 3 +- .../cvss_v3_vuln_assessment_relationship.py | 3 +- .../epss_vuln_assessment_relationship.py | 3 +- ...it_catalog_vuln_assessment_relationship.py | 3 +- .../ssvc_vuln_assessment_relationship.py | 3 +- ...x_affected_vuln_assessment_relationship.py | 3 +- .../vex_fixed_vuln_assessment_relationship.py | 3 +- ...t_affected_vuln_assessment_relationship.py | 3 +- ...estigation_vuln_assessment_relationship.py | 3 +- .../security/vuln_assessment_relationship.py | 4 +-- src/spdx_tools/spdx3/model/software/file.py | 7 ++++- .../spdx3/model/software/package.py | 7 ++++- src/spdx_tools/spdx3/model/software/sbom.py | 4 +-- .../spdx3/model/software/snippet.py | 7 ++++- .../software_dependency_relationship.py | 3 +- src/spdx_tools/spdx3/model/spdx_collection.py | 6 ++-- src/spdx_tools/spdx3/model/spdx_document.py | 4 +-- .../console/creation_information_writer.py | 2 +- .../writer/console/spdx_collection_writer.py | 6 ++-- tests/spdx3/bump/test_actor_bump.py | 13 +++++++-- tests/spdx3/bump/test_package_bump.py | 6 ++-- tests/spdx3/bump/test_relationship_bump.py | 10 +++---- tests/spdx3/fixtures.py | 12 ++++---- tests/spdx3/model/ai/test_ai_package.py | 25 ++++++++++++++--- tests/spdx3/model/build/test_build.py | 8 +++--- tests/spdx3/model/dataset/test_dataset.py | 28 ++++++++++++++++--- tests/spdx3/model/software/test_package.py | 6 ++++ tests/spdx3/model/software/test_sbom.py | 14 +++++----- tests/spdx3/model/software/test_snippet.py | 2 +- .../test_software_dependency_relationship.py | 4 +-- tests/spdx3/model/test_abstract_classes.py | 4 +-- tests/spdx3/model/test_agent.py | 12 +++++--- tests/spdx3/model/test_annotation.py | 7 ++--- tests/spdx3/model/test_bom.py | 14 +++++----- tests/spdx3/model/test_bundle.py | 14 +++++----- .../spdx3/model/test_creation_information.py | 12 ++++++-- .../test_lifecycle_scoped_relationship.py | 4 +-- tests/spdx3/model/test_relationship.py | 4 +-- tests/spdx3/model/test_spdx_document.py | 16 +++++------ tests/spdx3/model/test_tool.py | 13 +++++---- 57 files changed, 266 insertions(+), 167 deletions(-) diff --git a/src/spdx_tools/spdx3/README.md b/src/spdx_tools/spdx3/README.md index 4f1c3b54d..0f32aa1a9 100644 --- a/src/spdx_tools/spdx3/README.md +++ b/src/spdx_tools/spdx3/README.md @@ -1 +1 @@ -This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: 9dd167007fbf5fd127cc96ab98c9f28238ffb2a3). +This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: ea2e1446ae937c6722b3f599f95813f8747d54b4). diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py index 7e8f86956..01841bdf2 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py @@ -8,7 +8,7 @@ from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor from spdx_tools.spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model import CreationInformation, SpdxDocument +from spdx_tools.spdx3.model import CreationInformation, ProfileIdentifier, SpdxDocument from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.actor import ActorType from spdx_tools.spdx.model.document import CreationInfo as Spdx2_CreationInfo @@ -40,7 +40,7 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: created=spdx2_creation_info.created, created_by=[], created_using=[], - profile=["core", "software", "licensing"], + profile=[ProfileIdentifier.CORE, ProfileIdentifier.SOFTWARE, ProfileIdentifier.LICENSING], data_license=spdx2_creation_info.data_license, comment=spdx2_creation_info.document_comment, ) @@ -73,7 +73,7 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: creation_info=creation_information, name=spdx2_creation_info.name, comment=document_comment, - elements=[], - root_elements=[], + element=[], + root_element=[], imports=imports, ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index bb35f5e3e..a47c7847c 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -37,7 +37,9 @@ def bump_package( # package.supplier -> Relationship, suppliedBy? print_missing_conversion("package2.supplier", 0, "https://github.com/spdx/spdx-3-model/issues/113") if isinstance(spdx2_package.originator, Spdx2_Actor): - originated_by_spdx_id = bump_actor(spdx2_package.originator, payload, creation_information, document_namespace) + originated_by_spdx_id = [ + bump_actor(spdx2_package.originator, payload, creation_information, document_namespace) + ] else: originated_by_spdx_id = None # package.files_analyzed -> ? diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py index 79cee5e0a..9b19e0d11 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -206,8 +206,8 @@ def bump_relationship( spdx_id, creation_information, from_element, - to, relationship_type, + to, comment=spdx2_relationship.comment, completeness=completeness, scope=parameters.get("scope"), @@ -219,8 +219,8 @@ def bump_relationship( spdx_id, creation_information, from_element, - to, relationship_type, + to, comment=spdx2_relationship.comment, completeness=completeness, ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py index 9267dc7e8..78843ef42 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py @@ -38,6 +38,6 @@ def bump_spdx_document(document: Spdx2_Document) -> Payload: for counter, spdx2_annotation in enumerate(document.annotations): bump_annotation(spdx2_annotation, payload, creation_info, document_namespace, counter) - spdx_document.elements = [spdx_id for spdx_id in payload.get_full_map() if spdx_id != spdx_document.spdx_id] + spdx_document.element = [spdx_id for spdx_id in payload.get_full_map() if spdx_id != spdx_document.spdx_id] return payload diff --git a/src/spdx_tools/spdx3/model/__init__.py b/src/spdx_tools/spdx3/model/__init__.py index da137394d..6042b1e77 100644 --- a/src/spdx_tools/spdx3/model/__init__.py +++ b/src/spdx_tools/spdx3/model/__init__.py @@ -12,7 +12,7 @@ from spdx_tools.spdx3.model.organization import Organization from spdx_tools.spdx3.model.software_agent import SoftwareAgent from spdx_tools.spdx3.model.tool import Tool -from spdx_tools.spdx3.model.spdx_collection import SpdxCollection +from spdx_tools.spdx3.model.spdx_collection import ElementCollection from spdx_tools.spdx3.model.bundle import Bundle from spdx_tools.spdx3.model.bom import Bom from spdx_tools.spdx3.model.spdx_document import SpdxDocument diff --git a/src/spdx_tools/spdx3/model/ai/ai_package.py b/src/spdx_tools/spdx3/model/ai/ai_package.py index 9c2372618..f0ed49e33 100644 --- a/src/spdx_tools/spdx3/model/ai/ai_package.py +++ b/src/spdx_tools/spdx3/model/ai/ai_package.py @@ -29,8 +29,8 @@ class AIPackage(Package): information_about_training: Optional[str] = None information_about_application: Optional[str] = None hyperparameter: Dict[str, Optional[str]] = field(default_factory=dict) - model_data_preprocessing: Optional[str] = None - model_explainability: Optional[str] = None + model_data_preprocessing: List[str] = field(default_factory=list) + model_explainability: List[str] = field(default_factory=list) sensitive_personal_information: Optional[bool] = None metric_decision_threshold: Dict[str, Optional[str]] = field(default_factory=dict) metric: Dict[str, Optional[str]] = field(default_factory=dict) @@ -43,6 +43,11 @@ def __init__( spdx_id: str, creation_info: CreationInformation, name: str, + supplied_by: List[str], + download_location: str, + package_version: str, + purpose: List[SoftwarePurpose], + release_time: datetime, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, @@ -50,18 +55,15 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, - originated_by: Optional[str] = None, + originated_by: List[str] = None, built_time: Optional[datetime] = None, - release_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, + standard: List[str] = None, content_identifier: Optional[str] = None, - purpose: List[SoftwarePurpose] = None, concluded_license: Optional[LicenseField] = None, declared_license: Optional[LicenseField] = None, copyright_text: Optional[str] = None, attribution_text: Optional[str] = None, - package_version: Optional[str] = None, - download_location: Optional[str] = None, package_url: Optional[str] = None, homepage: Optional[str] = None, source_info: Optional[str] = None, @@ -72,8 +74,8 @@ def __init__( information_about_training: Optional[str] = None, information_about_application: Optional[str] = None, hyperparameter: Dict[str, Optional[str]] = None, - model_data_preprocessing: Optional[str] = None, - model_explainability: Optional[str] = None, + model_data_preprocessing: List[str] = None, + model_explainability: List[str] = None, sensitive_personal_information: Optional[bool] = None, metric_decision_threshold: Dict[str, Optional[str]] = None, metric: Dict[str, Optional[str]] = None, @@ -84,10 +86,13 @@ def __init__( verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier - purpose = [] if purpose is None else purpose + originated_by = [] if originated_by is None else originated_by + standard = [] if standard is None else standard standard_compliance = [] if standard_compliance is None else standard_compliance type_of_model = [] if type_of_model is None else type_of_model hyperparameter = {} if hyperparameter is None else hyperparameter + model_data_preprocessing = [] if model_data_preprocessing is None else model_data_preprocessing + model_explainability = [] if model_explainability is None else model_explainability metric_decision_threshold = {} if metric_decision_threshold is None else metric_decision_threshold metric = {} if metric is None else metric domain = [] if domain is None else domain diff --git a/src/spdx_tools/spdx3/model/annotation.py b/src/spdx_tools/spdx3/model/annotation.py index d2db8aa2f..5bdbecd5a 100644 --- a/src/spdx_tools/spdx3/model/annotation.py +++ b/src/spdx_tools/spdx3/model/annotation.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from dataclasses import field from enum import Enum, auto from typing import List, Optional @@ -18,7 +19,7 @@ class AnnotationType(Enum): class Annotation(Element): annotation_type: AnnotationType = None subject: str = None - content_type: Optional[str] = None # placeholder for MediaType + content_type: List[str] = field(default_factory=list) # placeholder for MediaType statement: Optional[str] = None def __init__( @@ -35,10 +36,11 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, - content_type: Optional[str] = None, + content_type: List[str] = None, statement: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier + content_type = [] if content_type is None else content_type check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/artifact.py b/src/spdx_tools/spdx3/model/artifact.py index 9f581ddff..bb88fea41 100644 --- a/src/spdx_tools/spdx3/model/artifact.py +++ b/src/spdx_tools/spdx3/model/artifact.py @@ -2,8 +2,9 @@ # # SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod +from dataclasses import field from datetime import datetime -from typing import Optional +from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.spdx3.model import Element @@ -11,10 +12,12 @@ @dataclass_with_properties class Artifact(Element): - originated_by: Optional[str] = None # SPDXID of the Agent/Tool + originated_by: List[str] = field(default_factory=list) # SPDXID of the Agent/Tool + supplied_by: List[str] = field(default_factory=list) # SPDXID of the Agent/Tool built_time: Optional[datetime] = None release_time: Optional[datetime] = None valid_until_time: Optional[datetime] = None + standard: List[str] = field(default_factory=list) @abstractmethod def __init__(self): diff --git a/src/spdx_tools/spdx3/model/bom.py b/src/spdx_tools/spdx3/model/bom.py index a32614042..7b6c51666 100644 --- a/src/spdx_tools/spdx3/model/bom.py +++ b/src/spdx_tools/spdx3/model/bom.py @@ -25,8 +25,8 @@ def __init__( self, spdx_id: str, creation_info: CreationInformation, - elements: List[str], - root_elements: List[str], + element: List[str], + root_element: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/build/build.py b/src/spdx_tools/spdx3/model/build/build.py index 21da4e261..d9842fbc9 100644 --- a/src/spdx_tools/spdx3/model/build/build.py +++ b/src/spdx_tools/spdx3/model/build/build.py @@ -25,8 +25,8 @@ class Build(Element): config_source_uri: List[str] = field(default_factory=list) config_source_digest: List[Hash] = field(default_factory=list) parameters: Dict[str, str] = field(default_factory=dict) - build_start: Optional[datetime] = None - build_end: Optional[datetime] = None + build_start_time: Optional[datetime] = None + build_end_time: Optional[datetime] = None environment: Dict[str, str] = field(default_factory=dict) def __init__( @@ -47,8 +47,8 @@ def __init__( config_source_uri: List[str] = None, config_source_digest: List[Hash] = None, parameters: Dict[str, str] = None, - build_start: Optional[datetime] = None, - build_end: Optional[datetime] = None, + build_start_time: Optional[datetime] = None, + build_end_time: Optional[datetime] = None, environment: Dict[str, str] = None, ): verified_using = [] if verified_using is None else verified_using diff --git a/src/spdx_tools/spdx3/model/bundle.py b/src/spdx_tools/spdx3/model/bundle.py index e6869cecb..1700ec697 100644 --- a/src/spdx_tools/spdx3/model/bundle.py +++ b/src/spdx_tools/spdx3/model/bundle.py @@ -7,25 +7,25 @@ from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( CreationInformation, + ElementCollection, ExternalIdentifier, ExternalMap, ExternalReference, IntegrityMethod, NamespaceMap, - SpdxCollection, ) @dataclass_with_properties -class Bundle(SpdxCollection): +class Bundle(ElementCollection): context: Optional[str] = None def __init__( self, spdx_id: str, creation_info: CreationInformation, - elements: List[str], - root_elements: List[str], + element: List[str], + root_element: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/creation_information.py b/src/spdx_tools/spdx3/model/creation_information.py index bac8c83f5..45030631b 100644 --- a/src/spdx_tools/spdx3/model/creation_information.py +++ b/src/spdx_tools/spdx3/model/creation_information.py @@ -8,6 +8,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values +from spdx_tools.spdx3.model import ProfileIdentifier @dataclass_with_properties @@ -16,7 +17,7 @@ class CreationInformation: created: datetime created_by: List[str] # SPDXID of Agents created_using: List[str] # SPDXID of Tools - profile: List[str] # or create an Enum for ProfileIdentifier? + profile: List[ProfileIdentifier] data_license: str comment: Optional[str] = None @@ -26,7 +27,7 @@ def __init__( created: datetime, created_by: List[str], created_using: List[str], - profile: List[str], + profile: List[ProfileIdentifier], data_license: str = "CC0", comment: Optional[str] = None, ): diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py index 187540eca..dd74642cd 100644 --- a/src/spdx_tools/spdx3/model/dataset/dataset.py +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -30,13 +30,14 @@ class DatasetAvailabilityType(Enum): @dataclass_with_properties class Dataset(Package): + dataset_type: str = None data_collection_process: Optional[str] = None intended_use: Optional[str] = None dataset_size: Optional[int] = None dataset_noise: Optional[str] = None - data_preprocessing: Optional[str] = None + data_preprocessing: List[str] = field(default_factory=list) sensor: Dict[str, Optional[str]] = field(default_factory=dict) - known_bias: Optional[str] = None + known_bias: List[str] = field(default_factory=list) sensitive_personal_information: Optional[bool] = None anonymization_method_used: List[str] = field(default_factory=list) confidentiality_level: Optional[ConfidentialityLevelType] = None @@ -48,6 +49,12 @@ def __init__( spdx_id: str, creation_info: CreationInformation, name: str, + originated_by: List[str], + download_location: str, + purpose: List[SoftwarePurpose], + built_time: datetime, + release_time: datetime, + dataset_type: str, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, @@ -55,18 +62,15 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, - originated_by: Optional[str] = None, - built_time: Optional[datetime] = None, - release_time: Optional[datetime] = None, + supplied_by: List[str] = None, valid_until_time: Optional[datetime] = None, + standard: List[str] = None, content_identifier: Optional[str] = None, - purpose: List[SoftwarePurpose] = None, concluded_license: Optional[LicenseField] = None, declared_license: Optional[LicenseField] = None, copyright_text: Optional[str] = None, attribution_text: Optional[str] = None, package_version: Optional[str] = None, - download_location: Optional[str] = None, package_url: Optional[str] = None, homepage: Optional[str] = None, source_info: Optional[str] = None, @@ -74,9 +78,9 @@ def __init__( intended_use: Optional[str] = None, dataset_size: Optional[int] = None, dataset_noise: Optional[str] = None, - data_preprocessing: Optional[str] = None, + data_preprocessing: List[str] = None, sensor: Dict[str, Optional[str]] = None, - known_bias: Optional[str] = None, + known_bias: List[str] = None, sensitive_personal_information: Optional[bool] = None, anonymization_method_used: List[str] = None, confidentiality_level: Optional[ConfidentialityLevelType] = None, @@ -86,7 +90,11 @@ def __init__( verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier - purpose = [] if purpose is None else purpose + originated_by = [] if originated_by is None else originated_by + supplied_by = [] if supplied_by is None else supplied_by + standard = [] if standard is None else standard + data_preprocessing = [] if data_preprocessing is None else data_preprocessing sensors = {} if sensor is None else sensor + known_bias = [] if known_bias is None else known_bias anonymization_method_used = [] if anonymization_method_used is None else anonymization_method_used check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py index 7cb5927ad..244eb6951 100644 --- a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py +++ b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py @@ -36,8 +36,8 @@ def __init__( spdx_id: str, creation_info: CreationInformation, from_element: str, - to: List[str], relationship_type: RelationshipType, + to: List[str] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, @@ -51,6 +51,7 @@ def __init__( end_time: Optional[datetime] = None, scope: Optional[LifecycleScopeType] = None, ): + to = [] if to is None else to verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx_tools/spdx3/model/profile_identifier.py b/src/spdx_tools/spdx3/model/profile_identifier.py index e939e791c..7295abfcb 100644 --- a/src/spdx_tools/spdx3/model/profile_identifier.py +++ b/src/spdx_tools/spdx3/model/profile_identifier.py @@ -8,3 +8,9 @@ class ProfileIdentifier(Enum): CORE = auto() SOFTWARE = auto() LICENSING = auto() + SECURITY = auto() + BUILD = auto() + AI = auto() + DATASET = auto() + USAGE = auto() + EXTENSION = auto() diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index 61a73762c..f8522f46d 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from dataclasses import field from datetime import datetime from enum import Enum, auto from typing import List, Optional @@ -87,7 +88,7 @@ class Relationship(Element): # due to the inheritance we need to make all fields non-default in the __annotation__, # the __init__ method still raises an error if required fields are not set from_element: str = None - to: List[str] = None + to: List[str] = field(default_factory=list) relationship_type: RelationshipType = None completeness: Optional[RelationshipCompleteness] = None start_time: Optional[datetime] = None @@ -98,8 +99,8 @@ def __init__( spdx_id: str, creation_info: CreationInformation, from_element: str, - to: List[str], relationship_type: RelationshipType, + to: List[str] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, @@ -112,6 +113,7 @@ def __init__( start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, ): + to = [] if to is None else to verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py index e45d33ac9..372bc698c 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py @@ -7,7 +7,6 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - Agent, CreationInformation, ExternalIdentifier, ExternalReference, @@ -45,7 +44,7 @@ def __init__( end_time: Optional[datetime] = None, assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, - supplied_by: Optional[Agent] = None, + supplied_by: Optional[str] = None, modified_time: Optional[datetime] = None, withdrawn_time: Optional[datetime] = None, severity: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py index 1f913861d..d85dd14f2 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py @@ -7,7 +7,6 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - Agent, CreationInformation, ExternalIdentifier, ExternalReference, @@ -45,7 +44,7 @@ def __init__( end_time: Optional[datetime] = None, assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, - supplied_by: Optional[Agent] = None, + supplied_by: Optional[str] = None, modified_time: Optional[datetime] = None, withdrawn_time: Optional[datetime] = None, severity: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py index 64375a340..4b5c3ea4c 100644 --- a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py @@ -7,7 +7,6 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - Agent, CreationInformation, ExternalIdentifier, ExternalReference, @@ -44,7 +43,7 @@ def __init__( end_time: Optional[datetime] = None, assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, - supplied_by: Optional[Agent] = None, + supplied_by: Optional[str] = None, modified_time: Optional[datetime] = None, withdrawn_time: Optional[datetime] = None, severity: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py index f916220ea..8abc8d85b 100644 --- a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py @@ -8,7 +8,6 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - Agent, CreationInformation, ExternalIdentifier, ExternalReference, @@ -53,7 +52,7 @@ def __init__( end_time: Optional[datetime] = None, assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, - supplied_by: Optional[Agent] = None, + supplied_by: Optional[str] = None, modified_time: Optional[datetime] = None, withdrawn_time: Optional[datetime] = None, ): diff --git a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py index eaf37233a..3505c9d9f 100644 --- a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py @@ -8,7 +8,6 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - Agent, CreationInformation, ExternalIdentifier, ExternalReference, @@ -51,7 +50,7 @@ def __init__( end_time: Optional[datetime] = None, assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, - supplied_by: Optional[Agent] = None, + supplied_by: Optional[str] = None, modified_time: Optional[datetime] = None, withdrawn_time: Optional[datetime] = None, ): diff --git a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py index 61296ea13..0394085fb 100644 --- a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py @@ -8,7 +8,6 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - Agent, CreationInformation, ExternalIdentifier, ExternalReference, @@ -44,7 +43,7 @@ def __init__( end_time: Optional[datetime] = None, assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, - supplied_by: Optional[Agent] = None, + supplied_by: Optional[str] = None, modified_time: Optional[datetime] = None, withdrawn_time: Optional[datetime] = None, vex_version: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py index 5695f7682..f981e7a3c 100644 --- a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py @@ -7,7 +7,6 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - Agent, CreationInformation, ExternalIdentifier, ExternalReference, @@ -40,7 +39,7 @@ def __init__( end_time: Optional[datetime] = None, assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, - supplied_by: Optional[Agent] = None, + supplied_by: Optional[str] = None, modified_time: Optional[datetime] = None, withdrawn_time: Optional[datetime] = None, vex_version: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py index e934aa195..dfb201465 100644 --- a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py @@ -8,7 +8,6 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - Agent, CreationInformation, ExternalIdentifier, ExternalReference, @@ -53,7 +52,7 @@ def __init__( end_time: Optional[datetime] = None, assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, - supplied_by: Optional[Agent] = None, + supplied_by: Optional[str] = None, modified_time: Optional[datetime] = None, withdrawn_time: Optional[datetime] = None, vex_version: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py index def62ce3a..58448a0cd 100644 --- a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py @@ -7,7 +7,6 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - Agent, CreationInformation, ExternalIdentifier, ExternalReference, @@ -40,7 +39,7 @@ def __init__( end_time: Optional[datetime] = None, assessed_element: Optional[str] = None, published_time: Optional[datetime] = None, - supplied_by: Optional[Agent] = None, + supplied_by: Optional[str] = None, modified_time: Optional[datetime] = None, withdrawn_time: Optional[datetime] = None, vex_version: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py index d93befbe2..b97dd0c91 100644 --- a/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py @@ -6,14 +6,14 @@ from typing import Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties -from spdx_tools.spdx3.model import Agent, Relationship +from spdx_tools.spdx3.model import Relationship @dataclass_with_properties class VulnAssessmentRelationship(Relationship): assessed_element: Optional[str] = None # id of the element published_time: Optional[datetime] = None - supplied_by: Optional[Agent] = None + supplied_by: Optional[str] = None modified_time: Optional[datetime] = None withdrawn_time: Optional[datetime] = None diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py index 61e119f74..8f2b67776 100644 --- a/src/spdx_tools/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -28,10 +28,12 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, - originated_by: Optional[str] = None, + originated_by: List[str] = None, + supplied_by: List[str] = None, built_time: Optional[datetime] = None, release_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, + standard: List[str] = None, content_identifier: Optional[str] = None, purpose: List[SoftwarePurpose] = None, concluded_license: Optional[LicenseField] = None, @@ -43,5 +45,8 @@ def __init__( verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier + originated_by = [] if originated_by is None else originated_by + supplied_by = [] if supplied_by is None else supplied_by + standard = [] if standard is None else standard purpose = [] if purpose is None else purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py index bb49a36a2..097e73079 100644 --- a/src/spdx_tools/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -32,10 +32,12 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, - originated_by: Optional[str] = None, + originated_by: List[str] = None, + supplied_by: List[str] = None, built_time: Optional[datetime] = None, release_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, + standard: List[str] = None, content_identifier: Optional[str] = None, purpose: List[SoftwarePurpose] = None, concluded_license: Optional[LicenseField] = None, @@ -51,5 +53,8 @@ def __init__( verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier + originated_by = [] if originated_by is None else originated_by + supplied_by = [] if supplied_by is None else supplied_by + standard = [] if standard is None else standard purpose = [] if purpose is None else purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/sbom.py b/src/spdx_tools/spdx3/model/software/sbom.py index 227d68f74..0b3da591e 100644 --- a/src/spdx_tools/spdx3/model/software/sbom.py +++ b/src/spdx_tools/spdx3/model/software/sbom.py @@ -37,8 +37,8 @@ def __init__( self, spdx_id: str, creation_info: CreationInformation, - elements: List[str], - root_elements: List[str], + element: List[str], + root_element: List[str], name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py index d9f5621e5..f94ffe410 100644 --- a/src/spdx_tools/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -29,10 +29,12 @@ def __init__( external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: None = None, - originated_by: Optional[str] = None, + originated_by: List[str] = None, + supplied_by: List[str] = None, built_time: Optional[datetime] = None, release_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, + standard: List[str] = None, content_identifier: Optional[str] = None, purpose: List[SoftwarePurpose] = None, concluded_license: Optional[LicenseField] = None, @@ -45,5 +47,8 @@ def __init__( verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier + originated_by = [] if originated_by is None else originated_by + supplied_by = [] if supplied_by is None else supplied_by + standard = [] if standard is None else standard purpose = [] if purpose is None else purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py index 9d6243c2f..1ec7781a3 100644 --- a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py +++ b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py @@ -44,8 +44,8 @@ def __init__( spdx_id: str, creation_info: CreationInformation, from_element: str, - to: List[str], relationship_type: RelationshipType, + to: List[str] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, @@ -61,6 +61,7 @@ def __init__( software_linkage: Optional[SoftwareDependencyLinkType] = None, conditionality: Optional[DependencyConditionalityType] = None, ): + to = [] if to is None else to verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier diff --git a/src/spdx_tools/spdx3/model/spdx_collection.py b/src/spdx_tools/spdx3/model/spdx_collection.py index 733604464..fcb05966f 100644 --- a/src/spdx_tools/spdx3/model/spdx_collection.py +++ b/src/spdx_tools/spdx3/model/spdx_collection.py @@ -10,11 +10,11 @@ @dataclass_with_properties -class SpdxCollection(Element): +class ElementCollection(Element): # due to the inheritance we need to make all fields non-default in the __annotation__, # the __init__ method still raises an error if required fields are not set - elements: List[str] = field(default_factory=list) - root_elements: List[str] = field(default_factory=list) + element: List[str] = field(default_factory=list) + root_element: List[str] = field(default_factory=list) namespaces: List[NamespaceMap] = field(default_factory=list) imports: List[ExternalMap] = field(default_factory=list) diff --git a/src/spdx_tools/spdx3/model/spdx_document.py b/src/spdx_tools/spdx3/model/spdx_document.py index 6939e5d22..0bd0ee1a2 100644 --- a/src/spdx_tools/spdx3/model/spdx_document.py +++ b/src/spdx_tools/spdx3/model/spdx_document.py @@ -26,8 +26,8 @@ def __init__( spdx_id: str, creation_info: CreationInformation, name: str, - elements: List[str], - root_elements: List[str], + element: List[str], + root_element: List[str], summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/writer/console/creation_information_writer.py b/src/spdx_tools/spdx3/writer/console/creation_information_writer.py index e935dcd97..ba68f4934 100644 --- a/src/spdx_tools/spdx3/writer/console/creation_information_writer.py +++ b/src/spdx_tools/spdx3/writer/console/creation_information_writer.py @@ -16,6 +16,6 @@ def write_creation_info(creation_info: CreationInformation, text_output: TextIO, write_value("created by", created_by, text_output, indent) for created_using in creation_info.created_using: write_value("created using", created_using, text_output, indent) - write_value("profile", creation_info.profile, text_output, indent) + write_value("profile", [profile.name for profile in creation_info.profile], text_output, indent) write_value("data license", creation_info.data_license, text_output, indent) write_value("comment", creation_info.comment, text_output, indent) diff --git a/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py b/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py index c34dcdb5e..242cae7bb 100644 --- a/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py +++ b/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py @@ -3,16 +3,16 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model import SpdxCollection +from spdx_tools.spdx3.model import ElementCollection from spdx_tools.spdx3.writer.console.element_writer import write_element_properties from spdx_tools.spdx3.writer.console.external_map_writer import write_external_map from spdx_tools.spdx3.writer.console.namespace_map_writer import write_namespace_map from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_optional_heading -def write_collection(collection: SpdxCollection, text_output: TextIO): +def write_collection(collection: ElementCollection, text_output: TextIO): write_element_properties(collection, text_output) - text_output.write(f"elements: {', '.join(collection.elements)}\n") + text_output.write(f"elements: {', '.join(collection.element)}\n") write_optional_heading(collection.namespaces, "# Namespaces\n", text_output) for namespace_map in collection.namespaces: write_namespace_map(namespace_map, text_output) diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index af01149f7..d995b992a 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -13,6 +13,7 @@ ExternalIdentifierType, Organization, Person, + ProfileIdentifier, Tool, ) from spdx_tools.spdx3.payload import Payload @@ -36,7 +37,9 @@ def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_id): payload = Payload() document_namespace = "https://doc.namespace" - creation_info = CreationInformation(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], ["core"]) + creation_info = CreationInformation( + Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], [ProfileIdentifier.CORE] + ) actor = Actor(actor_type, actor_name, actor_mail) agent_or_tool_id = bump_actor(actor, payload, creation_info, document_namespace) @@ -53,8 +56,12 @@ def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_i def test_bump_actor_that_already_exists(): - creation_info_old = CreationInformation(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], ["core"]) - creation_info_new = CreationInformation(Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], [], ["core"]) + creation_info_old = CreationInformation( + Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], [ProfileIdentifier.CORE] + ) + creation_info_new = CreationInformation( + Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], [], [ProfileIdentifier.CORE] + ) name = "some name" document_namespace = "https://doc.namespace" diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index f0d68c7c3..96bf7321d 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -19,9 +19,9 @@ @pytest.mark.parametrize( "originator, expected_originator", [ - (actor_fixture(name="originatorName"), "https://doc.namespace#SPDXRef-Actor-originatorName-some@mail.com"), - (None, None), - (SpdxNoAssertion(), None), + (actor_fixture(name="originatorName"), ["https://doc.namespace#SPDXRef-Actor-originatorName-some@mail.com"]), + (None, []), + (SpdxNoAssertion(), []), ], ) @mock.patch("spdx_tools.spdx3.model.CreationInformation") diff --git a/tests/spdx3/bump/test_relationship_bump.py b/tests/spdx3/bump/test_relationship_bump.py index 79143497e..b6ca94365 100644 --- a/tests/spdx3/bump/test_relationship_bump.py +++ b/tests/spdx3/bump/test_relationship_bump.py @@ -21,8 +21,8 @@ def test_relationship_bump(creation_info): f"{document_namespace}#SPDXRef-Relationship-1", creation_info, spdx2_relationship.spdx_element_id, - [spdx2_relationship.related_spdx_element_id], RelationshipType.DESCRIBES, + [spdx2_relationship.related_spdx_element_id], comment=spdx2_relationship.comment, ) @@ -41,8 +41,8 @@ def test_relationships_bump(creation_info): f"{document_namespace}#SPDXRef-Relationship-1", creation_info, relationships[0].spdx_element_id, - [relationships[0].related_spdx_element_id, relationships[1].related_spdx_element_id], RelationshipType.DESCRIBES, + [relationships[0].related_spdx_element_id, relationships[1].related_spdx_element_id], ) @@ -65,8 +65,8 @@ def test_relationships_bump_with_setting_completeness(creation_info): f"{document_namespace}#SPDXRef-Relationship-0", creation_info, relationships[0].spdx_element_id, - [], RelationshipType.DESCRIBES, + [], comment=relationships[0].comment, completeness=RelationshipCompleteness.NOASSERTION, ) @@ -74,16 +74,16 @@ def test_relationships_bump_with_setting_completeness(creation_info): f"{document_namespace}#SPDXRef-Relationship-1", creation_info, relationships[1].spdx_element_id, - [relationships[1].related_spdx_element_id], RelationshipType.DESCRIBES, + [relationships[1].related_spdx_element_id], comment=relationships[1].comment, ) assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-2") == Relationship( f"{document_namespace}#SPDXRef-Relationship-2", creation_info, relationships[2].spdx_element_id, - [], RelationshipType.SPECIFICATION_FOR, + [], completeness=RelationshipCompleteness.COMPLETE, ) diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 723f2bba0..24be1fc3e 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -170,8 +170,8 @@ def bom_fixture( return Bom( spdx_id=spdx_id, creation_info=creation_info, - elements=elements, - root_elements=root_elements, + element=elements, + root_element=root_elements, name=name, summary=summary, description=description, @@ -211,8 +211,8 @@ def bundle_fixture( return Bundle( spdx_id=spdx_id, creation_info=creation_info, - elements=elements, - root_elements=root_elements, + element=elements, + root_element=root_elements, name=name, summary=summary, description=description, @@ -377,8 +377,8 @@ def spdx_document_fixture( spdx_id=spdx_id, creation_info=creation_info, name=name, - elements=elements, - root_elements=root_elements, + element=elements, + root_element=root_elements, summary=summary, description=description, comment=comment, diff --git a/tests/spdx3/model/ai/test_ai_package.py b/tests/spdx3/model/ai/test_ai_package.py index 61c272ba7..d7b1c2c75 100644 --- a/tests/spdx3/model/ai/test_ai_package.py +++ b/tests/spdx3/model/ai/test_ai_package.py @@ -1,12 +1,14 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime from unittest import mock import pytest from spdx_tools.spdx3.model.ai import AIPackage from spdx_tools.spdx3.model.ai.ai_package import SafetyRiskAssessmentType +from spdx_tools.spdx3.model.software import SoftwarePurpose @mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) @@ -15,6 +17,11 @@ def test_correct_initialization(creation_information): "some_spdx_id", creation_information, "AI Package name", + ["https://namespace.test#supplier"], + "https://download.test", + "1.2:rc2", + [SoftwarePurpose.SOURCE], + datetime(12, 5, 23, 11), energy_consumption="energy consumption", standard_compliance=["some standard"], limitation="limitation", @@ -22,8 +29,8 @@ def test_correct_initialization(creation_information): information_about_training="training info", information_about_application="app info", hyperparameter={"param": "value"}, - model_data_preprocessing="preprocessing steps", - model_explainability="mechanism", + model_data_preprocessing=["preprocessing steps"], + model_explainability=["mechanism"], sensitive_personal_information=True, metric_decision_threshold={"metric1": "threshold", "metric2": None}, metric={"metric1": "value1", "metric2": None}, @@ -32,6 +39,11 @@ def test_correct_initialization(creation_information): safety_risk_assessment=SafetyRiskAssessmentType.HIGH, ) + assert ai_package.supplied_by == ["https://namespace.test#supplier"] + assert ai_package.download_location == "https://download.test" + assert ai_package.package_version == "1.2:rc2" + assert ai_package.purpose == [SoftwarePurpose.SOURCE] + assert ai_package.release_time == datetime(12, 5, 23, 11) assert ai_package.energy_consumption == "energy consumption" assert ai_package.standard_compliance == ["some standard"] assert ai_package.limitation == "limitation" @@ -39,8 +51,8 @@ def test_correct_initialization(creation_information): assert ai_package.information_about_training == "training info" assert ai_package.information_about_application == "app info" assert ai_package.hyperparameter == {"param": "value"} - assert ai_package.model_data_preprocessing == "preprocessing steps" - assert ai_package.model_explainability == "mechanism" + assert ai_package.model_data_preprocessing == ["preprocessing steps"] + assert ai_package.model_explainability == ["mechanism"] assert ai_package.sensitive_personal_information assert ai_package.metric_decision_threshold == {"metric1": "threshold", "metric2": None} assert ai_package.metric == {"metric1": "value1", "metric2": None} @@ -56,6 +68,11 @@ def test_invalid_initialization(creation_information): "some_spdx_id", creation_information, "AI Package name", + ["https://namespace.test#supplier"], + "https://download.test", + "1.2:rc2", + [SoftwarePurpose.SOURCE], + datetime(12, 5, 23, 11), metric={"metric1": "value", "metric2": 250}, ) diff --git a/tests/spdx3/model/build/test_build.py b/tests/spdx3/model/build/test_build.py index 2e6e38b1c..a3b1ddfec 100644 --- a/tests/spdx3/model/build/test_build.py +++ b/tests/spdx3/model/build/test_build.py @@ -21,8 +21,8 @@ def test_correct_initialization(creation_information): config_source_uri=["uri"], config_source_digest=[Hash(HashAlgorithm.MD2, "abcdef")], parameters={"param1": "value1"}, - build_start=datetime(2023, 1, 1), - build_end=datetime(2023, 2, 2), + build_start_time=datetime(2023, 1, 1), + build_end_time=datetime(2023, 2, 2), environment={"param2": "value2"}, ) @@ -32,8 +32,8 @@ def test_correct_initialization(creation_information): assert build.config_source_uri == ["uri"] assert build.config_source_digest == [Hash(HashAlgorithm.MD2, "abcdef")] assert build.parameters == {"param1": "value1"} - assert build.build_start == datetime(2023, 1, 1) - assert build.build_end == datetime(2023, 2, 2) + assert build.build_start_time == datetime(2023, 1, 1) + assert build.build_end_time == datetime(2023, 2, 2) assert build.environment == {"param2": "value2"} diff --git a/tests/spdx3/model/dataset/test_dataset.py b/tests/spdx3/model/dataset/test_dataset.py index da2f2b477..663d0e862 100644 --- a/tests/spdx3/model/dataset/test_dataset.py +++ b/tests/spdx3/model/dataset/test_dataset.py @@ -1,11 +1,13 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from datetime import datetime from unittest import mock import pytest from spdx_tools.spdx3.model.dataset import ConfidentialityLevelType, Dataset, DatasetAvailabilityType +from spdx_tools.spdx3.model.software import SoftwarePurpose @mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) @@ -14,13 +16,19 @@ def test_correct_initialization(creation_information): "some_spdx_id", creation_information, "Dataset name", + ["https://namespace.test#originator"], + "https://download.test", + [SoftwarePurpose.DATA], + datetime(10, 5, 23, 11), + datetime(11, 5, 24, 12), + "training data", data_collection_process="data collection process", intended_use="intended use", dataset_size=420000, dataset_noise="dataset noise", - data_preprocessing="data preprocessing steps", + data_preprocessing=["data preprocessing steps"], sensor={"sensor1": "some value"}, - known_bias="known biases", + known_bias=["known biases"], sensitive_personal_information=True, anonymization_method_used=["anonymization method"], confidentiality_level=ConfidentialityLevelType.RED, @@ -28,13 +36,19 @@ def test_correct_initialization(creation_information): dataset_availability=DatasetAvailabilityType.QUERY, ) + assert dataset.originated_by == ["https://namespace.test#originator"] + assert dataset.download_location == "https://download.test" + assert dataset.purpose == [SoftwarePurpose.DATA] + assert dataset.built_time == datetime(10, 5, 23, 11) + assert dataset.release_time == datetime(11, 5, 24, 12) + assert dataset.dataset_type == "training data" assert dataset.data_collection_process == "data collection process" assert dataset.intended_use == "intended use" assert dataset.dataset_size == 420000 assert dataset.dataset_noise == "dataset noise" - assert dataset.data_preprocessing == "data preprocessing steps" + assert dataset.data_preprocessing == ["data preprocessing steps"] assert dataset.sensor == {"sensor1": "some value"} - assert dataset.known_bias == "known biases" + assert dataset.known_bias == ["known biases"] assert dataset.sensitive_personal_information assert dataset.anonymization_method_used == ["anonymization method"] assert dataset.confidentiality_level == ConfidentialityLevelType.RED @@ -49,6 +63,12 @@ def test_invalid_initialization(creation_information): "some_spdx_id", creation_information, "Dataset name", + ["https://namespace.test#originator"], + "https://download.test", + [SoftwarePurpose.DATA], + datetime(10, 5, 23, 11), + datetime(11, 5, 24, 12), + "training data", sensor={"sensor1": "value", "sensor2": 250}, ) diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index fd59b9762..0b9b465c6 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -16,9 +16,12 @@ def test_correct_initialization(creation_information): creation_information, "Test package", content_identifier="https://any.uri", + originated_by=["https://namespace.test#originator"], + supplied_by=["https://namespace.test#supplier"], built_time=datetime(2022, 1, 1), release_time=datetime(2022, 1, 2), valid_until_time=datetime(2022, 1, 3), + standard=["ISO"], purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH], package_version="1:23a_bc", download_location="https://downloadlocation", @@ -31,9 +34,12 @@ def test_correct_initialization(creation_information): assert package.creation_info == creation_information assert package.name == "Test package" assert package.content_identifier == "https://any.uri" + assert package.originated_by == ["https://namespace.test#originator"] + assert package.supplied_by == ["https://namespace.test#supplier"] assert package.built_time == datetime(2022, 1, 1) assert package.release_time == datetime(2022, 1, 2) assert package.valid_until_time == datetime(2022, 1, 3) + assert package.standard == ["ISO"] assert package.purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH] assert package.package_version == "1:23a_bc" assert package.download_location == "https://downloadlocation" diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index 9a8a889ef..2a1218872 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -13,25 +13,25 @@ def test_correct_initialization(creation_information): sbom = Sbom( "SPDXRef-Sbom", creation_information, - elements=["spdx_id1", "spdx_id2"], - root_elements=["spdx_id3"], + element=["spdx_id1", "spdx_id2"], + root_element=["spdx_id3"], sbom_type=[SBOMType.DESIGN], ) assert sbom.spdx_id == "SPDXRef-Sbom" assert sbom.creation_info == creation_information - assert sbom.elements == ["spdx_id1", "spdx_id2"] - assert sbom.root_elements == ["spdx_id3"] + assert sbom.element == ["spdx_id1", "spdx_id2"] + assert sbom.root_element == ["spdx_id3"] assert sbom.sbom_type == [SBOMType.DESIGN] def test_invalid_initialization(): with pytest.raises(TypeError) as err: - Sbom(2, {"creation_info": [3, 4, 5]}, elements=[], root_elements=[]) + Sbom(2, {"creation_info": [3, 4, 5]}, element=[], root_element=[]) assert err.value.args[0] == [ 'SetterError Sbom: type of argument "spdx_id" must be str; got int instead: 2', 'SetterError Sbom: type of argument "creation_info" must be ' - "spdx_tools.spdx3.model.creation_information.CreationInformation; got dict instead: " - "{'creation_info': [3, 4, 5]}", + "spdx_tools.spdx3.model.creation_information.CreationInformation; got dict " + "instead: {'creation_info': [3, 4, 5]}", ] diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index d6c5599f7..ae123bb4c 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -34,7 +34,7 @@ def test_invalid_initialization(creation_information): assert err.value.args[0] == [ 'SetterError Snippet: type of argument "spdx_id" must be str; got int ' "instead: 2", - 'SetterError Snippet: type of argument "originated_by" must be one of (str, ' "NoneType); got int instead: 34", + 'SetterError Snippet: type of argument "originated_by" must be a list; got ' "int instead: 34", 'SetterError Snippet: type of argument "byte_range" must be one of ' "(Tuple[int, int], NoneType); got str instead: 34:45", ] diff --git a/tests/spdx3/model/software/test_software_dependency_relationship.py b/tests/spdx3/model/software/test_software_dependency_relationship.py index 71ebc3931..6c1a4472b 100644 --- a/tests/spdx3/model/software/test_software_dependency_relationship.py +++ b/tests/spdx3/model/software/test_software_dependency_relationship.py @@ -20,8 +20,8 @@ def test_correct_initialization(creation_information): "SPDXRef-Relationship", creation_information, "spdx_id1", - ["spdx_id2", "spdx_id3"], RelationshipType.DESCRIBES, + ["spdx_id2", "spdx_id3"], completeness=RelationshipCompleteness.NOASSERTION, start_time=datetime(11, 11, 11), end_time=datetime(12, 12, 12), @@ -50,8 +50,8 @@ def test_invalid_initialization(creation_information): "SPDXRef-Relationship", creation_information, "spdx_id1", - 42, RelationshipType.DESCRIBES, + 42, ) assert err.value.args[0] == [ diff --git a/tests/spdx3/model/test_abstract_classes.py b/tests/spdx3/model/test_abstract_classes.py index 39e45a46a..b6217e2e5 100644 --- a/tests/spdx3/model/test_abstract_classes.py +++ b/tests/spdx3/model/test_abstract_classes.py @@ -3,10 +3,10 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx_tools.spdx3.model import Artifact, Element, IntegrityMethod, SpdxCollection +from spdx_tools.spdx3.model import Artifact, Element, ElementCollection, IntegrityMethod -@pytest.mark.parametrize("abstract_class", [Element, Artifact, SpdxCollection, IntegrityMethod]) +@pytest.mark.parametrize("abstract_class", [Element, Artifact, ElementCollection, IntegrityMethod]) def test_initialization_throws_error(abstract_class): with pytest.raises(TypeError) as err: abstract_class() diff --git a/tests/spdx3/model/test_agent.py b/tests/spdx3/model/test_agent.py index ed057c4da..2c1618b73 100644 --- a/tests/spdx3/model/test_agent.py +++ b/tests/spdx3/model/test_agent.py @@ -13,6 +13,7 @@ ExternalIdentifierType, Organization, Person, + ProfileIdentifier, SoftwareAgent, ) @@ -21,13 +22,15 @@ def test_correct_initialization(agent_class): agent = agent_class( "SPDXRef-Agent", - CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0"), + CreationInformation( + Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], [ProfileIdentifier.CORE], "CC0" + ), external_identifier=[ExternalIdentifier(ExternalIdentifierType.EMAIL, "some@mail.com")], ) assert agent.spdx_id == "SPDXRef-Agent" assert agent.creation_info == CreationInformation( - Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0" + Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], [ProfileIdentifier.CORE], "CC0" ) assert agent.external_identifier == [ExternalIdentifier(ExternalIdentifierType.EMAIL, "some@mail.com")] @@ -38,7 +41,8 @@ def test_invalid_initialization(agent_class): agent_class(12, 345) assert err.value.args[0] == [ - f'SetterError {agent_class.__name__}: type of argument "spdx_id" must be str; got int instead: 12', + f'SetterError {agent_class.__name__}: type of argument "spdx_id" must be str; got int instead: ' "12", f'SetterError {agent_class.__name__}: type of argument "creation_info" must be ' - "spdx_tools.spdx3.model.creation_information.CreationInformation; got int instead: 345", + "spdx_tools.spdx3.model.creation_information.CreationInformation; got int " + "instead: 345", ] diff --git a/tests/spdx3/model/test_annotation.py b/tests/spdx3/model/test_annotation.py index f951fd671..5a98a09b6 100644 --- a/tests/spdx3/model/test_annotation.py +++ b/tests/spdx3/model/test_annotation.py @@ -15,7 +15,7 @@ def test_correct_initialization(creation_information): creation_information, AnnotationType.OTHER, "spdx_id1", - content_type="mediaType", + content_type=["mediaType"], statement="This is a statement", ) @@ -23,7 +23,7 @@ def test_correct_initialization(creation_information): assert annotation.creation_info == creation_information assert annotation.annotation_type == AnnotationType.OTHER assert annotation.subject == "spdx_id1" - assert annotation.content_type == "mediaType" + assert annotation.content_type == ["mediaType"] assert annotation.statement == "This is a statement" @@ -43,8 +43,7 @@ def test_invalid_initialization(creation_information): 'SetterError Annotation: type of argument "annotation_type" must be ' "spdx_tools.spdx3.model.annotation.AnnotationType; got str instead: REVIEW", 'SetterError Annotation: type of argument "subject" must be str; got dict ' "instead: {'element': 1}", - 'SetterError Annotation: type of argument "content_type" must be one of (str, ' - "NoneType); got int instead: 4", + 'SetterError Annotation: type of argument "content_type" must be a list; got ' "int instead: 4", 'SetterError Annotation: type of argument "statement" must be one of (str, ' "NoneType); got list instead: ['some statements']", ] diff --git a/tests/spdx3/model/test_bom.py b/tests/spdx3/model/test_bom.py index 0c897d841..c2d1c3191 100644 --- a/tests/spdx3/model/test_bom.py +++ b/tests/spdx3/model/test_bom.py @@ -11,22 +11,22 @@ @mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_correct_initialization(creation_information): - bom = Bom("SPDXRef-Bom", creation_information, elements=["spdx_id1"], root_elements=["spdx_id2"]) + bom = Bom("SPDXRef-Bom", creation_information, element=["spdx_id1"], root_element=["spdx_id2"]) assert bom.spdx_id == "SPDXRef-Bom" assert bom.creation_info == creation_information - assert bom.elements == ["spdx_id1"] - assert bom.root_elements == ["spdx_id2"] + assert bom.element == ["spdx_id1"] + assert bom.root_element == ["spdx_id2"] def test_invalid_initialization(): with pytest.raises(TypeError) as err: - Bom(1, "Creation Information", elements=[5], root_elements=[]) + Bom(1, "Creation Information", element=[5], root_element=[]) assert err.value.args[0] == [ 'SetterError Bom: type of argument "spdx_id" must be str; got int instead: 1', 'SetterError Bom: type of argument "creation_info" must be ' - "spdx_tools.spdx3.model.creation_information.CreationInformation; got str instead: " - "Creation Information", - 'SetterError Bom: type of argument "elements"[0] must be ' "str; got int instead: [5]", + "spdx_tools.spdx3.model.creation_information.CreationInformation; got str " + "instead: Creation Information", + 'SetterError Bom: type of argument "element"[0] must be str; got int instead: ' "[5]", ] diff --git a/tests/spdx3/model/test_bundle.py b/tests/spdx3/model/test_bundle.py index 6071985b9..ea525ac14 100644 --- a/tests/spdx3/model/test_bundle.py +++ b/tests/spdx3/model/test_bundle.py @@ -14,16 +14,16 @@ def test_correct_initialization(creation_information, namespace): bundle = Bundle( "SPDXRef-Bundle", creation_information, - elements=["spdx_id1"], - root_elements=["spdx_id2"], + element=["spdx_id1"], + root_element=["spdx_id2"], namespaces=[namespace], context="context", ) assert bundle.spdx_id == "SPDXRef-Bundle" assert bundle.creation_info == creation_information - assert bundle.elements == ["spdx_id1"] - assert bundle.root_elements == ["spdx_id2"] + assert bundle.element == ["spdx_id1"] + assert bundle.root_element == ["spdx_id2"] assert bundle.context == "context" assert bundle.namespaces == [namespace] @@ -31,12 +31,12 @@ def test_correct_initialization(creation_information, namespace): @mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: - Bundle(4, creation_information, elements="spdx_id1", root_elements=[42], namespaces=True, context=["yes"]) + Bundle(4, creation_information, element="spdx_id1", root_element=[42], namespaces=True, context=["yes"]) assert err.value.args[0] == [ 'SetterError Bundle: type of argument "spdx_id" must be str; got int instead: 4', - 'SetterError Bundle: type of argument "elements" must be a list; got str ' "instead: spdx_id1", - 'SetterError Bundle: type of argument "root_elements"[0] must be str; got int ' "instead: [42]", + 'SetterError Bundle: type of argument "element" must be a list; got str ' "instead: spdx_id1", + 'SetterError Bundle: type of argument "root_element"[0] must be str; got int ' "instead: [42]", 'SetterError Bundle: type of argument "namespaces" must be a list; ' "got bool instead: True", 'SetterError Bundle: type of argument "context" must be one of (str, ' "NoneType); got list instead: ['yes']", ] diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py index 1c6ed1cba..240348cc4 100644 --- a/tests/spdx3/model/test_creation_information.py +++ b/tests/spdx3/model/test_creation_information.py @@ -6,19 +6,25 @@ import pytest from semantic_version import Version -from spdx_tools.spdx3.model import CreationInformation +from spdx_tools.spdx3.model import CreationInformation, ProfileIdentifier def test_correct_initialization(): creation_information = CreationInformation( - Version("3.0.0"), datetime(2023, 1, 11, 16, 21), [], [], ["core", "software"], "CC0", "some comment" + Version("3.0.0"), + datetime(2023, 1, 11, 16, 21), + [], + [], + [ProfileIdentifier.CORE, ProfileIdentifier.SOFTWARE], + "CC0", + "some comment", ) assert creation_information.spec_version == Version("3.0.0") assert creation_information.created == datetime(2023, 1, 11, 16, 21) assert creation_information.created_by == [] assert creation_information.created_using == [] - assert creation_information.profile == ["core", "software"] + assert creation_information.profile == [ProfileIdentifier.CORE, ProfileIdentifier.SOFTWARE] assert creation_information.data_license == "CC0" assert creation_information.comment == "some comment" diff --git a/tests/spdx3/model/test_lifecycle_scoped_relationship.py b/tests/spdx3/model/test_lifecycle_scoped_relationship.py index 00c1adeee..00e8a82fd 100644 --- a/tests/spdx3/model/test_lifecycle_scoped_relationship.py +++ b/tests/spdx3/model/test_lifecycle_scoped_relationship.py @@ -20,8 +20,8 @@ def test_correct_initialization(creation_information): "SPDXRef-Relationship", creation_information, "spdx_id1", - ["spdx_id2", "spdx_id3"], RelationshipType.DESCRIBES, + ["spdx_id2", "spdx_id3"], completeness=RelationshipCompleteness.NOASSERTION, start_time=datetime(11, 11, 11), end_time=datetime(12, 12, 12), @@ -46,8 +46,8 @@ def test_invalid_initialization(creation_information): "SPDXRef-Relationship", creation_information, "spdx_id1", - 42, RelationshipType.DESCRIBES, + 42, ) assert err.value.args[0] == [ diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py index 64743de0b..471d1cd79 100644 --- a/tests/spdx3/model/test_relationship.py +++ b/tests/spdx3/model/test_relationship.py @@ -15,8 +15,8 @@ def test_correct_initialization(creation_information): "SPDXRef-Relationship", creation_information, "spdx_id1", - ["spdx_id2", "spdx_id3"], RelationshipType.DESCRIBES, + ["spdx_id2", "spdx_id3"], completeness=RelationshipCompleteness.NOASSERTION, start_time=datetime(11, 11, 11), end_time=datetime(12, 12, 12), @@ -35,7 +35,7 @@ def test_correct_initialization(creation_information): @mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: - Relationship("SPDXRef-Relationship", creation_information, 42, 5, "Relationshiptype", completeness=True) + Relationship("SPDXRef-Relationship", creation_information, 42, "Relationshiptype", 5, completeness=True) assert err.value.args[0] == [ 'SetterError Relationship: type of argument "from_element" must be ' "str; got int instead: 42", diff --git a/tests/spdx3/model/test_spdx_document.py b/tests/spdx3/model/test_spdx_document.py index d5a1f2cba..95d1da741 100644 --- a/tests/spdx3/model/test_spdx_document.py +++ b/tests/spdx3/model/test_spdx_document.py @@ -11,26 +11,26 @@ @mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_correct_initialization(creation_information): spdx_document = SpdxDocument( - "SPDXRef-DOCUMENT", creation_information, "Test document", elements=["spdx_id1"], root_elements=["spdx_id2"] + "SPDXRef-DOCUMENT", creation_information, "Test document", element=["spdx_id1"], root_element=["spdx_id2"] ) assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" assert spdx_document.creation_info == creation_information assert spdx_document.name == "Test document" - assert spdx_document.elements == ["spdx_id1"] - assert spdx_document.root_elements == ["spdx_id2"] + assert spdx_document.element == ["spdx_id1"] + assert spdx_document.root_element == ["spdx_id2"] def test_invalid_initialization(): with pytest.raises(TypeError) as err: - SpdxDocument(1, {"info": 5}, "document name", elements=[8], root_elements=[]) + SpdxDocument(1, {"info": 5}, "document name", element=[8], root_element=[]) assert err.value.args[0] == [ 'SetterError SpdxDocument: type of argument "spdx_id" must be str; got int ' "instead: 1", 'SetterError SpdxDocument: type of argument "creation_info" must be ' - "spdx_tools.spdx3.model.creation_information.CreationInformation; got dict instead: " - "{'info': 5}", - 'SetterError SpdxDocument: type of argument "elements"[0] must be ' "str; got int instead: [8]", + "spdx_tools.spdx3.model.creation_information.CreationInformation; got dict " + "instead: {'info': 5}", + 'SetterError SpdxDocument: type of argument "element"[0] must be str; got int ' "instead: [8]", ] @@ -40,6 +40,6 @@ def test_incomplete_initialization(creation_information): SpdxDocument("SPDXRef-Document", creation_information) assert ( - "__init__() missing 3 required positional arguments: 'name', 'elements', and 'root_elements'" + "__init__() missing 3 required positional arguments: 'name', 'element', and 'root_element'" in err.value.args[0] ) diff --git a/tests/spdx3/model/test_tool.py b/tests/spdx3/model/test_tool.py index 1820c7c6e..d619bfa67 100644 --- a/tests/spdx3/model/test_tool.py +++ b/tests/spdx3/model/test_tool.py @@ -6,18 +6,20 @@ import pytest from semantic_version import Version -from spdx_tools.spdx3.model import CreationInformation, Tool +from spdx_tools.spdx3.model import CreationInformation, ProfileIdentifier, Tool def test_correct_initialization(): agent = Tool( "SPDXRef-Tool", - CreationInformation(Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0"), + CreationInformation( + Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], [ProfileIdentifier.CORE], "CC0" + ), ) assert agent.spdx_id == "SPDXRef-Tool" assert agent.creation_info == CreationInformation( - Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], ["core"], "CC0" + Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], [ProfileIdentifier.CORE], "CC0" ) @@ -26,7 +28,8 @@ def test_invalid_initialization(): Tool(12, 345) assert err.value.args[0] == [ - 'SetterError Tool: type of argument "spdx_id" must be str; got int instead: 12', + 'SetterError Tool: type of argument "spdx_id" must be str; got int instead: ' "12", 'SetterError Tool: type of argument "creation_info" must be ' - "spdx_tools.spdx3.model.creation_information.CreationInformation; got int instead: 345", + "spdx_tools.spdx3.model.creation_information.CreationInformation; got int " + "instead: 345", ] From cdaec56119488ea513e8194883f945a34676806b Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 10 May 2023 12:18:39 +0200 Subject: [PATCH 212/354] implement review comments - bump package supplier Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/bump_from_spdx2/package.py | 7 +++++-- tests/spdx3/bump/test_package_bump.py | 17 ++++++++++++----- tests/spdx3/bump/test_spdx_document_bump.py | 2 +- tests/spdx3/model/test_tool.py | 5 ++--- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index a47c7847c..75f10c50d 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -34,8 +34,10 @@ def bump_package( download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") # package.file_name -> ? print_missing_conversion("package2.file_name", 0, "https://github.com/spdx/spdx-3-model/issues/83") - # package.supplier -> Relationship, suppliedBy? - print_missing_conversion("package2.supplier", 0, "https://github.com/spdx/spdx-3-model/issues/113") + if isinstance(spdx2_package.supplier, Spdx2_Actor): + supplied_by_spdx_id = [bump_actor(spdx2_package.supplier, payload, creation_information, document_namespace)] + else: + supplied_by_spdx_id = None if isinstance(spdx2_package.originator, Spdx2_Actor): originated_by_spdx_id = [ bump_actor(spdx2_package.originator, payload, creation_information, document_namespace) @@ -101,6 +103,7 @@ def bump_package( external_references=external_references, external_identifier=external_identifiers, originated_by=originated_by_spdx_id, + supplied_by=supplied_by_spdx_id, built_time=spdx2_package.built_date, release_time=spdx2_package.release_date, valid_until_time=spdx2_package.valid_until_date, diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 96bf7321d..002fc7d63 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -17,19 +17,25 @@ @pytest.mark.parametrize( - "originator, expected_originator", + "originator, expected_originator, supplier, expected_supplier", [ - (actor_fixture(name="originatorName"), ["https://doc.namespace#SPDXRef-Actor-originatorName-some@mail.com"]), - (None, []), - (SpdxNoAssertion(), []), + ( + actor_fixture(name="originatorName"), + ["https://doc.namespace#SPDXRef-Actor-originatorName-some@mail.com"], + actor_fixture(name="supplierName"), + ["https://doc.namespace#SPDXRef-Actor-supplierName-some@mail.com"], + ), + (None, [], None, []), + (SpdxNoAssertion(), [], SpdxNoAssertion(), []), ], ) @mock.patch("spdx_tools.spdx3.model.CreationInformation") -def test_bump_package(creation_information, originator, expected_originator): +def test_bump_package(creation_information, originator, expected_originator, supplier, expected_supplier): payload = Payload() document_namespace = "https://doc.namespace" spdx2_package: Spdx2_Package = package_fixture( originator=originator, + supplier=supplier, external_references=[ ExternalPackageRef( ExternalPackageRefCategory.SECURITY, "advisory", "advisory_locator", "advisory_comment" @@ -54,6 +60,7 @@ def test_bump_package(creation_information, originator, expected_originator): assert package.download_location == spdx2_package.download_location assert package.package_version == spdx2_package.version assert package.originated_by == expected_originator + assert package.supplied_by == expected_supplier assert package.homepage == spdx2_package.homepage assert package.source_info == spdx2_package.source_info assert package.built_time == spdx2_package.built_date diff --git a/tests/spdx3/bump/test_spdx_document_bump.py b/tests/spdx3/bump/test_spdx_document_bump.py index f6a1df4fb..14a165381 100644 --- a/tests/spdx3/bump/test_spdx_document_bump.py +++ b/tests/spdx3/bump/test_spdx_document_bump.py @@ -21,7 +21,7 @@ def test_bump_spdx_document(): write_payload(payload, sys.stdout) assert f"{document_namespace}#SPDXRef-Package" in payload.get_full_map() - assert len(payload.get_full_map()) == 10 + assert len(payload.get_full_map()) == 11 # this is more of a temporary test to make sure the dates don't get messed up again assert ( diff --git a/tests/spdx3/model/test_tool.py b/tests/spdx3/model/test_tool.py index d619bfa67..3c058fbbd 100644 --- a/tests/spdx3/model/test_tool.py +++ b/tests/spdx3/model/test_tool.py @@ -28,8 +28,7 @@ def test_invalid_initialization(): Tool(12, 345) assert err.value.args[0] == [ - 'SetterError Tool: type of argument "spdx_id" must be str; got int instead: ' "12", + 'SetterError Tool: type of argument "spdx_id" must be str; got int instead: 12', 'SetterError Tool: type of argument "creation_info" must be ' - "spdx_tools.spdx3.model.creation_information.CreationInformation; got int " - "instead: 345", + "spdx_tools.spdx3.model.creation_information.CreationInformation; got int instead: 345", ] From 2a6b8af23873ed05d8a5eb91e16e8547cb458402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 10 May 2023 09:31:59 +0200 Subject: [PATCH 213/354] [issue-432] rework SPDX3 Core fixtures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx3/fixtures.py | 377 ++++++++++++++++++++++------------------ 1 file changed, 211 insertions(+), 166 deletions(-) diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 24be1fc3e..20c512c5e 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -5,22 +5,30 @@ from semantic_version import Version -from spdx_tools.spdx3.model.agent import Agent -from spdx_tools.spdx3.model.annotation import Annotation, AnnotationType -from spdx_tools.spdx3.model.bom import Bom -from spdx_tools.spdx3.model.bundle import Bundle -from spdx_tools.spdx3.model.creation_information import CreationInformation -from spdx_tools.spdx3.model.external_identifier import ExternalIdentifier, ExternalIdentifierType -from spdx_tools.spdx3.model.external_map import ExternalMap -from spdx_tools.spdx3.model.external_reference import ExternalReference, ExternalReferenceType -from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm -from spdx_tools.spdx3.model.namespace_map import NamespaceMap -from spdx_tools.spdx3.model.organization import Organization -from spdx_tools.spdx3.model.person import Person -from spdx_tools.spdx3.model.relationship import Relationship, RelationshipCompleteness, RelationshipType -from spdx_tools.spdx3.model.software_agent import SoftwareAgent -from spdx_tools.spdx3.model.spdx_document import SpdxDocument -from spdx_tools.spdx3.model.tool import Tool +from spdx_tools.spdx3.model import ( + Agent, + Annotation, + AnnotationType, + Bom, + Bundle, + CreationInformation, + ExternalIdentifier, + ExternalIdentifierType, + ExternalMap, + ExternalReference, + ExternalReferenceType, + Hash, + HashAlgorithm, + NamespaceMap, + Organization, + Person, + Relationship, + RelationshipCompleteness, + RelationshipType, + SoftwareAgent, + SpdxDocument, + Tool, +) """Utility methods to create data model instances. All properties have valid defaults, so they don't need to be specified unless relevant for the test.""" @@ -29,12 +37,17 @@ def creation_info_fixture( spec_version=Version("3.0.0"), created=datetime(2022, 12, 1), - created_by=["creatorCreationInfo"], - created_using=["createdCreationInfo"], - profile=["profileCreationInfo"], + created_by=None, + created_using=None, + profile=None, data_license="CC0-1.0", - comment="commentCreationInfo", + comment="creationInfoComment", ) -> CreationInformation: + created_by = ["https://spdx.test/tools-python/creation_info_created_by"] if created_by is None else created_by + created_using = ( + ["https://spdx.test/tools-python/creation_info_created_using"] if created_using is None else created_using + ) + profile = ["core"] if profile is None else profile # TODO: this should use the Enum return CreationInformation( spec_version=spec_version, created=created, @@ -47,53 +60,76 @@ def creation_info_fixture( def external_identifier_fixture( - external_identifier_type=ExternalIdentifierType.OTHER, identifier="identifier_ext_iden", comment="comment_ext_iden" + external_identifier_type=ExternalIdentifierType.OTHER, + identifier="externalIdentifierIdentifier", + comment="externalIdentifierComment", + identifier_locator=None, + issuing_authority="https://spdx.test/tools-python/external_identifier_issuing_authority", ) -> ExternalIdentifier: - return ExternalIdentifier(external_identifier_type, identifier, comment) + identifier_locator = ( + ["https://spdx.test/tools-python/external_identifier_identifier_locator"] + if identifier_locator is None + else identifier_locator + ) + return ExternalIdentifier( + external_identifier_type=external_identifier_type, + identifier=identifier, + comment=comment, + identifier_locator=identifier_locator, + issuing_authority=issuing_authority, + ) def external_reference_fixture( external_reference_type=ExternalReferenceType.OTHER, locator=None, - content_type="content_type_exter_ref", - comment="comment_exter_ref", + content_type="externalReferenceContentType", + comment="externalReferenceComment", ) -> ExternalReference: - locator = ["locator for external reference"] if locator is None else locator - return ExternalReference(external_reference_type, locator, content_type, comment) + locator = ["org.apache.tomcat:tomcat:9.0.0.M4"] if locator is None else locator + return ExternalReference( + external_reference_type=external_reference_type, locator=locator, content_type=content_type, comment=comment + ) -def hash_fixture(algorithm=HashAlgorithm.SHA1, hash_value="hash_value", comment="comment_hash_algorithm") -> Hash: +def hash_fixture( + algorithm=HashAlgorithm.SHA1, + hash_value="71c4025dd9897b364f3ebbb42c484ff43d00791c", + comment="hashComment", +) -> Hash: return Hash(algorithm=algorithm, hash_value=hash_value, comment=comment) def external_map_fixture( - external_id="https://spdx.test/tools-python/ExternalMapFixture", + external_id="https://spdx.test/tools-python/external_map_external_id", verified_using=None, - location_hint="https://spdx.test/tools-python/location_hint_ExternalMap", + location_hint="https://spdx.test/tools-python/external_map_location_hint", ) -> ExternalMap: verified_using = [hash_fixture()] if verified_using is None else verified_using return ExternalMap(external_id=external_id, verified_using=verified_using, location_hint=location_hint) -def namespace_map_fixture(prefix="prefix_namespace_map", namespace="namespace_namespace_map") -> NamespaceMap: +def namespace_map_fixture( + prefix="namespaceMapPrefix", namespace="https://spdx.test/tools-python/namespace_map_namespace" +) -> NamespaceMap: return NamespaceMap(prefix=prefix, namespace=namespace) def agent_fixture( - spdx_id="https://spdx.test/tools-python/AgentFixture", + spdx_id="https://spdx.test/tools-python/agent_fixture", creation_info=creation_info_fixture(), - name="nameAgent", - summary="summaryAgent", - description="descriptionAgent", - comment="commentAgent", - verified_using=[hash_fixture()], - external_references=[external_reference_fixture()], - external_identifier=[external_identifier_fixture()], + name="agentName", + summary="agentSummary", + description="agentDescription", + comment="agentComment", + verified_using=None, + external_references=None, + external_identifier=None, extension=None, ) -> Agent: - verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references - external_identifier = [] if external_identifier is None else external_identifier + verified_using = [hash_fixture()] if verified_using is None else verified_using + external_references = [external_reference_fixture()] if external_references is None else external_references + external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier return Agent( spdx_id=spdx_id, creation_info=creation_info, @@ -109,24 +145,24 @@ def agent_fixture( def annotation_fixture( - spdx_id="https://spdx.test/tools-python/AnnotationFixture", + spdx_id="https://spdx.test/tools-python/annotation_fixture", creation_info=creation_info_fixture(), annotation_type=AnnotationType.OTHER, - subject="subject_annotation", - name="name_annotation", - summary="summary_annotation", - description="description_annotation", - comment="comment_annotation", - verified_using=[hash_fixture()], - external_references=[external_reference_fixture()], - external_identifier=[external_identifier_fixture()], + subject="https://spdx.test/tools-python/annotation_subject", + name="annotationName", + summary="annotationSummary", + description="annotationDescription", + comment="annotationComment", + verified_using=None, + external_references=None, + external_identifier=None, extension=None, - content_type="content_type_annotation", - statement="statement_annotation", + content_type="annotationContentType", + statement="annotationStatement", ) -> Annotation: - verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references - external_identifier = [] if external_identifier is None else external_identifier + verified_using = [hash_fixture()] if verified_using is None else verified_using + external_references = [external_reference_fixture()] if external_references is None else external_references + external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier return Annotation( spdx_id=spdx_id, creation_info=creation_info, @@ -146,27 +182,29 @@ def annotation_fixture( def bom_fixture( - spdx_id="https://spdx.test/tools-python/BomFixture", + spdx_id="https://spdx.test/tools-python/bom_fixture", creation_info=creation_info_fixture(), - elements=["elements_bom"], - root_elements=["root_elements_bom"], - name="name_bom", - summary="summary_bom", - description="description_bom", - comment="comment_bom", - verified_using=[hash_fixture()], - external_references=[external_reference_fixture()], - external_identifier=[external_identifier_fixture()], + elements=None, + root_elements=None, + name="bomName", + summary="bomSummary", + description="bomDescription", + comment="bomComment", + verified_using=None, + external_references=None, + external_identifier=None, extension=None, - namespaces=[namespace_map_fixture()], - imports=[external_map_fixture()], - context=None, + namespaces=None, + imports=None, + context="bomContext", ) -> Bom: - verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references - external_identifier = [] if external_identifier is None else external_identifier - namespaces = [] if namespaces is None else namespaces - imports = [] if imports is None else imports + elements = ["https://spdx.test/tools-python/bom_element"] if elements is None else elements + root_elements = ["https://spdx.test/tools-python/bom_root_element"] if root_elements is None else root_elements + verified_using = [hash_fixture()] if verified_using is None else verified_using + external_references = [external_reference_fixture()] if external_references is None else external_references + external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier + namespaces = [namespace_map_fixture()] if namespaces is None else namespaces + imports = [external_map_fixture()] if imports is None else imports return Bom( spdx_id=spdx_id, creation_info=creation_info, @@ -187,27 +225,29 @@ def bom_fixture( def bundle_fixture( - spdx_id="https://spdx.test/tools-python/BundleFixture", + spdx_id="https://spdx.test/tools-python/bundle_fixture", creation_info=creation_info_fixture(), - elements=["elements_bundle"], - root_elements=["root_elements_bundle"], - name="name_bundle", - summary="summary_bundle", - description="description_bundle", - comment="comment_bundle", - verified_using=[hash_fixture()], - external_references=[external_reference_fixture()], - external_identifier=[external_identifier_fixture()], + elements=None, + root_elements=None, + name="bundleName", + summary="bundleSummary", + description="bundleDescription", + comment="bundleComment", + verified_using=None, + external_references=None, + external_identifier=None, extension=None, - namespaces=[namespace_map_fixture()], - imports=[external_map_fixture()], - context="context_bundle", + namespaces=None, + imports=None, + context="bundleContext", ) -> Bundle: - verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references - external_identifier = [] if external_identifier is None else external_identifier - namespaces = [] if namespaces is None else namespaces - imports = [] if imports is None else imports + elements = ["https://spdx.test/tools-python/bundle_element"] if elements is None else elements + root_elements = ["https://spdx.test/tools-python/bundle_root_element"] if root_elements is None else root_elements + verified_using = [hash_fixture()] if verified_using is None else verified_using + external_references = [external_reference_fixture()] if external_references is None else external_references + external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier + namespaces = [namespace_map_fixture()] if namespaces is None else namespaces + imports = [external_map_fixture()] if imports is None else imports return Bundle( spdx_id=spdx_id, creation_info=creation_info, @@ -228,20 +268,20 @@ def bundle_fixture( def organization_fixture( - spdx_id="https://spdx.test/tools-python/OrganizationFixture", + spdx_id="https://spdx.test/tools-python/organization_fixture", creation_info=creation_info_fixture(), - name="name_organization", - summary="summary_organization", - description="description_organization", - comment="comment_organization", - verified_using=[hash_fixture()], - external_references=[external_reference_fixture()], - external_identifier=[external_identifier_fixture()], + name="organizationName", + summary="organizationSummary", + description="organizationDescription", + comment="organizationComment", + verified_using=None, + external_references=None, + external_identifier=None, extension=None, ) -> Organization: - verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references - external_identifier = [] if external_identifier is None else external_identifier + verified_using = [hash_fixture()] if verified_using is None else verified_using + external_references = [external_reference_fixture()] if external_references is None else external_references + external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier return Organization( spdx_id=spdx_id, creation_info=creation_info, @@ -257,20 +297,20 @@ def organization_fixture( def person_fixture( - spdx_id="https://spdx.test/tools-python/PersonFixture", + spdx_id="https://spdx.test/tools-python/person_fixture", creation_info=creation_info_fixture(), - name="name_person", - summary="summary_person", - description="description_person", - comment="comment_person", - verified_using=[hash_fixture()], - external_references=[external_reference_fixture()], - external_identifier=[external_identifier_fixture()], + name="personName", + summary="personSummary", + description="personDescription", + comment="personComment", + verified_using=None, + external_references=None, + external_identifier=None, extension=None, ) -> Person: - verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references - external_identifier = [] if external_identifier is None else external_identifier + verified_using = [hash_fixture()] if verified_using is None else verified_using + external_references = [external_reference_fixture()] if external_references is None else external_references + external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier return Person( spdx_id=spdx_id, creation_info=creation_info, @@ -286,24 +326,25 @@ def person_fixture( def relationship_fixture( - spdx_id="https://spdx.test/tools-python/RelationshipFixture", + spdx_id="https://spdx.test/tools-python/relationship_fixture", creation_info=creation_info_fixture(), - from_element="from_element_relationship", - to=["to_relationship"], + from_element="https://spdx.test/tools-python/relationship_from_element", + to=None, relationship_type=RelationshipType.OTHER, - name="name_relationship", - summary="summary_relationship", - description="description_relationship", - comment="comment_relationship", - verified_using=[hash_fixture()], - external_references=[external_reference_fixture()], - external_identifier=[external_identifier_fixture()], + name="relationshipName", + summary="relationshipSummary", + description="relationshipDescription", + comment="relationshipComment", + verified_using=None, + external_references=None, + external_identifier=None, extension=None, - completeness=RelationshipCompleteness.UNKNOWN, + completeness=RelationshipCompleteness.COMPLETE, ) -> Relationship: - verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references - external_identifier = [] if external_identifier is None else external_identifier + to = ["https://spdx.test/tools-python/relationship_to"] if to is None else to + verified_using = [hash_fixture()] if verified_using is None else verified_using + external_references = [external_reference_fixture()] if external_references is None else external_references + external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier return Relationship( spdx_id=spdx_id, creation_info=creation_info, @@ -323,20 +364,20 @@ def relationship_fixture( def software_agent_fixture( - spdx_id="https://spdx.test/tools-python/SoftwareAgentFixture", + spdx_id="https://spdx.test/tools-python/software_agent_fixture", creation_info=creation_info_fixture(), - name="name_software_agent", - summary="summary_software_agent", - description="description_software_agent", - comment="comment_software_agent", - verified_using=[hash_fixture()], - external_references=[external_reference_fixture()], - external_identifier=[external_identifier_fixture()], + name="softwareAgentName", + summary="softwareAgentSummary", + description="softwareAgentDescription", + comment="softwareAgentComment", + verified_using=None, + external_references=None, + external_identifier=None, extension=None, ) -> SoftwareAgent: - verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references - external_identifier = [] if external_identifier is None else external_identifier + verified_using = [hash_fixture()] if verified_using is None else verified_using + external_references = [external_reference_fixture()] if external_references is None else external_references + external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier return SoftwareAgent( spdx_id=spdx_id, creation_info=creation_info, @@ -352,27 +393,31 @@ def software_agent_fixture( def spdx_document_fixture( - spdx_id="https://spdx.test/tools-python/SpdxDocumentFixture", + spdx_id="https://spdx.test/tools-python/spdx_document_fixture", creation_info=creation_info_fixture(), - name="name_spdx_document", - elements=["elements_spdx_document"], - root_elements=["root_elements_spdx_document"], - summary="summary_spdx_document", - description="description_spdx_document", - comment="comment_spdx_document", - verified_using=[hash_fixture()], - external_references=[external_reference_fixture()], - external_identifier=[external_identifier_fixture()], + name="spdxDocumentName", + elements=None, + root_elements=None, + summary="spdxDocumentSummary", + description="spdxDocumentDescription", + comment="spdxDocumentComment", + verified_using=None, + external_references=None, + external_identifier=None, extension=None, - namespaces=[namespace_map_fixture()], - imports=[external_map_fixture()], + namespaces=None, + imports=None, context="context_spdx_document", ) -> SpdxDocument: - verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references - external_identifier = [] if external_identifier is None else external_identifier - namespaces = [] if namespaces is None else namespaces - imports = [] if imports is None else imports + elements = ["https://spdx.test/tools-python/spdx_document_element"] if elements is None else elements + root_elements = ( + ["https://spdx.test/tools-python/spdx_document_root_element"] if root_elements is None else root_elements + ) + verified_using = [hash_fixture()] if verified_using is None else verified_using + external_references = [external_reference_fixture()] if external_references is None else external_references + external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier + namespaces = [namespace_map_fixture()] if namespaces is None else namespaces + imports = [external_map_fixture()] if imports is None else imports return SpdxDocument( spdx_id=spdx_id, creation_info=creation_info, @@ -393,20 +438,20 @@ def spdx_document_fixture( def tool_fixture( - spdx_id="https://spdx.test/tools-python/ToolFixture", + spdx_id="https://spdx.test/tools-python/tool_fixture", creation_info=creation_info_fixture(), - name="name_tool", - summary="summary_tool", - description="description_tool", - comment="comment_tool", - verified_using=[hash_fixture()], - external_references=[external_reference_fixture()], - external_identifier=[external_identifier_fixture()], + name="toolName", + summary="toolSummary", + description="toolDescription", + comment="toolComment", + verified_using=None, + external_references=None, + external_identifier=None, extension=None, ) -> Tool: - verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references - external_identifier = [] if external_identifier is None else external_identifier + verified_using = [hash_fixture()] if verified_using is None else verified_using + external_references = [external_reference_fixture()] if external_references is None else external_references + external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier return Tool( spdx_id=spdx_id, creation_info=creation_info, From 1300b93fd4cdb0990826a80ce49c4deb54c831af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 11 May 2023 08:02:01 +0200 Subject: [PATCH 214/354] [issue-432] update SPDX3 Core fixtures according to model changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx3/fixtures.py | 52 +++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 20c512c5e..6880a1acf 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -22,6 +22,7 @@ NamespaceMap, Organization, Person, + ProfileIdentifier, Relationship, RelationshipCompleteness, RelationshipType, @@ -47,7 +48,11 @@ def creation_info_fixture( created_using = ( ["https://spdx.test/tools-python/creation_info_created_using"] if created_using is None else created_using ) - profile = ["core"] if profile is None else profile # TODO: this should use the Enum + profile = ( + [ProfileIdentifier.CORE, ProfileIdentifier.SOFTWARE, ProfileIdentifier.LICENSING] + if profile is None + else profile + ) return CreationInformation( spec_version=spec_version, created=created, @@ -157,12 +162,13 @@ def annotation_fixture( external_references=None, external_identifier=None, extension=None, - content_type="annotationContentType", + content_type=None, statement="annotationStatement", ) -> Annotation: verified_using = [hash_fixture()] if verified_using is None else verified_using external_references = [external_reference_fixture()] if external_references is None else external_references external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier + content_type = ["annotationContent"] if content_type is None else content_type return Annotation( spdx_id=spdx_id, creation_info=creation_info, @@ -184,8 +190,8 @@ def annotation_fixture( def bom_fixture( spdx_id="https://spdx.test/tools-python/bom_fixture", creation_info=creation_info_fixture(), - elements=None, - root_elements=None, + element=None, + root_element=None, name="bomName", summary="bomSummary", description="bomDescription", @@ -198,8 +204,8 @@ def bom_fixture( imports=None, context="bomContext", ) -> Bom: - elements = ["https://spdx.test/tools-python/bom_element"] if elements is None else elements - root_elements = ["https://spdx.test/tools-python/bom_root_element"] if root_elements is None else root_elements + element = ["https://spdx.test/tools-python/bom_element"] if element is None else element + root_element = ["https://spdx.test/tools-python/bom_root_element"] if root_element is None else root_element verified_using = [hash_fixture()] if verified_using is None else verified_using external_references = [external_reference_fixture()] if external_references is None else external_references external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier @@ -208,8 +214,8 @@ def bom_fixture( return Bom( spdx_id=spdx_id, creation_info=creation_info, - element=elements, - root_element=root_elements, + element=element, + root_element=root_element, name=name, summary=summary, description=description, @@ -227,8 +233,8 @@ def bom_fixture( def bundle_fixture( spdx_id="https://spdx.test/tools-python/bundle_fixture", creation_info=creation_info_fixture(), - elements=None, - root_elements=None, + element=None, + root_element=None, name="bundleName", summary="bundleSummary", description="bundleDescription", @@ -241,8 +247,8 @@ def bundle_fixture( imports=None, context="bundleContext", ) -> Bundle: - elements = ["https://spdx.test/tools-python/bundle_element"] if elements is None else elements - root_elements = ["https://spdx.test/tools-python/bundle_root_element"] if root_elements is None else root_elements + element = ["https://spdx.test/tools-python/bundle_element"] if element is None else element + root_element = ["https://spdx.test/tools-python/bundle_root_element"] if root_element is None else root_element verified_using = [hash_fixture()] if verified_using is None else verified_using external_references = [external_reference_fixture()] if external_references is None else external_references external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier @@ -251,8 +257,8 @@ def bundle_fixture( return Bundle( spdx_id=spdx_id, creation_info=creation_info, - element=elements, - root_element=root_elements, + element=element, + root_element=root_element, name=name, summary=summary, description=description, @@ -329,8 +335,8 @@ def relationship_fixture( spdx_id="https://spdx.test/tools-python/relationship_fixture", creation_info=creation_info_fixture(), from_element="https://spdx.test/tools-python/relationship_from_element", - to=None, relationship_type=RelationshipType.OTHER, + to=None, name="relationshipName", summary="relationshipSummary", description="relationshipDescription", @@ -349,8 +355,8 @@ def relationship_fixture( spdx_id=spdx_id, creation_info=creation_info, from_element=from_element, - to=to, relationship_type=relationship_type, + to=to, name=name, summary=summary, description=description, @@ -396,8 +402,8 @@ def spdx_document_fixture( spdx_id="https://spdx.test/tools-python/spdx_document_fixture", creation_info=creation_info_fixture(), name="spdxDocumentName", - elements=None, - root_elements=None, + element=None, + root_element=None, summary="spdxDocumentSummary", description="spdxDocumentDescription", comment="spdxDocumentComment", @@ -409,9 +415,9 @@ def spdx_document_fixture( imports=None, context="context_spdx_document", ) -> SpdxDocument: - elements = ["https://spdx.test/tools-python/spdx_document_element"] if elements is None else elements - root_elements = ( - ["https://spdx.test/tools-python/spdx_document_root_element"] if root_elements is None else root_elements + element = ["https://spdx.test/tools-python/spdx_document_element"] if element is None else element + root_element = ( + ["https://spdx.test/tools-python/spdx_document_root_element"] if root_element is None else root_element ) verified_using = [hash_fixture()] if verified_using is None else verified_using external_references = [external_reference_fixture()] if external_references is None else external_references @@ -422,8 +428,8 @@ def spdx_document_fixture( spdx_id=spdx_id, creation_info=creation_info, name=name, - element=elements, - root_element=root_elements, + element=element, + root_element=root_element, summary=summary, description=description, comment=comment, From e32e825ef98fcc720c4e7cd1564fb95cbf2fc1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 11 May 2023 11:34:15 +0200 Subject: [PATCH 215/354] [issue-644] change type of extension property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/model/agent.py | 2 +- src/spdx_tools/spdx3/model/ai/ai_package.py | 2 +- src/spdx_tools/spdx3/model/annotation.py | 2 +- src/spdx_tools/spdx3/model/bom.py | 2 +- src/spdx_tools/spdx3/model/build/build.py | 2 +- src/spdx_tools/spdx3/model/bundle.py | 2 +- src/spdx_tools/spdx3/model/dataset/dataset.py | 2 +- src/spdx_tools/spdx3/model/element.py | 2 +- src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py | 2 +- src/spdx_tools/spdx3/model/organization.py | 2 +- src/spdx_tools/spdx3/model/person.py | 2 +- src/spdx_tools/spdx3/model/relationship.py | 2 +- .../model/security/cvss_v2_vuln_assessment_relationship.py | 2 +- .../model/security/cvss_v3_vuln_assessment_relationship.py | 2 +- .../spdx3/model/security/epss_vuln_assessment_relationship.py | 2 +- .../security/exploit_catalog_vuln_assessment_relationship.py | 2 +- .../spdx3/model/security/ssvc_vuln_assessment_relationship.py | 2 +- .../model/security/vex_affected_vuln_assessment_relationship.py | 2 +- .../model/security/vex_fixed_vuln_assessment_relationship.py | 2 +- .../security/vex_not_affected_vuln_assessment_relationship.py | 2 +- .../vex_under_investigation_vuln_assessment_relationship.py | 2 +- src/spdx_tools/spdx3/model/security/vulnerability.py | 2 +- src/spdx_tools/spdx3/model/software/file.py | 2 +- src/spdx_tools/spdx3/model/software/package.py | 2 +- src/spdx_tools/spdx3/model/software/sbom.py | 2 +- src/spdx_tools/spdx3/model/software/snippet.py | 2 +- .../spdx3/model/software/software_dependency_relationship.py | 2 +- src/spdx_tools/spdx3/model/software_agent.py | 2 +- src/spdx_tools/spdx3/model/spdx_document.py | 2 +- src/spdx_tools/spdx3/model/tool.py | 2 +- 30 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/spdx_tools/spdx3/model/agent.py b/src/spdx_tools/spdx3/model/agent.py index 50afb99cf..c85398fac 100644 --- a/src/spdx_tools/spdx3/model/agent.py +++ b/src/spdx_tools/spdx3/model/agent.py @@ -21,7 +21,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references diff --git a/src/spdx_tools/spdx3/model/ai/ai_package.py b/src/spdx_tools/spdx3/model/ai/ai_package.py index f0ed49e33..a22e7cbce 100644 --- a/src/spdx_tools/spdx3/model/ai/ai_package.py +++ b/src/spdx_tools/spdx3/model/ai/ai_package.py @@ -54,7 +54,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, originated_by: List[str] = None, built_time: Optional[datetime] = None, valid_until_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/annotation.py b/src/spdx_tools/spdx3/model/annotation.py index 5bdbecd5a..e836893b2 100644 --- a/src/spdx_tools/spdx3/model/annotation.py +++ b/src/spdx_tools/spdx3/model/annotation.py @@ -35,7 +35,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, content_type: List[str] = None, statement: Optional[str] = None, ): diff --git a/src/spdx_tools/spdx3/model/bom.py b/src/spdx_tools/spdx3/model/bom.py index 7b6c51666..92ba6b2ac 100644 --- a/src/spdx_tools/spdx3/model/bom.py +++ b/src/spdx_tools/spdx3/model/bom.py @@ -34,7 +34,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, namespaces: List[NamespaceMap] = None, imports: List[ExternalMap] = None, context: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/build/build.py b/src/spdx_tools/spdx3/model/build/build.py index d9842fbc9..fc118017a 100644 --- a/src/spdx_tools/spdx3/model/build/build.py +++ b/src/spdx_tools/spdx3/model/build/build.py @@ -41,7 +41,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, build_id: Optional[str] = None, config_source_entrypoint: List[str] = None, config_source_uri: List[str] = None, diff --git a/src/spdx_tools/spdx3/model/bundle.py b/src/spdx_tools/spdx3/model/bundle.py index 1700ec697..ae12ecb76 100644 --- a/src/spdx_tools/spdx3/model/bundle.py +++ b/src/spdx_tools/spdx3/model/bundle.py @@ -33,7 +33,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, namespaces: List[NamespaceMap] = None, imports: List[ExternalMap] = None, context: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py index dd74642cd..3a1ce75ab 100644 --- a/src/spdx_tools/spdx3/model/dataset/dataset.py +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -61,7 +61,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, supplied_by: List[str] = None, valid_until_time: Optional[datetime] = None, standard: List[str] = None, diff --git a/src/spdx_tools/spdx3/model/element.py b/src/spdx_tools/spdx3/model/element.py index 7abd88f34..3b5dab9cc 100644 --- a/src/spdx_tools/spdx3/model/element.py +++ b/src/spdx_tools/spdx3/model/element.py @@ -20,7 +20,7 @@ class Element(ABC): verified_using: List[IntegrityMethod] = field(default_factory=list) external_references: List[ExternalReference] = field(default_factory=list) external_identifier: List[ExternalIdentifier] = field(default_factory=list) - extension: None = None # placeholder for extension + extension: Optional[str] = None # placeholder for extension @abstractmethod def __init__(self): diff --git a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py index 244eb6951..de14da44b 100644 --- a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py +++ b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py @@ -45,7 +45,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/organization.py b/src/spdx_tools/spdx3/model/organization.py index 19fec3cc5..f500bb64f 100644 --- a/src/spdx_tools/spdx3/model/organization.py +++ b/src/spdx_tools/spdx3/model/organization.py @@ -21,7 +21,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references diff --git a/src/spdx_tools/spdx3/model/person.py b/src/spdx_tools/spdx3/model/person.py index 95a80d015..c8b9eb3b4 100644 --- a/src/spdx_tools/spdx3/model/person.py +++ b/src/spdx_tools/spdx3/model/person.py @@ -21,7 +21,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index f8522f46d..a1933a81b 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -108,7 +108,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py index 372bc698c..a7b250984 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py @@ -38,7 +38,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py index d85dd14f2..77b77d119 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py @@ -38,7 +38,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py index 4b5c3ea4c..bd085e764 100644 --- a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py @@ -37,7 +37,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py index 8abc8d85b..fb45580a2 100644 --- a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py @@ -46,7 +46,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py index 3505c9d9f..81ed4c868 100644 --- a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py @@ -44,7 +44,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py index 0394085fb..245d03ea1 100644 --- a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py @@ -37,7 +37,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py index f981e7a3c..d15bdf1bc 100644 --- a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py @@ -33,7 +33,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py index dfb201465..593b591ef 100644 --- a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py @@ -46,7 +46,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py index 58448a0cd..3bac6a91a 100644 --- a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py @@ -33,7 +33,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/security/vulnerability.py b/src/spdx_tools/spdx3/model/security/vulnerability.py index 0760fe75d..14104f629 100644 --- a/src/spdx_tools/spdx3/model/security/vulnerability.py +++ b/src/spdx_tools/spdx3/model/security/vulnerability.py @@ -26,7 +26,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, published_time: Optional[datetime] = None, modified_time: Optional[datetime] = None, withdrawn_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py index 8f2b67776..0cce0a95b 100644 --- a/src/spdx_tools/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -27,7 +27,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, originated_by: List[str] = None, supplied_by: List[str] = None, built_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py index 097e73079..eff655705 100644 --- a/src/spdx_tools/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -31,7 +31,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, originated_by: List[str] = None, supplied_by: List[str] = None, built_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/software/sbom.py b/src/spdx_tools/spdx3/model/software/sbom.py index 0b3da591e..d99935125 100644 --- a/src/spdx_tools/spdx3/model/software/sbom.py +++ b/src/spdx_tools/spdx3/model/software/sbom.py @@ -46,7 +46,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, namespaces: List[NamespaceMap] = None, imports: List[ExternalMap] = None, context: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py index f94ffe410..5beb04bdb 100644 --- a/src/spdx_tools/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -28,7 +28,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, originated_by: List[str] = None, supplied_by: List[str] = None, built_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py index 1ec7781a3..05438c66c 100644 --- a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py +++ b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py @@ -53,7 +53,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, diff --git a/src/spdx_tools/spdx3/model/software_agent.py b/src/spdx_tools/spdx3/model/software_agent.py index 05087d9a9..b2c587548 100644 --- a/src/spdx_tools/spdx3/model/software_agent.py +++ b/src/spdx_tools/spdx3/model/software_agent.py @@ -21,7 +21,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references diff --git a/src/spdx_tools/spdx3/model/spdx_document.py b/src/spdx_tools/spdx3/model/spdx_document.py index 0bd0ee1a2..f70783a86 100644 --- a/src/spdx_tools/spdx3/model/spdx_document.py +++ b/src/spdx_tools/spdx3/model/spdx_document.py @@ -34,7 +34,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, namespaces: List[NamespaceMap] = None, imports: List[ExternalMap] = None, context: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/tool.py b/src/spdx_tools/spdx3/model/tool.py index d707926ca..22c5f081f 100644 --- a/src/spdx_tools/spdx3/model/tool.py +++ b/src/spdx_tools/spdx3/model/tool.py @@ -21,7 +21,7 @@ def __init__( verified_using: List[IntegrityMethod] = None, external_references: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, - extension: None = None, + extension: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references From 55f63517c6f7ef4f96db8ca260970043e924c693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 11 May 2023 11:21:34 +0200 Subject: [PATCH 216/354] [issue-432] refactor fixtures to deduplicate code from inherited properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx3/fixtures.py | 441 +++++-------------------- tests/spdx3/model/test_relationship.py | 45 +-- 2 files changed, 117 insertions(+), 369 deletions(-) diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 6880a1acf..a984992d4 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime +from typing import Any, Dict, Type from semantic_version import Version @@ -19,6 +20,8 @@ ExternalReferenceType, Hash, HashAlgorithm, + LifecycleScopedRelationship, + LifecycleScopeType, NamespaceMap, Organization, Person, @@ -30,6 +33,7 @@ SpdxDocument, Tool, ) +from spdx_tools.spdx3.model.software import Sbom, SBOMType """Utility methods to create data model instances. All properties have valid defaults, so they don't need to be specified unless relevant for the test.""" @@ -120,353 +124,90 @@ def namespace_map_fixture( return NamespaceMap(prefix=prefix, namespace=namespace) -def agent_fixture( - spdx_id="https://spdx.test/tools-python/agent_fixture", - creation_info=creation_info_fixture(), - name="agentName", - summary="agentSummary", - description="agentDescription", - comment="agentComment", - verified_using=None, - external_references=None, - external_identifier=None, - extension=None, -) -> Agent: - verified_using = [hash_fixture()] if verified_using is None else verified_using - external_references = [external_reference_fixture()] if external_references is None else external_references - external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier - return Agent( - spdx_id=spdx_id, - creation_info=creation_info, - name=name, - summary=summary, - description=description, - comment=comment, - verified_using=verified_using, - external_references=external_references, - external_identifier=external_identifier, - extension=extension, - ) - - -def annotation_fixture( - spdx_id="https://spdx.test/tools-python/annotation_fixture", - creation_info=creation_info_fixture(), - annotation_type=AnnotationType.OTHER, - subject="https://spdx.test/tools-python/annotation_subject", - name="annotationName", - summary="annotationSummary", - description="annotationDescription", - comment="annotationComment", - verified_using=None, - external_references=None, - external_identifier=None, - extension=None, - content_type=None, - statement="annotationStatement", -) -> Annotation: - verified_using = [hash_fixture()] if verified_using is None else verified_using - external_references = [external_reference_fixture()] if external_references is None else external_references - external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier - content_type = ["annotationContent"] if content_type is None else content_type - return Annotation( - spdx_id=spdx_id, - creation_info=creation_info, - annotation_type=annotation_type, - subject=subject, - name=name, - summary=summary, - description=description, - comment=comment, - verified_using=verified_using, - external_references=external_references, - external_identifier=external_identifier, - extension=extension, - content_type=content_type, - statement=statement, - ) - - -def bom_fixture( - spdx_id="https://spdx.test/tools-python/bom_fixture", - creation_info=creation_info_fixture(), - element=None, - root_element=None, - name="bomName", - summary="bomSummary", - description="bomDescription", - comment="bomComment", - verified_using=None, - external_references=None, - external_identifier=None, - extension=None, - namespaces=None, - imports=None, - context="bomContext", -) -> Bom: - element = ["https://spdx.test/tools-python/bom_element"] if element is None else element - root_element = ["https://spdx.test/tools-python/bom_root_element"] if root_element is None else root_element - verified_using = [hash_fixture()] if verified_using is None else verified_using - external_references = [external_reference_fixture()] if external_references is None else external_references - external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier - namespaces = [namespace_map_fixture()] if namespaces is None else namespaces - imports = [external_map_fixture()] if imports is None else imports - return Bom( - spdx_id=spdx_id, - creation_info=creation_info, - element=element, - root_element=root_element, - name=name, - summary=summary, - description=description, - comment=comment, - verified_using=verified_using, - external_references=external_references, - external_identifier=external_identifier, - extension=extension, - namespaces=namespaces, - imports=imports, - context=context, - ) - - -def bundle_fixture( - spdx_id="https://spdx.test/tools-python/bundle_fixture", - creation_info=creation_info_fixture(), - element=None, - root_element=None, - name="bundleName", - summary="bundleSummary", - description="bundleDescription", - comment="bundleComment", - verified_using=None, - external_references=None, - external_identifier=None, - extension=None, - namespaces=None, - imports=None, - context="bundleContext", -) -> Bundle: - element = ["https://spdx.test/tools-python/bundle_element"] if element is None else element - root_element = ["https://spdx.test/tools-python/bundle_root_element"] if root_element is None else root_element - verified_using = [hash_fixture()] if verified_using is None else verified_using - external_references = [external_reference_fixture()] if external_references is None else external_references - external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier - namespaces = [namespace_map_fixture()] if namespaces is None else namespaces - imports = [external_map_fixture()] if imports is None else imports - return Bundle( - spdx_id=spdx_id, - creation_info=creation_info, - element=element, - root_element=root_element, - name=name, - summary=summary, - description=description, - comment=comment, - verified_using=verified_using, - external_references=external_references, - external_identifier=external_identifier, - extension=extension, - namespaces=namespaces, - imports=imports, - context=context, - ) - - -def organization_fixture( - spdx_id="https://spdx.test/tools-python/organization_fixture", - creation_info=creation_info_fixture(), - name="organizationName", - summary="organizationSummary", - description="organizationDescription", - comment="organizationComment", - verified_using=None, - external_references=None, - external_identifier=None, - extension=None, -) -> Organization: - verified_using = [hash_fixture()] if verified_using is None else verified_using - external_references = [external_reference_fixture()] if external_references is None else external_references - external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier - return Organization( - spdx_id=spdx_id, - creation_info=creation_info, - name=name, - summary=summary, - description=description, - comment=comment, - verified_using=verified_using, - external_references=external_references, - external_identifier=external_identifier, - extension=extension, - ) - - -def person_fixture( - spdx_id="https://spdx.test/tools-python/person_fixture", - creation_info=creation_info_fixture(), - name="personName", - summary="personSummary", - description="personDescription", - comment="personComment", - verified_using=None, - external_references=None, - external_identifier=None, - extension=None, -) -> Person: - verified_using = [hash_fixture()] if verified_using is None else verified_using - external_references = [external_reference_fixture()] if external_references is None else external_references - external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier - return Person( - spdx_id=spdx_id, - creation_info=creation_info, - name=name, - summary=summary, - description=description, - comment=comment, - verified_using=verified_using, - external_references=external_references, - external_identifier=external_identifier, - extension=extension, - ) - - -def relationship_fixture( - spdx_id="https://spdx.test/tools-python/relationship_fixture", - creation_info=creation_info_fixture(), - from_element="https://spdx.test/tools-python/relationship_from_element", - relationship_type=RelationshipType.OTHER, - to=None, - name="relationshipName", - summary="relationshipSummary", - description="relationshipDescription", - comment="relationshipComment", - verified_using=None, - external_references=None, - external_identifier=None, - extension=None, - completeness=RelationshipCompleteness.COMPLETE, -) -> Relationship: - to = ["https://spdx.test/tools-python/relationship_to"] if to is None else to - verified_using = [hash_fixture()] if verified_using is None else verified_using - external_references = [external_reference_fixture()] if external_references is None else external_references - external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier - return Relationship( - spdx_id=spdx_id, - creation_info=creation_info, - from_element=from_element, - relationship_type=relationship_type, - to=to, - name=name, - summary=summary, - description=description, - comment=comment, - verified_using=verified_using, - external_references=external_references, - external_identifier=external_identifier, - extension=extension, - completeness=completeness, - ) - - -def software_agent_fixture( - spdx_id="https://spdx.test/tools-python/software_agent_fixture", - creation_info=creation_info_fixture(), - name="softwareAgentName", - summary="softwareAgentSummary", - description="softwareAgentDescription", - comment="softwareAgentComment", - verified_using=None, - external_references=None, - external_identifier=None, - extension=None, -) -> SoftwareAgent: - verified_using = [hash_fixture()] if verified_using is None else verified_using - external_references = [external_reference_fixture()] if external_references is None else external_references - external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier - return SoftwareAgent( - spdx_id=spdx_id, - creation_info=creation_info, - name=name, - summary=summary, - description=description, - comment=comment, - verified_using=verified_using, - external_references=external_references, - external_identifier=external_identifier, - extension=extension, - ) - - -def spdx_document_fixture( - spdx_id="https://spdx.test/tools-python/spdx_document_fixture", - creation_info=creation_info_fixture(), - name="spdxDocumentName", - element=None, - root_element=None, - summary="spdxDocumentSummary", - description="spdxDocumentDescription", - comment="spdxDocumentComment", - verified_using=None, - external_references=None, - external_identifier=None, - extension=None, - namespaces=None, - imports=None, - context="context_spdx_document", -) -> SpdxDocument: - element = ["https://spdx.test/tools-python/spdx_document_element"] if element is None else element - root_element = ( - ["https://spdx.test/tools-python/spdx_document_root_element"] if root_element is None else root_element - ) - verified_using = [hash_fixture()] if verified_using is None else verified_using - external_references = [external_reference_fixture()] if external_references is None else external_references - external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier - namespaces = [namespace_map_fixture()] if namespaces is None else namespaces - imports = [external_map_fixture()] if imports is None else imports - return SpdxDocument( - spdx_id=spdx_id, - creation_info=creation_info, - name=name, - element=element, - root_element=root_element, - summary=summary, - description=description, - comment=comment, - verified_using=verified_using, - external_references=external_references, - external_identifier=external_identifier, - extension=extension, - namespaces=namespaces, - imports=imports, - context=context, - ) - - -def tool_fixture( - spdx_id="https://spdx.test/tools-python/tool_fixture", - creation_info=creation_info_fixture(), - name="toolName", - summary="toolSummary", - description="toolDescription", - comment="toolComment", - verified_using=None, - external_references=None, - external_identifier=None, - extension=None, -) -> Tool: - verified_using = [hash_fixture()] if verified_using is None else verified_using - external_references = [external_reference_fixture()] if external_references is None else external_references - external_identifier = [external_identifier_fixture()] if external_identifier is None else external_identifier - return Tool( - spdx_id=spdx_id, - creation_info=creation_info, - name=name, - summary=summary, - description=description, - comment=comment, - verified_using=verified_using, - external_references=external_references, - external_identifier=external_identifier, - extension=extension, - ) +ELEMENT_DICT = { + "spdx_id": "https://spdx.test/tools-python/element_fixture", + "creation_info": creation_info_fixture(), + "name": "elementName", + "summary": "elementSummary", + "description": "elementDescription", + "comment": "elementComment", + "verified_using": [hash_fixture()], + "external_references": [external_reference_fixture()], + "external_identifier": [external_identifier_fixture()], + "extension": "extensionPlaceholder", +} + +RELATIONSHIP_DICT = { + "from_element": "https://spdx.test/tools-python/relationship_from_element", + "relationship_type": RelationshipType.OTHER, + "to": ["https://spdx.test/tools-python/relationship_to"], + "completeness": RelationshipCompleteness.COMPLETE, + "start_time": datetime(2020, 1, 1), + "end_time": datetime(2023, 1, 1), +} + +LIFECYCLE_SCOPED_RELATIONSHIP_DICT = {"scope": LifecycleScopeType.DESIGN} + +ANNOTATION_DICT = { + "annotation_type": AnnotationType.OTHER, + "subject": "https://spdx.test/tools-python/annotation_subject", + "content_type": ["annotationContent"], + "statement": "annotationStatement", +} + +ELEMENT_COLLECTION_DICT = { + "element": ["https://spdx.test/tools-python/collection_element"], + "root_element": ["https://spdx.test/tools-python/collection_root_element"], + "namespaces": [namespace_map_fixture()], + "imports": [external_map_fixture()], +} + +BUNDLE_DICT = { + "context": "bundleContext", +} + +SBOM_DICT = { + "sbom_type": [SBOMType.BUILD], +} + +FIXTURE_DICTS = { + Agent: [ELEMENT_DICT], + Person: [ELEMENT_DICT], + Organization: [ELEMENT_DICT], + SoftwareAgent: [ELEMENT_DICT], + Tool: [ELEMENT_DICT], + Relationship: [ELEMENT_DICT, RELATIONSHIP_DICT], + LifecycleScopedRelationship: [ELEMENT_DICT, RELATIONSHIP_DICT, LIFECYCLE_SCOPED_RELATIONSHIP_DICT], + Annotation: [ELEMENT_DICT, ANNOTATION_DICT], + Bundle: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT], + SpdxDocument: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT], + Bom: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT], + Sbom: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT, SBOM_DICT], +} + + +def element_fixture_factory(clazz: Type[Any], **kwargs) -> Any: + fixture_dict = get_fixture_dict(clazz) + + for key in kwargs.keys(): + if key not in fixture_dict.keys(): + raise ValueError(f"Provided property name {key} is not part of {clazz.__name__}.") + else: + fixture_dict[key] = kwargs[key] + + return clazz(**fixture_dict) + + +def get_fixture_dict(clazz: Type[Any]) -> Dict[str, Any]: + fixture_dict = {} + if clazz not in FIXTURE_DICTS.keys(): + raise ValueError( + f"{clazz.__name__} is not part of the FIXTURE_DICTS. " + f"If it is a non-abstract subclass of Element, it was probably forgotten to add." + ) + for property_dict in FIXTURE_DICTS[clazz]: + fixture_dict.update(property_dict) + + fixture_dict["spdx_id"] = f"https://spdx.test/tools-python/{clazz.__name__}_fixture" + + return fixture_dict diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py index 471d1cd79..aa99c268d 100644 --- a/tests/spdx3/model/test_relationship.py +++ b/tests/spdx3/model/test_relationship.py @@ -6,30 +6,37 @@ import pytest +from spdx3.fixtures import relationship_fixture, ELEMENT_DICT, RELATIONSHIP_DICT from spdx_tools.spdx3.model import Relationship, RelationshipCompleteness, RelationshipType @mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) def test_correct_initialization(creation_information): - relationship = Relationship( - "SPDXRef-Relationship", - creation_information, - "spdx_id1", - RelationshipType.DESCRIBES, - ["spdx_id2", "spdx_id3"], - completeness=RelationshipCompleteness.NOASSERTION, - start_time=datetime(11, 11, 11), - end_time=datetime(12, 12, 12), - ) - - assert relationship.spdx_id == "SPDXRef-Relationship" - assert relationship.creation_info == creation_information - assert relationship.from_element == "spdx_id1" - assert relationship.to == ["spdx_id2", "spdx_id3"] - assert relationship.relationship_type == RelationshipType.DESCRIBES - assert relationship.completeness == RelationshipCompleteness.NOASSERTION - assert relationship.start_time == datetime(11, 11, 11) - assert relationship.end_time == datetime(12, 12, 12) + relationship = relationship_fixture() + + local_dict = {} + local_dict.update(ELEMENT_DICT) + local_dict.update(RELATIONSHIP_DICT) + local_dict["spdx_id"] = "https://spdx.test/tools-python/relationship_fixture" + + keys = [ + attribute + for attribute in dir(Relationship) + if isinstance(getattr(Relationship, attribute), property) + ] + + for key in keys: + assert getattr(relationship, key) is not None + assert getattr(relationship, key) == local_dict[key] + + # assert relationship.spdx_id == "SPDXRef-Relationship" + # assert relationship.creation_info == creation_information + # assert relationship.from_element == "spdx_id1" + # assert relationship.to == ["spdx_id2", "spdx_id3"] + # assert relationship.relationship_type == RelationshipType.DESCRIBES + # assert relationship.completeness == RelationshipCompleteness.NOASSERTION + # assert relationship.start_time == datetime(11, 11, 11) + # assert relationship.end_time == datetime(12, 12, 12) @mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) From 3af691f7ca1376d6f6ec4e530d4817e3819cc3e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Fri, 12 May 2023 08:13:10 +0200 Subject: [PATCH 217/354] [issue-432] use new fixtures in Core class initialization testing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx3/model/test_agent.py | 48 ----------- tests/spdx3/model/test_annotation.py | 49 ------------ tests/spdx3/model/test_bom.py | 32 -------- tests/spdx3/model/test_bundle.py | 42 ---------- tests/spdx3/model/test_element_subclasses.py | 79 +++++++++++++++++++ .../test_lifecycle_scoped_relationship.py | 55 ------------- tests/spdx3/model/test_relationship.py | 55 ------------- tests/spdx3/model/test_spdx_document.py | 45 ----------- tests/spdx3/model/test_tool.py | 34 -------- 9 files changed, 79 insertions(+), 360 deletions(-) delete mode 100644 tests/spdx3/model/test_agent.py delete mode 100644 tests/spdx3/model/test_annotation.py delete mode 100644 tests/spdx3/model/test_bom.py delete mode 100644 tests/spdx3/model/test_bundle.py create mode 100644 tests/spdx3/model/test_element_subclasses.py delete mode 100644 tests/spdx3/model/test_lifecycle_scoped_relationship.py delete mode 100644 tests/spdx3/model/test_relationship.py delete mode 100644 tests/spdx3/model/test_spdx_document.py delete mode 100644 tests/spdx3/model/test_tool.py diff --git a/tests/spdx3/model/test_agent.py b/tests/spdx3/model/test_agent.py deleted file mode 100644 index 2c1618b73..000000000 --- a/tests/spdx3/model/test_agent.py +++ /dev/null @@ -1,48 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from datetime import datetime - -import pytest -from semantic_version import Version - -from spdx_tools.spdx3.model import ( - Agent, - CreationInformation, - ExternalIdentifier, - ExternalIdentifierType, - Organization, - Person, - ProfileIdentifier, - SoftwareAgent, -) - - -@pytest.mark.parametrize("agent_class", [Agent, Person, Organization, SoftwareAgent]) -def test_correct_initialization(agent_class): - agent = agent_class( - "SPDXRef-Agent", - CreationInformation( - Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], [ProfileIdentifier.CORE], "CC0" - ), - external_identifier=[ExternalIdentifier(ExternalIdentifierType.EMAIL, "some@mail.com")], - ) - - assert agent.spdx_id == "SPDXRef-Agent" - assert agent.creation_info == CreationInformation( - Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], [ProfileIdentifier.CORE], "CC0" - ) - assert agent.external_identifier == [ExternalIdentifier(ExternalIdentifierType.EMAIL, "some@mail.com")] - - -@pytest.mark.parametrize("agent_class", [Agent, Person, Organization, SoftwareAgent]) -def test_invalid_initialization(agent_class): - with pytest.raises(TypeError) as err: - agent_class(12, 345) - - assert err.value.args[0] == [ - f'SetterError {agent_class.__name__}: type of argument "spdx_id" must be str; got int instead: ' "12", - f'SetterError {agent_class.__name__}: type of argument "creation_info" must be ' - "spdx_tools.spdx3.model.creation_information.CreationInformation; got int " - "instead: 345", - ] diff --git a/tests/spdx3/model/test_annotation.py b/tests/spdx3/model/test_annotation.py deleted file mode 100644 index 5a98a09b6..000000000 --- a/tests/spdx3/model/test_annotation.py +++ /dev/null @@ -1,49 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from unittest import mock - -import pytest - -from spdx_tools.spdx3.model import Annotation, AnnotationType - - -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): - annotation = Annotation( - "SPDXRef-Annotation", - creation_information, - AnnotationType.OTHER, - "spdx_id1", - content_type=["mediaType"], - statement="This is a statement", - ) - - assert annotation.spdx_id == "SPDXRef-Annotation" - assert annotation.creation_info == creation_information - assert annotation.annotation_type == AnnotationType.OTHER - assert annotation.subject == "spdx_id1" - assert annotation.content_type == ["mediaType"] - assert annotation.statement == "This is a statement" - - -@mock.patch("spdx_tools.spdx3.model.CreationInformation") -def test_invalid_initialization(creation_information): - with pytest.raises(TypeError) as err: - Annotation( - "SPDXRef-Annotation", - creation_information, - "REVIEW", - {"element": 1}, - content_type=4, - statement=["some statements"], - ) - - assert err.value.args[0] == [ - 'SetterError Annotation: type of argument "annotation_type" must be ' - "spdx_tools.spdx3.model.annotation.AnnotationType; got str instead: REVIEW", - 'SetterError Annotation: type of argument "subject" must be str; got dict ' "instead: {'element': 1}", - 'SetterError Annotation: type of argument "content_type" must be a list; got ' "int instead: 4", - 'SetterError Annotation: type of argument "statement" must be one of (str, ' - "NoneType); got list instead: ['some statements']", - ] diff --git a/tests/spdx3/model/test_bom.py b/tests/spdx3/model/test_bom.py deleted file mode 100644 index c2d1c3191..000000000 --- a/tests/spdx3/model/test_bom.py +++ /dev/null @@ -1,32 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 - -from unittest import mock - -import pytest - -from spdx_tools.spdx3.model import Bom - - -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): - bom = Bom("SPDXRef-Bom", creation_information, element=["spdx_id1"], root_element=["spdx_id2"]) - - assert bom.spdx_id == "SPDXRef-Bom" - assert bom.creation_info == creation_information - assert bom.element == ["spdx_id1"] - assert bom.root_element == ["spdx_id2"] - - -def test_invalid_initialization(): - with pytest.raises(TypeError) as err: - Bom(1, "Creation Information", element=[5], root_element=[]) - - assert err.value.args[0] == [ - 'SetterError Bom: type of argument "spdx_id" must be str; got int instead: 1', - 'SetterError Bom: type of argument "creation_info" must be ' - "spdx_tools.spdx3.model.creation_information.CreationInformation; got str " - "instead: Creation Information", - 'SetterError Bom: type of argument "element"[0] must be str; got int instead: ' "[5]", - ] diff --git a/tests/spdx3/model/test_bundle.py b/tests/spdx3/model/test_bundle.py deleted file mode 100644 index ea525ac14..000000000 --- a/tests/spdx3/model/test_bundle.py +++ /dev/null @@ -1,42 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from unittest import mock - -import pytest - -from spdx_tools.spdx3.model import Bundle - - -@mock.patch("spdx_tools.spdx3.model.NamespaceMap", autospec=True) -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information, namespace): - bundle = Bundle( - "SPDXRef-Bundle", - creation_information, - element=["spdx_id1"], - root_element=["spdx_id2"], - namespaces=[namespace], - context="context", - ) - - assert bundle.spdx_id == "SPDXRef-Bundle" - assert bundle.creation_info == creation_information - assert bundle.element == ["spdx_id1"] - assert bundle.root_element == ["spdx_id2"] - assert bundle.context == "context" - assert bundle.namespaces == [namespace] - - -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_invalid_initialization(creation_information): - with pytest.raises(TypeError) as err: - Bundle(4, creation_information, element="spdx_id1", root_element=[42], namespaces=True, context=["yes"]) - - assert err.value.args[0] == [ - 'SetterError Bundle: type of argument "spdx_id" must be str; got int instead: 4', - 'SetterError Bundle: type of argument "element" must be a list; got str ' "instead: spdx_id1", - 'SetterError Bundle: type of argument "root_element"[0] must be str; got int ' "instead: [42]", - 'SetterError Bundle: type of argument "namespaces" must be a list; ' "got bool instead: True", - 'SetterError Bundle: type of argument "context" must be one of (str, ' "NoneType); got list instead: ['yes']", - ] diff --git a/tests/spdx3/model/test_element_subclasses.py b/tests/spdx3/model/test_element_subclasses.py new file mode 100644 index 000000000..3225a3fc4 --- /dev/null +++ b/tests/spdx3/model/test_element_subclasses.py @@ -0,0 +1,79 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import Any, Type + +import pytest + +from spdx_tools.spdx3.model import ( + Agent, + Annotation, + Bom, + Bundle, + LifecycleScopedRelationship, + Organization, + Person, + Relationship, + SoftwareAgent, + SpdxDocument, +) +from tests.spdx3.fixtures import element_fixture_factory, get_fixture_dict + + +def get_property_names(clazz: Type[Any]): + return [ + attribute + for attribute in dir(clazz) + if not attribute.startswith("_") and not callable(getattr(clazz, attribute)) + ] + + +CLASS_LIST = [ + Agent, + Person, + Organization, + SoftwareAgent, + Annotation, + Relationship, + LifecycleScopedRelationship, + Bundle, + Bom, + SpdxDocument, +] + + +@pytest.mark.parametrize( + "clazz", + CLASS_LIST, +) +def test_correct_initialization(clazz): + clazz_instance = element_fixture_factory(clazz) + fixture_dict = get_fixture_dict(clazz) + + property_names = get_property_names(clazz) + + for property_name in property_names: + assert getattr(clazz_instance, property_name) is not None + assert getattr(clazz_instance, property_name) == fixture_dict[property_name] + + +@pytest.mark.parametrize( + "clazz", + CLASS_LIST, +) +def test_invalid_initialization(clazz): + property_names = get_property_names(clazz) + false_properties_dict = {} + for property_name in property_names: + false_properties_dict[property_name] = InvalidTypeClass() + + with pytest.raises(TypeError) as err: + element_fixture_factory(clazz, **false_properties_dict) + + assert len(err.value.args[0]) == len(property_names) + for error in err.value.args[0]: + assert error.startswith(f"SetterError {clazz.__name__}") + + +class InvalidTypeClass: + pass diff --git a/tests/spdx3/model/test_lifecycle_scoped_relationship.py b/tests/spdx3/model/test_lifecycle_scoped_relationship.py deleted file mode 100644 index 00e8a82fd..000000000 --- a/tests/spdx3/model/test_lifecycle_scoped_relationship.py +++ /dev/null @@ -1,55 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from datetime import datetime -from unittest import mock - -import pytest - -from spdx_tools.spdx3.model import ( - LifecycleScopedRelationship, - LifecycleScopeType, - RelationshipCompleteness, - RelationshipType, -) - - -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): - relationship = LifecycleScopedRelationship( - "SPDXRef-Relationship", - creation_information, - "spdx_id1", - RelationshipType.DESCRIBES, - ["spdx_id2", "spdx_id3"], - completeness=RelationshipCompleteness.NOASSERTION, - start_time=datetime(11, 11, 11), - end_time=datetime(12, 12, 12), - scope=LifecycleScopeType.DESIGN, - ) - - assert relationship.spdx_id == "SPDXRef-Relationship" - assert relationship.creation_info == creation_information - assert relationship.from_element == "spdx_id1" - assert relationship.to == ["spdx_id2", "spdx_id3"] - assert relationship.relationship_type == RelationshipType.DESCRIBES - assert relationship.completeness == RelationshipCompleteness.NOASSERTION - assert relationship.start_time == datetime(11, 11, 11) - assert relationship.end_time == datetime(12, 12, 12) - assert relationship.scope == LifecycleScopeType.DESIGN - - -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_invalid_initialization(creation_information): - with pytest.raises(TypeError) as err: - LifecycleScopedRelationship( - "SPDXRef-Relationship", - creation_information, - "spdx_id1", - RelationshipType.DESCRIBES, - 42, - ) - - assert err.value.args[0] == [ - 'SetterError LifecycleScopedRelationship: type of argument "to" must be a ' "list; got int instead: 42" - ] diff --git a/tests/spdx3/model/test_relationship.py b/tests/spdx3/model/test_relationship.py deleted file mode 100644 index aa99c268d..000000000 --- a/tests/spdx3/model/test_relationship.py +++ /dev/null @@ -1,55 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from datetime import datetime -from unittest import mock - -import pytest - -from spdx3.fixtures import relationship_fixture, ELEMENT_DICT, RELATIONSHIP_DICT -from spdx_tools.spdx3.model import Relationship, RelationshipCompleteness, RelationshipType - - -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): - relationship = relationship_fixture() - - local_dict = {} - local_dict.update(ELEMENT_DICT) - local_dict.update(RELATIONSHIP_DICT) - local_dict["spdx_id"] = "https://spdx.test/tools-python/relationship_fixture" - - keys = [ - attribute - for attribute in dir(Relationship) - if isinstance(getattr(Relationship, attribute), property) - ] - - for key in keys: - assert getattr(relationship, key) is not None - assert getattr(relationship, key) == local_dict[key] - - # assert relationship.spdx_id == "SPDXRef-Relationship" - # assert relationship.creation_info == creation_information - # assert relationship.from_element == "spdx_id1" - # assert relationship.to == ["spdx_id2", "spdx_id3"] - # assert relationship.relationship_type == RelationshipType.DESCRIBES - # assert relationship.completeness == RelationshipCompleteness.NOASSERTION - # assert relationship.start_time == datetime(11, 11, 11) - # assert relationship.end_time == datetime(12, 12, 12) - - -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_invalid_initialization(creation_information): - with pytest.raises(TypeError) as err: - Relationship("SPDXRef-Relationship", creation_information, 42, "Relationshiptype", 5, completeness=True) - - assert err.value.args[0] == [ - 'SetterError Relationship: type of argument "from_element" must be ' "str; got int instead: 42", - 'SetterError Relationship: type of argument "to" must be a list; got int ' "instead: 5", - 'SetterError Relationship: type of argument "relationship_type" must be ' - "spdx_tools.spdx3.model.relationship.RelationshipType; got str instead: Relationshiptype", - 'SetterError Relationship: type of argument "completeness" must be one of ' - "(spdx_tools.spdx3.model.relationship.RelationshipCompleteness, NoneType); got bool " - "instead: True", - ] diff --git a/tests/spdx3/model/test_spdx_document.py b/tests/spdx3/model/test_spdx_document.py deleted file mode 100644 index 95d1da741..000000000 --- a/tests/spdx3/model/test_spdx_document.py +++ /dev/null @@ -1,45 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from unittest import mock - -import pytest - -from spdx_tools.spdx3.model import SpdxDocument - - -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): - spdx_document = SpdxDocument( - "SPDXRef-DOCUMENT", creation_information, "Test document", element=["spdx_id1"], root_element=["spdx_id2"] - ) - - assert spdx_document.spdx_id == "SPDXRef-DOCUMENT" - assert spdx_document.creation_info == creation_information - assert spdx_document.name == "Test document" - assert spdx_document.element == ["spdx_id1"] - assert spdx_document.root_element == ["spdx_id2"] - - -def test_invalid_initialization(): - with pytest.raises(TypeError) as err: - SpdxDocument(1, {"info": 5}, "document name", element=[8], root_element=[]) - - assert err.value.args[0] == [ - 'SetterError SpdxDocument: type of argument "spdx_id" must be str; got int ' "instead: 1", - 'SetterError SpdxDocument: type of argument "creation_info" must be ' - "spdx_tools.spdx3.model.creation_information.CreationInformation; got dict " - "instead: {'info': 5}", - 'SetterError SpdxDocument: type of argument "element"[0] must be str; got int ' "instead: [8]", - ] - - -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_incomplete_initialization(creation_information): - with pytest.raises(TypeError) as err: - SpdxDocument("SPDXRef-Document", creation_information) - - assert ( - "__init__() missing 3 required positional arguments: 'name', 'element', and 'root_element'" - in err.value.args[0] - ) diff --git a/tests/spdx3/model/test_tool.py b/tests/spdx3/model/test_tool.py deleted file mode 100644 index 3c058fbbd..000000000 --- a/tests/spdx3/model/test_tool.py +++ /dev/null @@ -1,34 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from datetime import datetime - -import pytest -from semantic_version import Version - -from spdx_tools.spdx3.model import CreationInformation, ProfileIdentifier, Tool - - -def test_correct_initialization(): - agent = Tool( - "SPDXRef-Tool", - CreationInformation( - Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], [ProfileIdentifier.CORE], "CC0" - ), - ) - - assert agent.spdx_id == "SPDXRef-Tool" - assert agent.creation_info == CreationInformation( - Version("3.0.0"), datetime(2023, 1, 1), ["SPDXRef-Agent"], [], [ProfileIdentifier.CORE], "CC0" - ) - - -def test_invalid_initialization(): - with pytest.raises(TypeError) as err: - Tool(12, 345) - - assert err.value.args[0] == [ - 'SetterError Tool: type of argument "spdx_id" must be str; got int instead: 12', - 'SetterError Tool: type of argument "creation_info" must be ' - "spdx_tools.spdx3.model.creation_information.CreationInformation; got int instead: 345", - ] From 9dfc722ad9dcbcf83776beb94bc7c0f883f7f14f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Fri, 12 May 2023 11:06:43 +0200 Subject: [PATCH 218/354] [issue-432] add security profile fixtures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx3/fixtures.py | 146 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index a984992d4..b5c7b39e1 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -33,6 +33,21 @@ SpdxDocument, Tool, ) +from spdx_tools.spdx3.model.security import ( + CvssV2VulnAssessmentRelationship, + CvssV3VulnAssessmentRelationship, + EpssVulnAssessmentRelationship, + ExploitCatalogType, + ExploitCatalogVulnAssessmentRelationship, + SsvcDecisionType, + SsvcVulnAssessmentRelationship, + VexAffectedVulnAssessmentRelationship, + VexFixedVulnAssessmentRelationship, + VexJustificationType, + VexNotAffectedVulnAssessmentRelationship, + VexUnderInvestigationVulnAssessmentRelationship, + Vulnerability, +) from spdx_tools.spdx3.model.software import Sbom, SBOMType """Utility methods to create data model instances. All properties have valid defaults, so they don't need to be @@ -170,6 +185,78 @@ def namespace_map_fixture( "sbom_type": [SBOMType.BUILD], } +VULNERABILITY_DICT = { + "published_time": datetime(2010, 1, 1), + "modified_time": datetime(2011, 1, 1), + "withdrawn_time": datetime(2012, 1, 1), +} + +VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "assessed_element": "https://spdx.test/tools-python/assessed_element", + "published_time": datetime(2004, 1, 1), + "supplied_by": "https://spdx.test/tools-python/supplied_by", + "modified_time": datetime(2005, 1, 1), + "withdrawn_time": datetime(2006, 1, 1), +} + +CVSS_V2_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "score": "4.3", + "severity": "low", + "vector": "(AV:N/AC:M/Au:N/C:P/I:N/A:N)", + "relationship_type": RelationshipType.HAS_CVSS_V2_ASSESSMENT_FOR, +} + +CVSS_V3_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "score": "6.8", + "severity": "medium", + "vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N", + "relationship_type": RelationshipType.HAS_CVSS_V3_ASSESSMENT_FOR, +} + +EPSS_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "probability": 80, + "severity": "high", + "relationship_type": RelationshipType.HAS_EPSS_ASSESSMENT_FOR, +} + +SSVC_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "decision": SsvcDecisionType.ACT, + "relationship_type": RelationshipType.HAS_SSVC_ASSESSMENT_FOR, +} + +EXPLOIT_CATALOG_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "catalog_type": ExploitCatalogType.KEV, + "exploited": True, + "locator": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog", + "relationship_type": RelationshipType.HAS_EXPLOIT_CATALOG_ASSESSMENT_FOR, +} + +VEX_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "vex_version": "v4.2", + "status_notes": "some status notes", +} + +VEX_AFFECTED_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "action_statement": "Upgrade to version 1.4 of ACME application.", + "action_statement_time": [datetime(2015, 10, 15)], + "relationship_type": RelationshipType.AFFECTS, +} + +VEX_NOT_AFFECTED_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "justification": VexJustificationType.COMPONENT_NOT_PRESENT, + "impact_statement": "Not using this vulnerable part of this library.", + "impact_statement_time": datetime(2015, 10, 15), + "relationship_type": RelationshipType.DOES_NOT_AFFECT, +} + +VEX_UNDER_INVESTIGATION_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "relationship_type": RelationshipType.UNDER_INVESTIGATION_FOR, +} + +VEX_FIXED_VULN_ASSESSMENT_RELATIONSHIP_DICT = { + "relationship_type": RelationshipType.FIXED_IN, +} + FIXTURE_DICTS = { Agent: [ELEMENT_DICT], Person: [ELEMENT_DICT], @@ -183,6 +270,65 @@ def namespace_map_fixture( SpdxDocument: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT], Bom: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT], Sbom: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT, SBOM_DICT], + CvssV2VulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + CVSS_V2_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + CvssV3VulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + CVSS_V3_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + EpssVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + EPSS_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + ExploitCatalogVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + EXPLOIT_CATALOG_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + SsvcVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + SSVC_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + VexAffectedVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_AFFECTED_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + VexFixedVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_FIXED_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + VexNotAffectedVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_NOT_AFFECTED_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + VexUnderInvestigationVulnAssessmentRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_VULN_ASSESSMENT_RELATIONSHIP_DICT, + VEX_UNDER_INVESTIGATION_VULN_ASSESSMENT_RELATIONSHIP_DICT, + ], + Vulnerability: [ELEMENT_DICT, VULNERABILITY_DICT], } From 012d04f58ee75ae47fcac57f85c03bd8930b2137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Fri, 12 May 2023 14:52:14 +0200 Subject: [PATCH 219/354] [issue-426] add security profile tests and fix errors in security classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../cvss_v2_vuln_assessment_relationship.py | 4 ++-- .../cvss_v3_vuln_assessment_relationship.py | 4 ++-- .../ssvc_vuln_assessment_relationship.py | 4 ++-- ...t_affected_vuln_assessment_relationship.py | 4 ++-- tests/spdx3/model/test_element_subclasses.py | 22 +++++++++++++++++++ 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py index a7b250984..b24c1b885 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py @@ -19,7 +19,7 @@ @dataclass_with_properties class CvssV2VulnAssessmentRelationship(VulnAssessmentRelationship): - score: float = None + score: str = None severity: Optional[str] = None vector: Optional[str] = None @@ -30,7 +30,7 @@ def __init__( from_element: str, to: List[str], relationship_type: RelationshipType, - score: float, + score: str, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py index 77b77d119..d11170b13 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py @@ -19,7 +19,7 @@ @dataclass_with_properties class CvssV3VulnAssessmentRelationship(VulnAssessmentRelationship): - score: float = None + score: str = None severity: Optional[str] = None vector: Optional[str] = None @@ -30,7 +30,7 @@ def __init__( from_element: str, to: List[str], relationship_type: RelationshipType, - score: float, + score: str, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py index 81ed4c868..581f47572 100644 --- a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from enum import auto +from enum import Enum, auto from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties @@ -18,7 +18,7 @@ from spdx_tools.spdx.model import RelationshipType -class SsvcDecisionType: +class SsvcDecisionType(Enum): ACT = auto() ATTEND = auto() TRACK = auto() diff --git a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py index 593b591ef..570bb0fb7 100644 --- a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from enum import auto +from enum import Enum, auto from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties @@ -18,7 +18,7 @@ from spdx_tools.spdx.model import RelationshipType -class VexJustificationType: +class VexJustificationType(Enum): COMPONENT_NOT_PRESENT = auto() VULNERABLE_CODE_NOT_PRESENT = auto() VULNERABLE_CODE_CANNOT_BE_CONTROLLED_BY_ADVERSARY = auto() diff --git a/tests/spdx3/model/test_element_subclasses.py b/tests/spdx3/model/test_element_subclasses.py index 3225a3fc4..e0fdf0e50 100644 --- a/tests/spdx3/model/test_element_subclasses.py +++ b/tests/spdx3/model/test_element_subclasses.py @@ -17,6 +17,18 @@ SoftwareAgent, SpdxDocument, ) +from spdx_tools.spdx3.model.security import ( + CvssV2VulnAssessmentRelationship, + CvssV3VulnAssessmentRelationship, + EpssVulnAssessmentRelationship, + ExploitCatalogVulnAssessmentRelationship, + SsvcVulnAssessmentRelationship, + VexAffectedVulnAssessmentRelationship, + VexFixedVulnAssessmentRelationship, + VexNotAffectedVulnAssessmentRelationship, + VexUnderInvestigationVulnAssessmentRelationship, + Vulnerability, +) from tests.spdx3.fixtures import element_fixture_factory, get_fixture_dict @@ -39,6 +51,16 @@ def get_property_names(clazz: Type[Any]): Bundle, Bom, SpdxDocument, + CvssV2VulnAssessmentRelationship, + CvssV3VulnAssessmentRelationship, + EpssVulnAssessmentRelationship, + ExploitCatalogVulnAssessmentRelationship, + SsvcVulnAssessmentRelationship, + VexAffectedVulnAssessmentRelationship, + VexFixedVulnAssessmentRelationship, + VexNotAffectedVulnAssessmentRelationship, + VexUnderInvestigationVulnAssessmentRelationship, + Vulnerability, ] From 38428d24f5d2be5a5edf300f1ca522debf5c28fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 15 May 2023 11:05:19 +0200 Subject: [PATCH 220/354] [issue-432] add licensing fixtures and tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx3/fixtures.py | 50 ++++++++++++++++++- tests/spdx3/model/licensing/__init__.py | 0 .../licensing/test_conjunctive_license_set.py | 23 +++++++++ .../licensing/test_disjunctive_license_set.py | 23 +++++++++ .../model/licensing/test_or_later_operator.py | 22 ++++++++ .../licensing/test_with_addition_operator.py | 24 +++++++++ ... test_element_and_licensing_subclasses.py} | 16 ++++-- 7 files changed, 153 insertions(+), 5 deletions(-) create mode 100644 tests/spdx3/model/licensing/__init__.py create mode 100644 tests/spdx3/model/licensing/test_conjunctive_license_set.py create mode 100644 tests/spdx3/model/licensing/test_disjunctive_license_set.py create mode 100644 tests/spdx3/model/licensing/test_or_later_operator.py create mode 100644 tests/spdx3/model/licensing/test_with_addition_operator.py rename tests/spdx3/model/{test_element_subclasses.py => test_element_and_licensing_subclasses.py} (85%) diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index b5c7b39e1..992fb9b4e 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -33,6 +33,12 @@ SpdxDocument, Tool, ) +from spdx_tools.spdx3.model.licensing import ( + CustomLicense, + CustomLicenseAddition, + ListedLicense, + ListedLicenseException, +) from spdx_tools.spdx3.model.security import ( CvssV2VulnAssessmentRelationship, CvssV3VulnAssessmentRelationship, @@ -185,6 +191,41 @@ def namespace_map_fixture( "sbom_type": [SBOMType.BUILD], } +LICENSE_DICT = { + "license_id": "https://spdx.test/tools-python/license_id", + "license_name": "license name", + "license_text": "license text", + "license_comment": "license comment", + "see_also": ["https://see.also/license"], + "is_osi_approved": True, + "is_fsf_libre": True, + "standard_license_header": "license header", + "standard_license_template": "license template", + "is_deprecated_license_id": True, + "obsoleted_by": "https://spdx.test/tools-python/obsoleted_by_license_id", +} + +LISTED_LICENSE_DICT = { + "list_version_added": "2.1", + "deprecated_version": "2.2", +} + +LICENSE_ADDITION_DICT = { + "addition_id": "https://spdx.test/tools-python/addition_id", + "addition_name": "addition name", + "addition_text": "addition text", + "addition_comment": "addition comment", + "see_also": ["https://see.also/addition"], + "standard_addition_template": "addition template", + "is_deprecated_addition_id": True, + "obsoleted_by": "https://spdx.test/tools-python/obsoleted_by_addition_id", +} + +LISTED_LICENSE_EXCEPTION_DICT = { + "list_version_added": "2.1", + "deprecated_version": "2.2", +} + VULNERABILITY_DICT = { "published_time": datetime(2010, 1, 1), "modified_time": datetime(2011, 1, 1), @@ -270,6 +311,10 @@ def namespace_map_fixture( SpdxDocument: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT], Bom: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT], Sbom: [ELEMENT_DICT, ELEMENT_COLLECTION_DICT, BUNDLE_DICT, SBOM_DICT], + ListedLicense: [LICENSE_DICT, LISTED_LICENSE_DICT], + CustomLicense: [LICENSE_DICT], + ListedLicenseException: [LICENSE_ADDITION_DICT, LISTED_LICENSE_EXCEPTION_DICT], + CustomLicenseAddition: [LICENSE_ADDITION_DICT], CvssV2VulnAssessmentRelationship: [ ELEMENT_DICT, RELATIONSHIP_DICT, @@ -332,7 +377,7 @@ def namespace_map_fixture( } -def element_fixture_factory(clazz: Type[Any], **kwargs) -> Any: +def fixture_factory(clazz: Type[Any], **kwargs) -> Any: fixture_dict = get_fixture_dict(clazz) for key in kwargs.keys(): @@ -354,6 +399,7 @@ def get_fixture_dict(clazz: Type[Any]) -> Dict[str, Any]: for property_dict in FIXTURE_DICTS[clazz]: fixture_dict.update(property_dict) - fixture_dict["spdx_id"] = f"https://spdx.test/tools-python/{clazz.__name__}_fixture" + if "spdx_id" in fixture_dict.keys(): + fixture_dict["spdx_id"] = f"https://spdx.test/tools-python/{clazz.__name__}_fixture" return fixture_dict diff --git a/tests/spdx3/model/licensing/__init__.py b/tests/spdx3/model/licensing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/model/licensing/test_conjunctive_license_set.py b/tests/spdx3/model/licensing/test_conjunctive_license_set.py new file mode 100644 index 000000000..8a676041c --- /dev/null +++ b/tests/spdx3/model/licensing/test_conjunctive_license_set.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model.licensing import ConjunctiveLicenseSet, ListedLicense +from tests.spdx3.fixtures import fixture_factory + + +def test_valid_initialization(): + lic = fixture_factory(ListedLicense) + conjunctive_license_set = ConjunctiveLicenseSet([lic, lic]) + + assert conjunctive_license_set.member == [lic, lic] + + +def test_invalid_initialization(): + lic = fixture_factory(ListedLicense) + with pytest.raises(TypeError) as err: + ConjunctiveLicenseSet(lic) + + assert len(err.value.args[0]) == 1 + assert err.value.args[0][0].startswith("SetterError ConjunctiveLicenseSet:") diff --git a/tests/spdx3/model/licensing/test_disjunctive_license_set.py b/tests/spdx3/model/licensing/test_disjunctive_license_set.py new file mode 100644 index 000000000..f18bd6424 --- /dev/null +++ b/tests/spdx3/model/licensing/test_disjunctive_license_set.py @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model.licensing import DisjunctiveLicenseSet, ListedLicense +from tests.spdx3.fixtures import fixture_factory + + +def test_valid_initialization(): + lic = fixture_factory(ListedLicense) + disjunctive_license_set = DisjunctiveLicenseSet([lic, lic]) + + assert disjunctive_license_set.member == [lic, lic] + + +def test_invalid_initialization(): + lic = fixture_factory(ListedLicense) + with pytest.raises(TypeError) as err: + DisjunctiveLicenseSet(lic) + + assert len(err.value.args[0]) == 1 + assert err.value.args[0][0].startswith("SetterError DisjunctiveLicenseSet:") diff --git a/tests/spdx3/model/licensing/test_or_later_operator.py b/tests/spdx3/model/licensing/test_or_later_operator.py new file mode 100644 index 000000000..219307fa0 --- /dev/null +++ b/tests/spdx3/model/licensing/test_or_later_operator.py @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model.licensing import ListedLicense, OrLaterOperator +from tests.spdx3.fixtures import fixture_factory + + +def test_valid_initialization(): + lic = fixture_factory(ListedLicense) + or_later_operator = OrLaterOperator(lic) + + assert or_later_operator.subject_license == lic + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + OrLaterOperator("License") + + assert len(err.value.args[0]) == 1 + assert err.value.args[0][0].startswith("SetterError OrLaterOperator:") diff --git a/tests/spdx3/model/licensing/test_with_addition_operator.py b/tests/spdx3/model/licensing/test_with_addition_operator.py new file mode 100644 index 000000000..388aca27f --- /dev/null +++ b/tests/spdx3/model/licensing/test_with_addition_operator.py @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx3.model.licensing import ListedLicense, ListedLicenseException, WithAdditionOperator +from tests.spdx3.fixtures import fixture_factory + + +def test_valid_initialization(): + lic = fixture_factory(ListedLicense) + lic_addition = fixture_factory(ListedLicenseException) + with_addition_operator = WithAdditionOperator(lic, lic_addition) + + assert with_addition_operator.subject_license == lic + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + WithAdditionOperator("License", "LicenseAddition") + + assert len(err.value.args[0]) == 2 + for arg in err.value.args[0]: + assert arg.startswith("SetterError WithAdditionOperator:") diff --git a/tests/spdx3/model/test_element_subclasses.py b/tests/spdx3/model/test_element_and_licensing_subclasses.py similarity index 85% rename from tests/spdx3/model/test_element_subclasses.py rename to tests/spdx3/model/test_element_and_licensing_subclasses.py index e0fdf0e50..5aa9dc678 100644 --- a/tests/spdx3/model/test_element_subclasses.py +++ b/tests/spdx3/model/test_element_and_licensing_subclasses.py @@ -17,6 +17,12 @@ SoftwareAgent, SpdxDocument, ) +from spdx_tools.spdx3.model.licensing import ( + CustomLicense, + CustomLicenseAddition, + ListedLicense, + ListedLicenseException, +) from spdx_tools.spdx3.model.security import ( CvssV2VulnAssessmentRelationship, CvssV3VulnAssessmentRelationship, @@ -29,7 +35,7 @@ VexUnderInvestigationVulnAssessmentRelationship, Vulnerability, ) -from tests.spdx3.fixtures import element_fixture_factory, get_fixture_dict +from tests.spdx3.fixtures import fixture_factory, get_fixture_dict def get_property_names(clazz: Type[Any]): @@ -51,6 +57,10 @@ def get_property_names(clazz: Type[Any]): Bundle, Bom, SpdxDocument, + ListedLicense, + CustomLicense, + ListedLicenseException, + CustomLicenseAddition, CvssV2VulnAssessmentRelationship, CvssV3VulnAssessmentRelationship, EpssVulnAssessmentRelationship, @@ -69,7 +79,7 @@ def get_property_names(clazz: Type[Any]): CLASS_LIST, ) def test_correct_initialization(clazz): - clazz_instance = element_fixture_factory(clazz) + clazz_instance = fixture_factory(clazz) fixture_dict = get_fixture_dict(clazz) property_names = get_property_names(clazz) @@ -90,7 +100,7 @@ def test_invalid_initialization(clazz): false_properties_dict[property_name] = InvalidTypeClass() with pytest.raises(TypeError) as err: - element_fixture_factory(clazz, **false_properties_dict) + fixture_factory(clazz, **false_properties_dict) assert len(err.value.args[0]) == len(property_names) for error in err.value.args[0]: From 12da053d34645292a85e6ffa252751dde486e131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 16 May 2023 11:51:35 +0200 Subject: [PATCH 221/354] fix tests after typeguard update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx3/model/ai/test_ai_package.py | 9 +++----- tests/spdx3/model/build/test_build.py | 9 +++----- tests/spdx3/model/dataset/test_dataset.py | 9 +++----- tests/spdx3/model/software/test_file.py | 14 +++---------- tests/spdx3/model/software/test_package.py | 21 +++---------------- tests/spdx3/model/software/test_sbom.py | 9 +++----- tests/spdx3/model/software/test_snippet.py | 9 +++----- .../test_software_dependency_relationship.py | 6 +++--- .../spdx3/model/test_creation_information.py | 13 +++--------- tests/spdx3/model/test_external_identifier.py | 16 +++----------- tests/spdx3/model/test_external_map.py | 8 +++---- tests/spdx3/model/test_external_reference.py | 13 +++--------- tests/spdx3/model/test_hash.py | 8 +++---- tests/spdx3/model/test_namespace_map.py | 8 +++---- 14 files changed, 42 insertions(+), 110 deletions(-) diff --git a/tests/spdx3/model/ai/test_ai_package.py b/tests/spdx3/model/ai/test_ai_package.py index d7b1c2c75..70e8a047f 100644 --- a/tests/spdx3/model/ai/test_ai_package.py +++ b/tests/spdx3/model/ai/test_ai_package.py @@ -76,9 +76,6 @@ def test_invalid_initialization(creation_information): metric={"metric1": "value", "metric2": 250}, ) - assert err.value.args[0] == [ - ( - "SetterError AIPackage: type of argument \"metric\"['metric2'] must be one of " - "(str, NoneType); got int instead: {'metric1': 'value', 'metric2': 250}" - ) - ] + assert len(err.value.args[0]) == 1 + for error in err.value.args[0]: + assert error.startswith("SetterError AIPackage:") diff --git a/tests/spdx3/model/build/test_build.py b/tests/spdx3/model/build/test_build.py index a3b1ddfec..22d214853 100644 --- a/tests/spdx3/model/build/test_build.py +++ b/tests/spdx3/model/build/test_build.py @@ -47,9 +47,6 @@ def test_invalid_initialization(creation_information): config_source_digest=["hash_value"], ) - assert err.value.args[0] == [ - ( - "SetterError Build: type of argument \"config_source_digest\"[0] must be spdx_tools.spdx3.model.hash.Hash;" - " got str instead: ['hash_value']" - ) - ] + assert len(err.value.args[0]) == 1 + for error in err.value.args[0]: + assert error.startswith("SetterError Build:") diff --git a/tests/spdx3/model/dataset/test_dataset.py b/tests/spdx3/model/dataset/test_dataset.py index 663d0e862..22cce21da 100644 --- a/tests/spdx3/model/dataset/test_dataset.py +++ b/tests/spdx3/model/dataset/test_dataset.py @@ -72,9 +72,6 @@ def test_invalid_initialization(creation_information): sensor={"sensor1": "value", "sensor2": 250}, ) - assert err.value.args[0] == [ - ( - "SetterError Dataset: type of argument \"sensor\"['sensor2'] must be one of " - "(str, NoneType); got int instead: {'sensor1': 'value', 'sensor2': 250}" - ) - ] + assert len(err.value.args[0]) == 1 + for error in err.value.args[0]: + assert error.startswith("SetterError Dataset:") diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index cf454cc33..8cdd3611d 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -40,14 +40,6 @@ def test_invalid_initialization(creation_information): content_type=SoftwarePurpose.ARCHIVE, ) - assert err.value.args[0] == [ - 'SetterError File: type of argument "spdx_id" must be str; got int instead: 1', - 'SetterError File: type of argument "content_identifier" must be one of (str, ' - "NoneType); got int instead: 3", - 'SetterError File: type of argument "purpose" must be a list; got ' - "spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose instead: " - "SoftwarePurpose.FILE", - 'SetterError File: type of argument "content_type" must be one of (str, ' - "NoneType); got spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose " - "instead: SoftwarePurpose.ARCHIVE", - ] + assert len(err.value.args[0]) == 4 + for error in err.value.args[0]: + assert error.startswith("SetterError File:") diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 0b9b465c6..384d1bd46 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -65,21 +65,6 @@ def test_invalid_initialization(creation_information): source_info=["some info"], ) - assert err.value.args[0] == [ - 'SetterError Package: type of argument "built_time" must be one of ' - "(datetime.datetime, NoneType); got str instead: 2022-03-04T00:00:00Z", - 'SetterError Package: type of argument "content_identifier" must be one of ' - "(str, NoneType); got int instead: 3", - 'SetterError Package: type of argument "purpose" must be a list; got ' - "spdx_tools.spdx3.model.software.software_purpose.SoftwarePurpose instead: " - "SoftwarePurpose.FILE", - 'SetterError Package: type of argument "package_version" must be one of ' - "(str, NoneType); got int instead: 42", - 'SetterError Package: type of argument "download_location" must be one of ' - "(str, NoneType); got int instead: 4", - 'SetterError Package: type of argument "package_url" must be one of (str, ' - "NoneType); got list instead: ['uris']", - 'SetterError Package: type of argument "homepage" must be one of (str, ' "NoneType); got bool instead: True", - 'SetterError Package: type of argument "source_info" must be one of (str, ' - "NoneType); got list instead: ['some info']", - ] + assert len(err.value.args[0]) == 8 + for error in err.value.args[0]: + assert error.startswith("SetterError Package:") diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index 2a1218872..1264e8121 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -29,9 +29,6 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: Sbom(2, {"creation_info": [3, 4, 5]}, element=[], root_element=[]) - assert err.value.args[0] == [ - 'SetterError Sbom: type of argument "spdx_id" must be str; got int instead: 2', - 'SetterError Sbom: type of argument "creation_info" must be ' - "spdx_tools.spdx3.model.creation_information.CreationInformation; got dict " - "instead: {'creation_info': [3, 4, 5]}", - ] + assert len(err.value.args[0]) == 2 + for error in err.value.args[0]: + assert error.startswith("SetterError Sbom:") diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index ae123bb4c..7a3e480a3 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -32,9 +32,6 @@ def test_invalid_initialization(creation_information): with pytest.raises(TypeError) as err: Snippet(2, creation_information, originated_by=34, byte_range="34:45") - assert err.value.args[0] == [ - 'SetterError Snippet: type of argument "spdx_id" must be str; got int ' "instead: 2", - 'SetterError Snippet: type of argument "originated_by" must be a list; got ' "int instead: 34", - 'SetterError Snippet: type of argument "byte_range" must be one of ' - "(Tuple[int, int], NoneType); got str instead: 34:45", - ] + assert len(err.value.args[0]) == 3 + for error in err.value.args[0]: + assert error.startswith("SetterError Snippet:") diff --git a/tests/spdx3/model/software/test_software_dependency_relationship.py b/tests/spdx3/model/software/test_software_dependency_relationship.py index 6c1a4472b..7d6e0697c 100644 --- a/tests/spdx3/model/software/test_software_dependency_relationship.py +++ b/tests/spdx3/model/software/test_software_dependency_relationship.py @@ -54,6 +54,6 @@ def test_invalid_initialization(creation_information): 42, ) - assert err.value.args[0] == [ - 'SetterError SoftwareDependencyRelationship: type of argument "to" must be a ' "list; got int instead: 42" - ] + assert len(err.value.args[0]) == 1 + for error in err.value.args[0]: + assert error.startswith("SetterError SoftwareDependencyRelationship:") diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py index 240348cc4..6a1b28e8d 100644 --- a/tests/spdx3/model/test_creation_information.py +++ b/tests/spdx3/model/test_creation_information.py @@ -33,16 +33,9 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: CreationInformation("2.3", "2012-01-01", [], [], "core", 3, []) - assert err.value.args[0] == [ - 'SetterError CreationInformation: type of argument "spec_version" must be ' - "semantic_version.base.Version; got str instead: 2.3", - 'SetterError CreationInformation: type of argument "created" must be ' - "datetime.datetime; got str instead: 2012-01-01", - 'SetterError CreationInformation: type of argument "profile" must be a list; ' "got str instead: core", - 'SetterError CreationInformation: type of argument "data_license" must be ' "str; got int instead: 3", - 'SetterError CreationInformation: type of argument "comment" must be' - " one of (str, NoneType); got list instead: []", - ] + assert len(err.value.args[0]) == 5 + for error in err.value.args[0]: + assert error.startswith("SetterError CreationInformation:") def test_incomplete_initialization(): diff --git a/tests/spdx3/model/test_external_identifier.py b/tests/spdx3/model/test_external_identifier.py index d25dad3bb..098851765 100644 --- a/tests/spdx3/model/test_external_identifier.py +++ b/tests/spdx3/model/test_external_identifier.py @@ -27,16 +27,6 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: ExternalIdentifier("CPE22", ["identifier", "another_identifier"], 34, "locator", True) - assert err.value.args[0] == [ - 'SetterError ExternalIdentifier: type of argument "external_identifier_type" ' - "must be spdx_tools.spdx3.model.external_identifier.ExternalIdentifierType; got str " - "instead: CPE22", - 'SetterError ExternalIdentifier: type of argument "identifier" must be str; ' - "got list instead: ['identifier', 'another_identifier']", - 'SetterError ExternalIdentifier: type of argument "comment" must be one of ' - "(str, NoneType); got int instead: 34", - 'SetterError ExternalIdentifier: type of argument "identifier_locator" must ' - "be a list; got str instead: locator", - 'SetterError ExternalIdentifier: type of argument "issuing_authority" must be ' - "one of (str, NoneType); got bool instead: True", - ] + assert len(err.value.args[0]) == 5 + for error in err.value.args[0]: + assert error.startswith("SetterError ExternalIdentifier:") diff --git a/tests/spdx3/model/test_external_map.py b/tests/spdx3/model/test_external_map.py index c925dade2..396a02e8b 100644 --- a/tests/spdx3/model/test_external_map.py +++ b/tests/spdx3/model/test_external_map.py @@ -21,8 +21,6 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: ExternalMap(234, None, ["location hints"]) - assert err.value.args[0] == [ - 'SetterError ExternalMap: type of argument "external_id" must be str; got int ' "instead: 234", - 'SetterError ExternalMap: type of argument "location_hint" must be one of ' - "(str, NoneType); got list instead: ['location hints']", - ] + assert len(err.value.args[0]) == 2 + for error in err.value.args[0]: + assert error.startswith("SetterError ExternalMap:") diff --git a/tests/spdx3/model/test_external_reference.py b/tests/spdx3/model/test_external_reference.py index ebee27713..0d2971493 100644 --- a/tests/spdx3/model/test_external_reference.py +++ b/tests/spdx3/model/test_external_reference.py @@ -20,13 +20,6 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: ExternalReference("OTHER", "a URI", 34, True) - assert err.value.args[0] == [ - 'SetterError ExternalReference: type of argument "external_reference_type" ' - "must be one of (spdx_tools.spdx3.model.external_reference.ExternalReferenceType, " - "NoneType); got str instead: OTHER", - 'SetterError ExternalReference: type of argument "locator" must be a list; ' "got str instead: a URI", - 'SetterError ExternalReference: type of argument "content_type" must be one ' - "of (str, NoneType); got int instead: 34", - 'SetterError ExternalReference: type of argument "comment" must be one of ' - "(str, NoneType); got bool instead: True", - ] + assert len(err.value.args[0]) == 4 + for error in err.value.args[0]: + assert error.startswith("SetterError ExternalReference:") diff --git a/tests/spdx3/model/test_hash.py b/tests/spdx3/model/test_hash.py index 1cfc4f117..e8ecd9f96 100644 --- a/tests/spdx3/model/test_hash.py +++ b/tests/spdx3/model/test_hash.py @@ -17,8 +17,6 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: Hash("SHA1", 345) - assert err.value.args[0] == [ - 'SetterError Hash: type of argument "algorithm" must be ' - "spdx_tools.spdx3.model.hash.HashAlgorithm; got str instead: SHA1", - 'SetterError Hash: type of argument "hash_value" must be str; got int ' "instead: 345", - ] + assert len(err.value.args[0]) == 2 + for error in err.value.args[0]: + assert error.startswith("SetterError Hash:") diff --git a/tests/spdx3/model/test_namespace_map.py b/tests/spdx3/model/test_namespace_map.py index 0217bff18..f615335bc 100644 --- a/tests/spdx3/model/test_namespace_map.py +++ b/tests/spdx3/model/test_namespace_map.py @@ -17,8 +17,6 @@ def test_invalid_initialization(): with pytest.raises(TypeError) as err: NamespaceMap(34, ["list of namespaces"]) - assert err.value.args[0] == [ - 'SetterError NamespaceMap: type of argument "prefix" must be one of (str, ' "NoneType); got int instead: 34", - 'SetterError NamespaceMap: type of argument "namespace" must be one of (str, ' - "NoneType); got list instead: ['list of namespaces']", - ] + assert len(err.value.args[0]) == 2 + for error in err.value.args[0]: + assert error.startswith("SetterError NamespaceMap:") From 7eee6d7b0b8a3c71b3302b4388f53dea3a0a8b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 16 May 2023 09:20:06 +0200 Subject: [PATCH 222/354] [issue-427] fix external document ref bumping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../bump_from_spdx2/creation_information.py | 13 ++++--- .../bump_from_spdx2/external_document_ref.py | 11 +++--- .../bump/test_external_document_ref_bump.py | 36 +++++++++++++++++++ 3 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 tests/spdx3/bump/test_external_document_ref_bump.py diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py index 01841bdf2..0c172a644 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py @@ -23,10 +23,14 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: print_missing_conversion("creation_info.document_namespace", 0, "https://github.com/spdx/spdx-3-model/issues/87") # creation_info.external_document_refs -> spdx_document.imports - imports = [ - bump_external_document_ref(external_document_ref) - for external_document_ref in spdx2_creation_info.external_document_refs - ] + namespaces, imports = zip( + *[ + bump_external_document_ref(external_document_ref) + for external_document_ref in spdx2_creation_info.external_document_refs + ] + ) + namespaces = list(namespaces) + imports = list(imports) # creation_info.license_list_version -> ? print_missing_conversion( "creation_info.license_list_version", @@ -76,4 +80,5 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: element=[], root_element=[], imports=imports, + namespaces=namespaces, ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py b/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py index 10cfdd530..1e496aa16 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py @@ -1,18 +1,17 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from typing import List, Tuple from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum -from spdx_tools.spdx3.model import ExternalMap, Hash +from spdx_tools.spdx3.model import ExternalMap, Hash, NamespaceMap from spdx_tools.spdx.model.external_document_ref import ExternalDocumentRef -def bump_external_document_ref(external_document_ref: ExternalDocumentRef) -> ExternalMap: +def bump_external_document_ref(external_document_ref: ExternalDocumentRef) -> Tuple[NamespaceMap, ExternalMap]: verified_using: List[Hash] = [bump_checksum(external_document_ref.checksum)] - return ExternalMap( - external_id=external_document_ref.document_ref_id, + return NamespaceMap(external_document_ref.document_ref_id, external_document_ref.document_uri + "#"), ExternalMap( + external_id=f"{external_document_ref.document_ref_id}:SPDXRef-DOCUMENT", verified_using=verified_using, - location_hint=external_document_ref.document_uri, ) diff --git a/tests/spdx3/bump/test_external_document_ref_bump.py b/tests/spdx3/bump/test_external_document_ref_bump.py new file mode 100644 index 000000000..ebbe1d521 --- /dev/null +++ b/tests/spdx3/bump/test_external_document_ref_bump.py @@ -0,0 +1,36 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.bump_from_spdx2.creation_information import bump_creation_information +from spdx_tools.spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import ExternalDocumentRef +from tests.spdx.fixtures import checksum_fixture, creation_info_fixture, external_document_ref_fixture + + +def test_bump_external_document_ref(): + checksum = checksum_fixture() + external_document_ref = ExternalDocumentRef("DocumentRef-external", "https://external.uri", checksum) + namespace_map, imports = bump_external_document_ref(external_document_ref) + + assert namespace_map.prefix == "DocumentRef-external" + assert namespace_map.namespace == "https://external.uri#" + + assert imports.external_id == "DocumentRef-external:SPDXRef-DOCUMENT" + assert imports.verified_using == [bump_checksum(checksum)] + + +def test_bump_multiple_external_document_refs(): + payload = Payload() + creation_info = creation_info_fixture( + external_document_refs=[ + external_document_ref_fixture("DocumentRef-external1", "https://external.uri1"), + external_document_ref_fixture("DocumentRef-external2", "https://external.uri2"), + ] + ) + spdx_document = bump_creation_information(creation_info, payload) + + assert len(spdx_document.imports) == 2 + assert len(spdx_document.namespaces) == 2 From 4befa030391f3df1b50d63da3ba2765397456871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 16 May 2023 12:29:23 +0200 Subject: [PATCH 223/354] delete property migration comments from bumping functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py | 5 ----- src/spdx_tools/spdx3/bump_from_spdx2/file.py | 2 -- src/spdx_tools/spdx3/bump_from_spdx2/package.py | 4 ---- 3 files changed, 11 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py index 0c172a644..b5b882f25 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py @@ -15,14 +15,11 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload) -> SpdxDocument: - # creation_info.spdx_id -> spdx_document.spdx_id document_namespace = spdx2_creation_info.document_namespace spdx_id = f"{document_namespace}#{spdx2_creation_info.spdx_id}" - # creation_info.document_namespace -> ? print_missing_conversion("creation_info.document_namespace", 0, "https://github.com/spdx/spdx-3-model/issues/87") - # creation_info.external_document_refs -> spdx_document.imports namespaces, imports = zip( *[ bump_external_document_ref(external_document_ref) @@ -31,13 +28,11 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: ) namespaces = list(namespaces) imports = list(imports) - # creation_info.license_list_version -> ? print_missing_conversion( "creation_info.license_list_version", 0, "part of licensing profile, " "https://github.com/spdx/spdx-3-model/issues/131", ) - # creation_info.document_comment -> spdx_document.comment document_comment = spdx2_creation_info.document_comment creation_information = CreationInformation( spec_version=Version("3.0.0"), diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/file.py b/src/spdx_tools/spdx3/bump_from_spdx2/file.py index 88a0d7f75..9a5ba69bb 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/file.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/file.py @@ -20,8 +20,6 @@ def bump_file( ): spdx_id = "#".join([document_namespace, spdx2_file.spdx_id]) integrity_methods = [bump_checksum(checksum) for checksum in spdx2_file.checksums] - # file.checksums -> file.verifiedUsing - # file.file_types -> file.content_type (MediaType with Cardinality 1) print_missing_conversion( "file.file_type", 0, "different cardinalities, " "https://github.com/spdx/spdx-3-model/issues/82" ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index 75f10c50d..c9c2235e4 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -32,7 +32,6 @@ def bump_package( ): spdx_id = "#".join([document_namespace, spdx2_package.spdx_id]) download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") - # package.file_name -> ? print_missing_conversion("package2.file_name", 0, "https://github.com/spdx/spdx-3-model/issues/83") if isinstance(spdx2_package.supplier, Spdx2_Actor): supplied_by_spdx_id = [bump_actor(spdx2_package.supplier, payload, creation_information, document_namespace)] @@ -44,13 +43,10 @@ def bump_package( ] else: originated_by_spdx_id = None - # package.files_analyzed -> ? print_missing_conversion("package2.files_analyzed", 0, "https://github.com/spdx/spdx-3-model/issues/84") - # package.verification_code -> package.verified_using print_missing_conversion( "package2.verification_code", 1, "of IntegrityMethod, https://github.com/spdx/spdx-3-model/issues/85" ) - # package.checksums -> package.verified_using integrity_methods = [bump_checksum(checksum) for checksum in spdx2_package.checksums] declared_license = bump_license_expression_or_none_or_no_assertion( spdx2_package.license_declared, extracted_licensing_info From 46aebee0299bb613bbdcc90d549f41acaf47282f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 17 May 2023 09:30:17 +0200 Subject: [PATCH 224/354] [issue-432] use fixtures in initialization tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx3/model/model_test_utils.py | 16 ++++++++++ .../spdx3/model/test_creation_information.py | 31 ++++++++++--------- .../test_element_and_licensing_subclasses.py | 20 ++---------- tests/spdx3/model/test_external_identifier.py | 28 +++++++++-------- tests/spdx3/model/test_external_map.py | 17 +++++----- tests/spdx3/model/test_external_reference.py | 18 ++++++----- tests/spdx3/model/test_hash.py | 10 ++++-- tests/spdx3/model/test_namespace_map.py | 11 +++++-- 8 files changed, 86 insertions(+), 65 deletions(-) create mode 100644 tests/spdx3/model/model_test_utils.py diff --git a/tests/spdx3/model/model_test_utils.py b/tests/spdx3/model/model_test_utils.py new file mode 100644 index 000000000..174d8ce40 --- /dev/null +++ b/tests/spdx3/model/model_test_utils.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import Any, List, Type + + +def get_property_names(clazz: Type[Any]) -> List[str]: + return [ + attribute + for attribute in dir(clazz) + if not attribute.startswith("_") and not callable(getattr(clazz, attribute)) + ] + + +class InvalidTypeClass: + pass diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py index 6a1b28e8d..a86d08d7a 100644 --- a/tests/spdx3/model/test_creation_information.py +++ b/tests/spdx3/model/test_creation_information.py @@ -7,26 +7,27 @@ from semantic_version import Version from spdx_tools.spdx3.model import CreationInformation, ProfileIdentifier +from tests.spdx3.fixtures import creation_info_fixture +from tests.spdx3.model.model_test_utils import get_property_names def test_correct_initialization(): - creation_information = CreationInformation( - Version("3.0.0"), - datetime(2023, 1, 11, 16, 21), - [], - [], - [ProfileIdentifier.CORE, ProfileIdentifier.SOFTWARE], - "CC0", - "some comment", - ) + creation_information = creation_info_fixture() + + for property_name in get_property_names(CreationInformation): + assert getattr(creation_information, property_name) is not None assert creation_information.spec_version == Version("3.0.0") - assert creation_information.created == datetime(2023, 1, 11, 16, 21) - assert creation_information.created_by == [] - assert creation_information.created_using == [] - assert creation_information.profile == [ProfileIdentifier.CORE, ProfileIdentifier.SOFTWARE] - assert creation_information.data_license == "CC0" - assert creation_information.comment == "some comment" + assert creation_information.created == datetime(2022, 12, 1) + assert creation_information.created_by == ["https://spdx.test/tools-python/creation_info_created_by"] + assert creation_information.created_using == ["https://spdx.test/tools-python/creation_info_created_using"] + assert creation_information.profile == [ + ProfileIdentifier.CORE, + ProfileIdentifier.SOFTWARE, + ProfileIdentifier.LICENSING, + ] + assert creation_information.data_license == "CC0-1.0" + assert creation_information.comment == "creationInfoComment" def test_invalid_initialization(): diff --git a/tests/spdx3/model/test_element_and_licensing_subclasses.py b/tests/spdx3/model/test_element_and_licensing_subclasses.py index 5aa9dc678..d9413bf7b 100644 --- a/tests/spdx3/model/test_element_and_licensing_subclasses.py +++ b/tests/spdx3/model/test_element_and_licensing_subclasses.py @@ -1,8 +1,6 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Type - import pytest from spdx_tools.spdx3.model import ( @@ -36,15 +34,7 @@ Vulnerability, ) from tests.spdx3.fixtures import fixture_factory, get_fixture_dict - - -def get_property_names(clazz: Type[Any]): - return [ - attribute - for attribute in dir(clazz) - if not attribute.startswith("_") and not callable(getattr(clazz, attribute)) - ] - +from tests.spdx3.model.model_test_utils import InvalidTypeClass, get_property_names CLASS_LIST = [ Agent, @@ -82,9 +72,7 @@ def test_correct_initialization(clazz): clazz_instance = fixture_factory(clazz) fixture_dict = get_fixture_dict(clazz) - property_names = get_property_names(clazz) - - for property_name in property_names: + for property_name in get_property_names(clazz): assert getattr(clazz_instance, property_name) is not None assert getattr(clazz_instance, property_name) == fixture_dict[property_name] @@ -105,7 +93,3 @@ def test_invalid_initialization(clazz): assert len(err.value.args[0]) == len(property_names) for error in err.value.args[0]: assert error.startswith(f"SetterError {clazz.__name__}") - - -class InvalidTypeClass: - pass diff --git a/tests/spdx3/model/test_external_identifier.py b/tests/spdx3/model/test_external_identifier.py index 098851765..c006dfda5 100644 --- a/tests/spdx3/model/test_external_identifier.py +++ b/tests/spdx3/model/test_external_identifier.py @@ -1,26 +1,28 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from unittest import TestCase - import pytest from spdx_tools.spdx3.model import ExternalIdentifier, ExternalIdentifierType +from tests.spdx3.fixtures import external_identifier_fixture +from tests.spdx3.model.model_test_utils import get_property_names def test_correct_initialization(): - external_identifier = ExternalIdentifier( - ExternalIdentifierType.CPE22, - "cpe:/o:canonical:ubuntu_linux:10.04:-:lts", - "This is a comment", - ["first locator", "second locator"], - "authority", + external_identifier = external_identifier_fixture() + + for property_name in get_property_names(ExternalIdentifier): + assert getattr(external_identifier, property_name) is not None + + assert external_identifier.external_identifier_type == ExternalIdentifierType.OTHER + assert external_identifier.identifier == "externalIdentifierIdentifier" + assert external_identifier.comment == "externalIdentifierComment" + assert external_identifier.identifier_locator == [ + "https://spdx.test/tools-python/external_identifier_identifier_locator" + ] + assert ( + external_identifier.issuing_authority == "https://spdx.test/tools-python/external_identifier_issuing_authority" ) - assert external_identifier.external_identifier_type == ExternalIdentifierType.CPE22 - assert external_identifier.identifier == "cpe:/o:canonical:ubuntu_linux:10.04:-:lts" - assert external_identifier.comment == "This is a comment" - TestCase().assertCountEqual(external_identifier.identifier_locator, ["first locator", "second locator"]) - assert external_identifier.issuing_authority == "authority" def test_invalid_initialization(): diff --git a/tests/spdx3/model/test_external_map.py b/tests/spdx3/model/test_external_map.py index 396a02e8b..7a2865cd6 100644 --- a/tests/spdx3/model/test_external_map.py +++ b/tests/spdx3/model/test_external_map.py @@ -1,20 +1,23 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from unittest import mock import pytest from spdx_tools.spdx3.model import ExternalMap +from tests.spdx3.fixtures import external_map_fixture, hash_fixture +from tests.spdx3.model.model_test_utils import get_property_names -@mock.patch("spdx_tools.spdx3.model.IntegrityMethod", autospec=True) -def test_correct_initialization(integrity_method): - external_map = ExternalMap("https://external.id", [integrity_method], "https://location.hint") +def test_correct_initialization(): + external_map = external_map_fixture() - assert external_map.external_id == "https://external.id" - assert external_map.verified_using == [integrity_method] - assert external_map.location_hint == "https://location.hint" + for property_name in get_property_names(ExternalMap): + assert getattr(external_map, property_name) is not None + + assert external_map.external_id == "https://spdx.test/tools-python/external_map_external_id" + assert external_map.verified_using == [hash_fixture()] + assert external_map.location_hint == "https://spdx.test/tools-python/external_map_location_hint" def test_invalid_initialization(): diff --git a/tests/spdx3/model/test_external_reference.py b/tests/spdx3/model/test_external_reference.py index 0d2971493..91dac9fb8 100644 --- a/tests/spdx3/model/test_external_reference.py +++ b/tests/spdx3/model/test_external_reference.py @@ -4,16 +4,20 @@ import pytest from spdx_tools.spdx3.model import ExternalReference, ExternalReferenceType +from tests.spdx3.fixtures import external_reference_fixture +from tests.spdx3.model.model_test_utils import get_property_names def test_correct_initialization(): - external_reference = ExternalReference( - ExternalReferenceType.SECURITY_ADVISORY, ["https://anyURI"], "MediaType", "This is a comment" - ) - assert external_reference.external_reference_type == ExternalReferenceType.SECURITY_ADVISORY - assert external_reference.locator == ["https://anyURI"] - assert external_reference.content_type == "MediaType" - assert external_reference.comment == "This is a comment" + external_reference = external_reference_fixture() + + for property_name in get_property_names(ExternalReference): + assert getattr(external_reference, property_name) is not None + + assert external_reference.external_reference_type == ExternalReferenceType.OTHER + assert external_reference.locator == ["org.apache.tomcat:tomcat:9.0.0.M4"] + assert external_reference.content_type == "externalReferenceContentType" + assert external_reference.comment == "externalReferenceComment" def test_invalid_initialization(): diff --git a/tests/spdx3/model/test_hash.py b/tests/spdx3/model/test_hash.py index e8ecd9f96..8994e1a7c 100644 --- a/tests/spdx3/model/test_hash.py +++ b/tests/spdx3/model/test_hash.py @@ -4,13 +4,19 @@ import pytest from spdx_tools.spdx3.model import Hash, HashAlgorithm +from tests.spdx3.fixtures import hash_fixture +from tests.spdx3.model.model_test_utils import get_property_names def test_correct_initialization(): - hash = Hash(algorithm=HashAlgorithm.SHA1, hash_value="value") + hash = hash_fixture() + + for property_name in get_property_names(Hash): + assert getattr(hash, property_name) is not None assert hash.algorithm == HashAlgorithm.SHA1 - assert hash.hash_value == "value" + assert hash.hash_value == "71c4025dd9897b364f3ebbb42c484ff43d00791c" + assert hash.comment == "hashComment" def test_invalid_initialization(): diff --git a/tests/spdx3/model/test_namespace_map.py b/tests/spdx3/model/test_namespace_map.py index f615335bc..a0e430162 100644 --- a/tests/spdx3/model/test_namespace_map.py +++ b/tests/spdx3/model/test_namespace_map.py @@ -4,13 +4,18 @@ import pytest from spdx_tools.spdx3.model import NamespaceMap +from tests.spdx3.fixtures import namespace_map_fixture +from tests.spdx3.model.model_test_utils import get_property_names def test_correct_initialization(): - namespace_map = NamespaceMap("some prefix", "https://namespace") + namespace_map = namespace_map_fixture() - assert namespace_map.prefix == "some prefix" - assert namespace_map.namespace == "https://namespace" + for property_name in get_property_names(NamespaceMap): + assert getattr(namespace_map, property_name) is not None + + assert namespace_map.prefix == "namespaceMapPrefix" + assert namespace_map.namespace == "https://spdx.test/tools-python/namespace_map_namespace" def test_invalid_initialization(): From cb99c0f15249c94e86796d21c16f75763d54980c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 17 May 2023 11:13:01 +0200 Subject: [PATCH 225/354] [issue-659] rename CreationInformation to CreationInfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/bump_from_spdx2/actor.py | 11 +---- .../spdx3/bump_from_spdx2/annotation.py | 4 +- ...eation_information.py => creation_info.py} | 18 +++---- src/spdx_tools/spdx3/bump_from_spdx2/file.py | 6 +-- .../spdx3/bump_from_spdx2/package.py | 12 ++--- .../spdx3/bump_from_spdx2/relationship.py | 12 ++--- .../spdx3/bump_from_spdx2/snippet.py | 6 +-- .../spdx3/bump_from_spdx2/spdx_document.py | 8 +-- src/spdx_tools/spdx3/model/__init__.py | 2 +- src/spdx_tools/spdx3/model/agent.py | 4 +- src/spdx_tools/spdx3/model/ai/ai_package.py | 4 +- src/spdx_tools/spdx3/model/annotation.py | 4 +- src/spdx_tools/spdx3/model/bom.py | 4 +- src/spdx_tools/spdx3/model/build/build.py | 11 +---- src/spdx_tools/spdx3/model/bundle.py | 4 +- ...eation_information.py => creation_info.py} | 2 +- src/spdx_tools/spdx3/model/dataset/dataset.py | 4 +- src/spdx_tools/spdx3/model/element.py | 4 +- .../model/lifecycle_scoped_relationship.py | 4 +- src/spdx_tools/spdx3/model/organization.py | 4 +- src/spdx_tools/spdx3/model/person.py | 4 +- src/spdx_tools/spdx3/model/relationship.py | 4 +- .../cvss_v2_vuln_assessment_relationship.py | 4 +- .../cvss_v3_vuln_assessment_relationship.py | 4 +- .../epss_vuln_assessment_relationship.py | 4 +- ...it_catalog_vuln_assessment_relationship.py | 4 +- .../ssvc_vuln_assessment_relationship.py | 4 +- ...x_affected_vuln_assessment_relationship.py | 4 +- .../vex_fixed_vuln_assessment_relationship.py | 4 +- ...t_affected_vuln_assessment_relationship.py | 4 +- ...estigation_vuln_assessment_relationship.py | 4 +- .../spdx3/model/security/vulnerability.py | 4 +- src/spdx_tools/spdx3/model/software/file.py | 4 +- .../spdx3/model/software/package.py | 4 +- src/spdx_tools/spdx3/model/software/sbom.py | 4 +- .../spdx3/model/software/snippet.py | 4 +- .../software_dependency_relationship.py | 4 +- src/spdx_tools/spdx3/model/software_agent.py | 4 +- src/spdx_tools/spdx3/model/spdx_document.py | 4 +- src/spdx_tools/spdx3/model/tool.py | 4 +- ...tion_writer.py => creation_info_writer.py} | 4 +- .../spdx3/writer/console/element_writer.py | 2 +- tests/spdx3/bump/test_actor_bump.py | 14 ++---- .../bump/test_external_document_ref_bump.py | 4 +- tests/spdx3/bump/test_file_bump.py | 6 +-- tests/spdx3/bump/test_package_bump.py | 24 ++++----- tests/spdx3/bump/test_relationship_bump.py | 8 +-- tests/spdx3/bump/test_snippet_bump.py | 6 +-- tests/spdx3/fixtures.py | 6 +-- tests/spdx3/model/ai/test_ai_package.py | 12 ++--- tests/spdx3/model/build/test_build.py | 12 ++--- tests/spdx3/model/dataset/test_dataset.py | 12 ++--- tests/spdx3/model/software/test_file.py | 14 +++--- tests/spdx3/model/software/test_package.py | 14 +++--- tests/spdx3/model/software/test_sbom.py | 8 +-- tests/spdx3/model/software/test_snippet.py | 10 ++-- .../test_software_dependency_relationship.py | 14 +++--- tests/spdx3/model/test_creation_info.py | 49 +++++++++++++++++++ .../spdx3/model/test_creation_information.py | 49 ------------------- 59 files changed, 227 insertions(+), 249 deletions(-) rename src/spdx_tools/spdx3/bump_from_spdx2/{creation_information.py => creation_info.py} (81%) rename src/spdx_tools/spdx3/model/{creation_information.py => creation_info.py} (97%) rename src/spdx_tools/spdx3/writer/console/{creation_information_writer.py => creation_info_writer.py} (86%) create mode 100644 tests/spdx3/model/test_creation_info.py delete mode 100644 tests/spdx3/model/test_creation_information.py diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/actor.py b/src/spdx_tools/spdx3/bump_from_spdx2/actor.py index 3c9e0a430..6a84af7a1 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/actor.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/actor.py @@ -3,21 +3,14 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List -from spdx_tools.spdx3.model import ( - CreationInformation, - ExternalIdentifier, - ExternalIdentifierType, - Organization, - Person, - Tool, -) +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalIdentifierType, Organization, Person, Tool from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.actor import Actor as Spdx2_Actor from spdx_tools.spdx.model.actor import ActorType def bump_actor( - spdx2_actor: Spdx2_Actor, payload: Payload, creation_info: CreationInformation, document_namespace: str + spdx2_actor: Spdx2_Actor, payload: Payload, creation_info: CreationInfo, document_namespace: str ) -> str: name: str = spdx2_actor.name email: str = spdx2_actor.email diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py index 0c2b4387d..63209edc0 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py @@ -5,7 +5,7 @@ from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model import Annotation, AnnotationType, CreationInformation +from spdx_tools.spdx3.model import Annotation, AnnotationType, CreationInfo from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.actor import ActorType from spdx_tools.spdx.model.annotation import Annotation as Spdx2_Annotation @@ -14,7 +14,7 @@ def bump_annotation( spdx2_annotation: Spdx2_Annotation, payload: Payload, - creation_info: CreationInformation, + creation_info: CreationInfo, document_namespace: str, counter: int, ): diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py similarity index 81% rename from src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py rename to src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py index b5b882f25..9be0c6330 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_information.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py @@ -8,13 +8,13 @@ from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor from spdx_tools.spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model import CreationInformation, ProfileIdentifier, SpdxDocument +from spdx_tools.spdx3.model import CreationInfo, ProfileIdentifier, SpdxDocument from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.actor import ActorType from spdx_tools.spdx.model.document import CreationInfo as Spdx2_CreationInfo -def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload) -> SpdxDocument: +def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload) -> SpdxDocument: document_namespace = spdx2_creation_info.document_namespace spdx_id = f"{document_namespace}#{spdx2_creation_info.spdx_id}" @@ -34,7 +34,7 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: "part of licensing profile, " "https://github.com/spdx/spdx-3-model/issues/131", ) document_comment = spdx2_creation_info.document_comment - creation_information = CreationInformation( + creation_info = CreationInfo( spec_version=Version("3.0.0"), created=spdx2_creation_info.created, created_by=[], @@ -44,12 +44,12 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: comment=spdx2_creation_info.document_comment, ) - # due to creators having a creation_information themselves which inherits from the document's one, - # we have to add them after the creation_information has been initialized + # due to creators having a creation_info themselves which inherits from the document's one, + # we have to add them after the creation_info has been initialized creator_ids: List[str] = [] tool_ids: List[str] = [] for creator in spdx2_creation_info.creators: - bumped_actor_id = bump_actor(creator, payload, creation_information, document_namespace) + bumped_actor_id = bump_actor(creator, payload, creation_info, document_namespace) if creator.actor_type in [ActorType.PERSON, ActorType.ORGANIZATION]: creator_ids.append(bumped_actor_id) else: @@ -64,12 +64,12 @@ def bump_creation_information(spdx2_creation_info: Spdx2_CreationInfo, payload: "https://github.com/spdx/spdx-3-model/issues/180", ) - creation_information.created_by = creator_ids - creation_information.created_using = tool_ids + creation_info.created_by = creator_ids + creation_info.created_using = tool_ids return SpdxDocument( spdx_id=spdx_id, - creation_info=creation_information, + creation_info=creation_info, name=spdx2_creation_info.name, comment=document_comment, element=[], diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/file.py b/src/spdx_tools/spdx3/bump_from_spdx2/file.py index 9a5ba69bb..656490fc6 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/file.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/file.py @@ -4,7 +4,7 @@ from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model import CreationInformation +from spdx_tools.spdx3.model import CreationInfo from spdx_tools.spdx3.model.software import File from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model import SpdxNoAssertion @@ -14,7 +14,7 @@ def bump_file( spdx2_file: Spdx2_File, payload: Payload, - creation_information: CreationInformation, + creation_info: CreationInfo, document_namespace: str, extracted_licensing_info, ): @@ -40,7 +40,7 @@ def bump_file( payload.add_element( File( spdx_id, - creation_info=creation_information, + creation_info=creation_info, name=spdx2_file.name, comment=spdx2_file.comment, verified_using=integrity_methods, diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index c9c2235e4..819d2cd91 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -9,7 +9,7 @@ from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalIdentifierType, ExternalReference, @@ -26,7 +26,7 @@ def bump_package( spdx2_package: Spdx2_Package, payload: Payload, - creation_information: CreationInformation, + creation_info: CreationInfo, document_namespace: str, extracted_licensing_info: List[ExtractedLicensingInfo], ): @@ -34,13 +34,11 @@ def bump_package( download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") print_missing_conversion("package2.file_name", 0, "https://github.com/spdx/spdx-3-model/issues/83") if isinstance(spdx2_package.supplier, Spdx2_Actor): - supplied_by_spdx_id = [bump_actor(spdx2_package.supplier, payload, creation_information, document_namespace)] + supplied_by_spdx_id = [bump_actor(spdx2_package.supplier, payload, creation_info, document_namespace)] else: supplied_by_spdx_id = None if isinstance(spdx2_package.originator, Spdx2_Actor): - originated_by_spdx_id = [ - bump_actor(spdx2_package.originator, payload, creation_information, document_namespace) - ] + originated_by_spdx_id = [bump_actor(spdx2_package.originator, payload, creation_info, document_namespace)] else: originated_by_spdx_id = None print_missing_conversion("package2.files_analyzed", 0, "https://github.com/spdx/spdx-3-model/issues/84") @@ -90,7 +88,7 @@ def bump_package( payload.add_element( Package( spdx_id, - creation_information, + creation_info, spdx2_package.name, summary=spdx2_package.summary, description=spdx2_package.description, diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py index 9b19e0d11..bf7c6764b 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -7,7 +7,7 @@ from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, LifecycleScopeType, Relationship, RelationshipCompleteness, @@ -157,12 +157,12 @@ def bump_relationships( spdx2_relationships: List[Spdx2_Relationship], payload: Payload, - creation_information: CreationInformation, + creation_info: CreationInfo, document_namespace: str, ): generated_relationships: Dict[Tuple[str, str], List[Relationship]] = {} for counter, spdx2_relationship in enumerate(spdx2_relationships): - relationship = bump_relationship(spdx2_relationship, creation_information, document_namespace, counter) + relationship = bump_relationship(spdx2_relationship, creation_info, document_namespace, counter) if relationship: generated_relationships.setdefault( (relationship.from_element, relationship.relationship_type.name), [] @@ -177,7 +177,7 @@ def bump_relationships( def bump_relationship( spdx2_relationship: Spdx2_Relationship, - creation_information: CreationInformation, + creation_info: CreationInfo, document_namespace: str, counter: int, ) -> Optional[Union[Relationship, SoftwareDependencyRelationship]]: @@ -204,7 +204,7 @@ def bump_relationship( return SoftwareDependencyRelationship( spdx_id, - creation_information, + creation_info, from_element, relationship_type, to, @@ -217,7 +217,7 @@ def bump_relationship( return Relationship( spdx_id, - creation_information, + creation_info, from_element, relationship_type, to, diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index 27fa5d475..848de6d63 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -5,7 +5,7 @@ from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model import CreationInformation +from spdx_tools.spdx3.model import CreationInfo from spdx_tools.spdx3.model.software import Snippet from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model import ExtractedLicensingInfo, SpdxNoAssertion @@ -15,7 +15,7 @@ def bump_snippet( spdx2_snippet: Spdx2_Snippet, payload: Payload, - creation_information: CreationInformation, + creation_info: CreationInfo, document_namespace: str, extracted_licensing_info: List[ExtractedLicensingInfo], ): @@ -38,7 +38,7 @@ def bump_snippet( payload.add_element( Snippet( spdx_id=spdx_id, - creation_info=creation_information, + creation_info=creation_info, name=spdx2_snippet.name, comment=spdx2_snippet.comment, byte_range=spdx2_snippet.byte_range, diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py index 78843ef42..02d5763a2 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py @@ -2,12 +2,12 @@ # # SPDX-License-Identifier: Apache-2.0 from spdx_tools.spdx3.bump_from_spdx2.annotation import bump_annotation -from spdx_tools.spdx3.bump_from_spdx2.creation_information import bump_creation_information +from spdx_tools.spdx3.bump_from_spdx2.creation_info import bump_creation_info from spdx_tools.spdx3.bump_from_spdx2.file import bump_file from spdx_tools.spdx3.bump_from_spdx2.package import bump_package from spdx_tools.spdx3.bump_from_spdx2.relationship import bump_relationships from spdx_tools.spdx3.bump_from_spdx2.snippet import bump_snippet -from spdx_tools.spdx3.model import CreationInformation, SpdxDocument +from spdx_tools.spdx3.model import CreationInfo, SpdxDocument from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.document import Document as Spdx2_Document @@ -19,8 +19,8 @@ def bump_spdx_document(document: Spdx2_Document) -> Payload: payload = Payload() document_namespace: str = document.creation_info.document_namespace - spdx_document: SpdxDocument = bump_creation_information(document.creation_info, payload) - creation_info: CreationInformation = spdx_document.creation_info + spdx_document: SpdxDocument = bump_creation_info(document.creation_info, payload) + creation_info: CreationInfo = spdx_document.creation_info payload.add_element(spdx_document) diff --git a/src/spdx_tools/spdx3/model/__init__.py b/src/spdx_tools/spdx3/model/__init__.py index 6042b1e77..6ee016fe2 100644 --- a/src/spdx_tools/spdx3/model/__init__.py +++ b/src/spdx_tools/spdx3/model/__init__.py @@ -1,5 +1,5 @@ from spdx_tools.spdx3.model.profile_identifier import ProfileIdentifier -from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.creation_info import CreationInfo from spdx_tools.spdx3.model.integrity_method import IntegrityMethod from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm from spdx_tools.spdx3.model.external_reference import ExternalReference, ExternalReferenceType diff --git a/src/spdx_tools/spdx3/model/agent.py b/src/spdx_tools/spdx3/model/agent.py index c85398fac..ced560740 100644 --- a/src/spdx_tools/spdx3/model/agent.py +++ b/src/spdx_tools/spdx3/model/agent.py @@ -5,7 +5,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import CreationInformation, Element, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties @@ -13,7 +13,7 @@ class Agent(Element): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/ai/ai_package.py b/src/spdx_tools/spdx3/model/ai/ai_package.py index a22e7cbce..557be1f90 100644 --- a/src/spdx_tools/spdx3/model/ai/ai_package.py +++ b/src/spdx_tools/spdx3/model/ai/ai_package.py @@ -8,7 +8,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod from spdx_tools.spdx3.model.licensing import LicenseField from spdx_tools.spdx3.model.software import Package, SoftwarePurpose @@ -41,7 +41,7 @@ class AIPackage(Package): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, name: str, supplied_by: List[str], download_location: str, diff --git a/src/spdx_tools/spdx3/model/annotation.py b/src/spdx_tools/spdx3/model/annotation.py index e836893b2..fba272e4d 100644 --- a/src/spdx_tools/spdx3/model/annotation.py +++ b/src/spdx_tools/spdx3/model/annotation.py @@ -7,7 +7,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import CreationInformation, Element, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, IntegrityMethod class AnnotationType(Enum): @@ -25,7 +25,7 @@ class Annotation(Element): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, annotation_type: AnnotationType, subject: str, name: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/bom.py b/src/spdx_tools/spdx3/model/bom.py index 92ba6b2ac..7fef82626 100644 --- a/src/spdx_tools/spdx3/model/bom.py +++ b/src/spdx_tools/spdx3/model/bom.py @@ -7,7 +7,7 @@ from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( Bundle, - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalMap, ExternalReference, @@ -24,7 +24,7 @@ class Bom(Bundle): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, element: List[str], root_element: List[str], name: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/build/build.py b/src/spdx_tools/spdx3/model/build/build.py index fc118017a..aeb70334a 100644 --- a/src/spdx_tools/spdx3/model/build/build.py +++ b/src/spdx_tools/spdx3/model/build/build.py @@ -7,14 +7,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import ( - CreationInformation, - Element, - ExternalIdentifier, - ExternalReference, - Hash, - IntegrityMethod, -) +from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, Hash, IntegrityMethod @dataclass_with_properties @@ -32,7 +25,7 @@ class Build(Element): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, build_type: str, name: Optional[str] = None, summary: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/bundle.py b/src/spdx_tools/spdx3/model/bundle.py index ae12ecb76..50f44d1d8 100644 --- a/src/spdx_tools/spdx3/model/bundle.py +++ b/src/spdx_tools/spdx3/model/bundle.py @@ -6,7 +6,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ElementCollection, ExternalIdentifier, ExternalMap, @@ -23,7 +23,7 @@ class Bundle(ElementCollection): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, element: List[str], root_element: List[str], name: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/creation_information.py b/src/spdx_tools/spdx3/model/creation_info.py similarity index 97% rename from src/spdx_tools/spdx3/model/creation_information.py rename to src/spdx_tools/spdx3/model/creation_info.py index 45030631b..40f02abea 100644 --- a/src/spdx_tools/spdx3/model/creation_information.py +++ b/src/spdx_tools/spdx3/model/creation_info.py @@ -12,7 +12,7 @@ @dataclass_with_properties -class CreationInformation: +class CreationInfo: spec_version: Version created: datetime created_by: List[str] # SPDXID of Agents diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py index 3a1ce75ab..8eacc2716 100644 --- a/src/spdx_tools/spdx3/model/dataset/dataset.py +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -8,7 +8,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod from spdx_tools.spdx3.model.licensing import LicenseField from spdx_tools.spdx3.model.software import Package, SoftwarePurpose @@ -47,7 +47,7 @@ class Dataset(Package): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, name: str, originated_by: List[str], download_location: str, diff --git a/src/spdx_tools/spdx3/model/element.py b/src/spdx_tools/spdx3/model/element.py index 3b5dab9cc..28e27171e 100644 --- a/src/spdx_tools/spdx3/model/element.py +++ b/src/spdx_tools/spdx3/model/element.py @@ -6,13 +6,13 @@ from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties -from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties class Element(ABC): spdx_id: str # IRI - creation_info: CreationInformation + creation_info: CreationInfo name: Optional[str] = None summary: Optional[str] = None description: Optional[str] = None diff --git a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py index de14da44b..497a99a8f 100644 --- a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py +++ b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py @@ -8,7 +8,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -34,7 +34,7 @@ class LifecycleScopedRelationship(Relationship): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, from_element: str, relationship_type: RelationshipType, to: List[str] = None, diff --git a/src/spdx_tools/spdx3/model/organization.py b/src/spdx_tools/spdx3/model/organization.py index f500bb64f..92531bee2 100644 --- a/src/spdx_tools/spdx3/model/organization.py +++ b/src/spdx_tools/spdx3/model/organization.py @@ -5,7 +5,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import Agent, CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import Agent, CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties @@ -13,7 +13,7 @@ class Organization(Agent): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/person.py b/src/spdx_tools/spdx3/model/person.py index c8b9eb3b4..7fc3b7221 100644 --- a/src/spdx_tools/spdx3/model/person.py +++ b/src/spdx_tools/spdx3/model/person.py @@ -5,7 +5,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import Agent, CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import Agent, CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties @@ -13,7 +13,7 @@ class Person(Agent): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index a1933a81b..c1d041f0f 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -8,7 +8,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import CreationInformation, Element, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, IntegrityMethod class RelationshipType(Enum): @@ -97,7 +97,7 @@ class Relationship(Element): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, from_element: str, relationship_type: RelationshipType, to: List[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py index b24c1b885..4a9f82dde 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py @@ -7,7 +7,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -26,7 +26,7 @@ class CvssV2VulnAssessmentRelationship(VulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, from_element: str, to: List[str], relationship_type: RelationshipType, diff --git a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py index d11170b13..54967a726 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py @@ -7,7 +7,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -26,7 +26,7 @@ class CvssV3VulnAssessmentRelationship(VulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, from_element: str, to: List[str], relationship_type: RelationshipType, diff --git a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py index bd085e764..357e90f2c 100644 --- a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py @@ -7,7 +7,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -25,7 +25,7 @@ class EpssVulnAssessmentRelationship(VulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, from_element: str, to: List[str], relationship_type: RelationshipType, diff --git a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py index fb45580a2..71261677b 100644 --- a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py @@ -8,7 +8,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -32,7 +32,7 @@ class ExploitCatalogVulnAssessmentRelationship(VulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, from_element: str, to: List[str], relationship_type: RelationshipType, diff --git a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py index 581f47572..e75ffa4dc 100644 --- a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py @@ -8,7 +8,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -32,7 +32,7 @@ class SsvcVulnAssessmentRelationship(VulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, from_element: str, to: List[str], relationship_type: RelationshipType, diff --git a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py index 245d03ea1..6d11ee92d 100644 --- a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py @@ -8,7 +8,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -26,7 +26,7 @@ class VexAffectedVulnAssessmentRelationship(VexVulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, from_element: str, to: List[str], relationship_type: RelationshipType, diff --git a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py index d15bdf1bc..f3bfeffb4 100644 --- a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py @@ -7,7 +7,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -22,7 +22,7 @@ class VexFixedVulnAssessmentRelationship(VexVulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, from_element: str, to: List[str], relationship_type: RelationshipType, diff --git a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py index 570bb0fb7..9a1fad5a9 100644 --- a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py @@ -8,7 +8,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -35,7 +35,7 @@ class VexNotAffectedVulnAssessmentRelationship(VexVulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, from_element: str, to: List[str], relationship_type: RelationshipType, diff --git a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py index 3bac6a91a..55729c26d 100644 --- a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py @@ -7,7 +7,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -22,7 +22,7 @@ class VexUnderInvestigationVulnAssessmentRelationship(VexVulnAssessmentRelations def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, from_element: str, to: List[str], relationship_type: RelationshipType, diff --git a/src/spdx_tools/spdx3/model/security/vulnerability.py b/src/spdx_tools/spdx3/model/security/vulnerability.py index 14104f629..21680fd48 100644 --- a/src/spdx_tools/spdx3/model/security/vulnerability.py +++ b/src/spdx_tools/spdx3/model/security/vulnerability.py @@ -6,7 +6,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import CreationInformation, Element, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties @@ -18,7 +18,7 @@ class Vulnerability(Element): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py index 0cce0a95b..30496f17e 100644 --- a/src/spdx_tools/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -6,7 +6,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod from spdx_tools.spdx3.model.licensing import LicenseField from spdx_tools.spdx3.model.software import SoftwarePurpose from spdx_tools.spdx3.model.software.software_artifact import SoftwareArtifact @@ -19,7 +19,7 @@ class File(SoftwareArtifact): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, name: str, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py index eff655705..37570039f 100644 --- a/src/spdx_tools/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -6,7 +6,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod from spdx_tools.spdx3.model.licensing import LicenseField from spdx_tools.spdx3.model.software import SoftwarePurpose from spdx_tools.spdx3.model.software.software_artifact import SoftwareArtifact @@ -23,7 +23,7 @@ class Package(SoftwareArtifact): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, name: str, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/sbom.py b/src/spdx_tools/spdx3/model/software/sbom.py index d99935125..e3b019e33 100644 --- a/src/spdx_tools/spdx3/model/software/sbom.py +++ b/src/spdx_tools/spdx3/model/software/sbom.py @@ -9,7 +9,7 @@ from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( Bom, - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalMap, ExternalReference, @@ -36,7 +36,7 @@ class Sbom(Bom): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, element: List[str], root_element: List[str], name: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py index 5beb04bdb..81e0ef7a9 100644 --- a/src/spdx_tools/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -6,7 +6,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod from spdx_tools.spdx3.model.licensing import LicenseField from spdx_tools.spdx3.model.software import SoftwarePurpose from spdx_tools.spdx3.model.software.software_artifact import SoftwareArtifact @@ -20,7 +20,7 @@ class Snippet(SoftwareArtifact): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py index 05438c66c..fc77aa35e 100644 --- a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py +++ b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py @@ -8,7 +8,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod, @@ -42,7 +42,7 @@ class SoftwareDependencyRelationship(LifecycleScopedRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, from_element: str, relationship_type: RelationshipType, to: List[str] = None, diff --git a/src/spdx_tools/spdx3/model/software_agent.py b/src/spdx_tools/spdx3/model/software_agent.py index b2c587548..fbd7d5890 100644 --- a/src/spdx_tools/spdx3/model/software_agent.py +++ b/src/spdx_tools/spdx3/model/software_agent.py @@ -5,7 +5,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import Agent, CreationInformation, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import Agent, CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties @@ -13,7 +13,7 @@ class SoftwareAgent(Agent): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/spdx_document.py b/src/spdx_tools/spdx3/model/spdx_document.py index f70783a86..a5626a1f4 100644 --- a/src/spdx_tools/spdx3/model/spdx_document.py +++ b/src/spdx_tools/spdx3/model/spdx_document.py @@ -7,7 +7,7 @@ from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import ( Bundle, - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalMap, ExternalReference, @@ -24,7 +24,7 @@ class SpdxDocument(Bundle): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, name: str, element: List[str], root_element: List[str], diff --git a/src/spdx_tools/spdx3/model/tool.py b/src/spdx_tools/spdx3/model/tool.py index 22c5f081f..da8f01b31 100644 --- a/src/spdx_tools/spdx3/model/tool.py +++ b/src/spdx_tools/spdx3/model/tool.py @@ -5,7 +5,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import CreationInformation, Element, ExternalIdentifier, ExternalReference, IntegrityMethod +from spdx_tools.spdx3.model import CreationInfo, Element, ExternalIdentifier, ExternalReference, IntegrityMethod @dataclass_with_properties @@ -13,7 +13,7 @@ class Tool(Element): def __init__( self, spdx_id: str, - creation_info: CreationInformation, + creation_info: CreationInfo, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/writer/console/creation_information_writer.py b/src/spdx_tools/spdx3/writer/console/creation_info_writer.py similarity index 86% rename from src/spdx_tools/spdx3/writer/console/creation_information_writer.py rename to src/spdx_tools/spdx3/writer/console/creation_info_writer.py index ba68f4934..3f357f677 100644 --- a/src/spdx_tools/spdx3/writer/console/creation_information_writer.py +++ b/src/spdx_tools/spdx3/writer/console/creation_info_writer.py @@ -3,12 +3,12 @@ # SPDX-License-Identifier: Apache-2.0 from typing import TextIO -from spdx_tools.spdx3.model import CreationInformation +from spdx_tools.spdx3.model import CreationInfo from spdx_tools.spdx3.writer.console.console import write_value from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string -def write_creation_info(creation_info: CreationInformation, text_output: TextIO, indent: bool = True): +def write_creation_info(creation_info: CreationInfo, text_output: TextIO, indent: bool = True): text_output.write("# Creation Information\n") write_value("specVersion", str(creation_info.spec_version), text_output, indent) write_value("created", datetime_to_iso_string(creation_info.created), text_output, indent) diff --git a/src/spdx_tools/spdx3/writer/console/element_writer.py b/src/spdx_tools/spdx3/writer/console/element_writer.py index c83e763b1..239b87174 100644 --- a/src/spdx_tools/spdx3/writer/console/element_writer.py +++ b/src/spdx_tools/spdx3/writer/console/element_writer.py @@ -5,7 +5,7 @@ from spdx_tools.spdx3.model import Element from spdx_tools.spdx3.writer.console.console import write_value -from spdx_tools.spdx3.writer.console.creation_information_writer import write_creation_info +from spdx_tools.spdx3.writer.console.creation_info_writer import write_creation_info from spdx_tools.spdx3.writer.console.external_identifier_writer import write_external_identifier from spdx_tools.spdx3.writer.console.external_reference_writer import write_external_reference from spdx_tools.spdx3.writer.console.hash_writer import write_hash diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index d995b992a..124341f87 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -8,7 +8,7 @@ from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor from spdx_tools.spdx3.model import ( - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalIdentifierType, Organization, @@ -37,9 +37,7 @@ def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_id): payload = Payload() document_namespace = "https://doc.namespace" - creation_info = CreationInformation( - Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], [ProfileIdentifier.CORE] - ) + creation_info = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], [ProfileIdentifier.CORE]) actor = Actor(actor_type, actor_name, actor_mail) agent_or_tool_id = bump_actor(actor, payload, creation_info, document_namespace) @@ -56,12 +54,8 @@ def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_i def test_bump_actor_that_already_exists(): - creation_info_old = CreationInformation( - Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], [ProfileIdentifier.CORE] - ) - creation_info_new = CreationInformation( - Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], [], [ProfileIdentifier.CORE] - ) + creation_info_old = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], [ProfileIdentifier.CORE]) + creation_info_new = CreationInfo(Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], [], [ProfileIdentifier.CORE]) name = "some name" document_namespace = "https://doc.namespace" diff --git a/tests/spdx3/bump/test_external_document_ref_bump.py b/tests/spdx3/bump/test_external_document_ref_bump.py index ebbe1d521..296a080c6 100644 --- a/tests/spdx3/bump/test_external_document_ref_bump.py +++ b/tests/spdx3/bump/test_external_document_ref_bump.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum -from spdx_tools.spdx3.bump_from_spdx2.creation_information import bump_creation_information +from spdx_tools.spdx3.bump_from_spdx2.creation_info import bump_creation_info from spdx_tools.spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model import ExternalDocumentRef @@ -30,7 +30,7 @@ def test_bump_multiple_external_document_refs(): external_document_ref_fixture("DocumentRef-external2", "https://external.uri2"), ] ) - spdx_document = bump_creation_information(creation_info, payload) + spdx_document = bump_creation_info(creation_info, payload) assert len(spdx_document.imports) == 2 assert len(spdx_document.namespaces) == 2 diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index a3e1acddf..3e49efe6a 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -12,15 +12,15 @@ from tests.spdx.fixtures import file_fixture -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_bump_file(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_bump_file(creation_info): payload = Payload() document_namespace = "https://doc.namespace" spdx2_file: Spdx2_File = file_fixture() integrity_method: Hash = Hash(HashAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c") expected_new_file_id = f"{document_namespace}#{spdx2_file.spdx_id}" - bump_file(spdx2_file, payload, creation_information, document_namespace, None) + bump_file(spdx2_file, payload, creation_info, document_namespace, None) file = payload.get_element(expected_new_file_id) assert isinstance(file, File) diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 002fc7d63..7261d1394 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -29,8 +29,8 @@ (SpdxNoAssertion(), [], SpdxNoAssertion(), []), ], ) -@mock.patch("spdx_tools.spdx3.model.CreationInformation") -def test_bump_package(creation_information, originator, expected_originator, supplier, expected_supplier): +@mock.patch("spdx_tools.spdx3.model.CreationInfo") +def test_bump_package(creation_info, originator, expected_originator, supplier, expected_supplier): payload = Payload() document_namespace = "https://doc.namespace" spdx2_package: Spdx2_Package = package_fixture( @@ -45,7 +45,7 @@ def test_bump_package(creation_information, originator, expected_originator, sup ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_information, document_namespace, []) + bump_package(spdx2_package, payload, creation_info, document_namespace, []) package = payload.get_element(expected_new_package_id) assert isinstance(package, Package) @@ -76,8 +76,8 @@ def test_bump_package(creation_information, originator, expected_originator, sup ) -@mock.patch("spdx_tools.spdx3.model.CreationInformation") -def test_bump_of_single_purl_without_comment(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo") +def test_bump_of_single_purl_without_comment(creation_info): payload = Payload() document_namespace = "https://doc.namespace" spdx2_package: Spdx2_Package = package_fixture( @@ -87,7 +87,7 @@ def test_bump_of_single_purl_without_comment(creation_information): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_information, document_namespace, []) + bump_package(spdx2_package, payload, creation_info, document_namespace, []) package = payload.get_element(expected_new_package_id) assert package.package_url == "purl_locator" @@ -95,8 +95,8 @@ def test_bump_of_single_purl_without_comment(creation_information): assert package.external_identifier == [] -@mock.patch("spdx_tools.spdx3.model.CreationInformation") -def test_bump_of_single_purl_with_comment(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo") +def test_bump_of_single_purl_with_comment(creation_info): payload = Payload() document_namespace = "https://doc.namespace" spdx2_package: Spdx2_Package = package_fixture( @@ -106,7 +106,7 @@ def test_bump_of_single_purl_with_comment(creation_information): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_information, document_namespace, []) + bump_package(spdx2_package, payload, creation_info, document_namespace, []) package = payload.get_element(expected_new_package_id) assert package.package_url is None @@ -116,8 +116,8 @@ def test_bump_of_single_purl_with_comment(creation_information): ] -@mock.patch("spdx_tools.spdx3.model.CreationInformation") -def test_bump_of_multiple_purls(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo") +def test_bump_of_multiple_purls(creation_info): payload = Payload() document_namespace = "https://doc.namespace" spdx2_package: Spdx2_Package = package_fixture( @@ -128,7 +128,7 @@ def test_bump_of_multiple_purls(creation_information): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_information, document_namespace, []) + bump_package(spdx2_package, payload, creation_info, document_namespace, []) package = payload.get_element(expected_new_package_id) assert package.package_url is None diff --git a/tests/spdx3/bump/test_relationship_bump.py b/tests/spdx3/bump/test_relationship_bump.py index b6ca94365..c2ddf47d6 100644 --- a/tests/spdx3/bump/test_relationship_bump.py +++ b/tests/spdx3/bump/test_relationship_bump.py @@ -11,7 +11,7 @@ from tests.spdx.fixtures import relationship_fixture -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) def test_relationship_bump(creation_info): spdx2_relationship = relationship_fixture() document_namespace = "https://doc.namespace" @@ -27,7 +27,7 @@ def test_relationship_bump(creation_info): ) -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) def test_relationships_bump(creation_info): relationships = [ relationship_fixture(comment=None), @@ -46,7 +46,7 @@ def test_relationships_bump(creation_info): ) -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) def test_relationships_bump_with_setting_completeness(creation_info): relationships = [ relationship_fixture(related_spdx_element_id=SpdxNoAssertion()), @@ -88,7 +88,7 @@ def test_relationships_bump_with_setting_completeness(creation_info): ) -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) def test_undefined_relationship_bump(creation_info, capsys): relationships = [ relationship_fixture( diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index f5cc8178f..b98ae5468 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -11,14 +11,14 @@ from tests.spdx.fixtures import snippet_fixture -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_bump_snippet(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_bump_snippet(creation_info): payload = Payload() document_namespace = "https://doc.namespace" spdx2_snippet: Spdx2_Snippet = snippet_fixture() expected_new_snippet_id = f"{document_namespace}#{spdx2_snippet.spdx_id}" - bump_snippet(spdx2_snippet, payload, creation_information, document_namespace, []) + bump_snippet(spdx2_snippet, payload, creation_info, document_namespace, []) snippet = payload.get_element(expected_new_snippet_id) assert isinstance(snippet, Snippet) diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 992fb9b4e..9b518d2d1 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -12,7 +12,7 @@ AnnotationType, Bom, Bundle, - CreationInformation, + CreationInfo, ExternalIdentifier, ExternalIdentifierType, ExternalMap, @@ -68,7 +68,7 @@ def creation_info_fixture( profile=None, data_license="CC0-1.0", comment="creationInfoComment", -) -> CreationInformation: +) -> CreationInfo: created_by = ["https://spdx.test/tools-python/creation_info_created_by"] if created_by is None else created_by created_using = ( ["https://spdx.test/tools-python/creation_info_created_using"] if created_using is None else created_using @@ -78,7 +78,7 @@ def creation_info_fixture( if profile is None else profile ) - return CreationInformation( + return CreationInfo( spec_version=spec_version, created=created, created_by=created_by, diff --git a/tests/spdx3/model/ai/test_ai_package.py b/tests/spdx3/model/ai/test_ai_package.py index 70e8a047f..d65b822aa 100644 --- a/tests/spdx3/model/ai/test_ai_package.py +++ b/tests/spdx3/model/ai/test_ai_package.py @@ -11,11 +11,11 @@ from spdx_tools.spdx3.model.software import SoftwarePurpose -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_correct_initialization(creation_info): ai_package = AIPackage( "some_spdx_id", - creation_information, + creation_info, "AI Package name", ["https://namespace.test#supplier"], "https://download.test", @@ -61,12 +61,12 @@ def test_correct_initialization(creation_information): assert ai_package.safety_risk_assessment == SafetyRiskAssessmentType.HIGH -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_invalid_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: AIPackage( "some_spdx_id", - creation_information, + creation_info, "AI Package name", ["https://namespace.test#supplier"], "https://download.test", diff --git a/tests/spdx3/model/build/test_build.py b/tests/spdx3/model/build/test_build.py index 22d214853..d5d0aefa3 100644 --- a/tests/spdx3/model/build/test_build.py +++ b/tests/spdx3/model/build/test_build.py @@ -10,11 +10,11 @@ from spdx_tools.spdx3.model.build import Build -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_correct_initialization(creation_info): build = Build( "some_spdx_id", - creation_information, + creation_info, build_type="build type", build_id="build id", config_source_entrypoint=["entrypoint"], @@ -37,12 +37,12 @@ def test_correct_initialization(creation_information): assert build.environment == {"param2": "value2"} -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_invalid_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: Build( "some_spdx_id", - creation_information, + creation_info, build_type="build type", config_source_digest=["hash_value"], ) diff --git a/tests/spdx3/model/dataset/test_dataset.py b/tests/spdx3/model/dataset/test_dataset.py index 22cce21da..be780c8ae 100644 --- a/tests/spdx3/model/dataset/test_dataset.py +++ b/tests/spdx3/model/dataset/test_dataset.py @@ -10,11 +10,11 @@ from spdx_tools.spdx3.model.software import SoftwarePurpose -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_correct_initialization(creation_info): dataset = Dataset( "some_spdx_id", - creation_information, + creation_info, "Dataset name", ["https://namespace.test#originator"], "https://download.test", @@ -56,12 +56,12 @@ def test_correct_initialization(creation_information): assert dataset.dataset_availability == DatasetAvailabilityType.QUERY -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_invalid_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: Dataset( "some_spdx_id", - creation_information, + creation_info, "Dataset name", ["https://namespace.test#originator"], "https://download.test", diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index 8cdd3611d..ea8687c6d 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -8,11 +8,11 @@ from spdx_tools.spdx3.model.software import File, SoftwarePurpose -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_correct_initialization(creation_info): file = File( "SPDXRef-File", - creation_information, + creation_info, "Test file", verified_using=None, content_identifier="https://any.uri", @@ -21,19 +21,19 @@ def test_correct_initialization(creation_information): ) assert file.spdx_id == "SPDXRef-File" - assert file.creation_info == creation_information + assert file.creation_info == creation_info assert file.name == "Test file" assert file.content_identifier == "https://any.uri" assert file.purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE] assert file.content_type == "MediaType" -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_invalid_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: File( 1, - creation_information, + creation_info, "test file", content_identifier=3, purpose=SoftwarePurpose.FILE, diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 384d1bd46..17312b83c 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -9,11 +9,11 @@ from spdx_tools.spdx3.model.software import Package, SoftwarePurpose -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_correct_initialization(creation_info): package = Package( "SPDXRef-Package", - creation_information, + creation_info, "Test package", content_identifier="https://any.uri", originated_by=["https://namespace.test#originator"], @@ -31,7 +31,7 @@ def test_correct_initialization(creation_information): ) assert package.spdx_id == "SPDXRef-Package" - assert package.creation_info == creation_information + assert package.creation_info == creation_info assert package.name == "Test package" assert package.content_identifier == "https://any.uri" assert package.originated_by == ["https://namespace.test#originator"] @@ -48,12 +48,12 @@ def test_correct_initialization(creation_information): assert package.source_info == "some info" -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_invalid_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: Package( "SPDXRef-Package", - creation_information, + creation_info, "Test package", built_time="2022-03-04T00:00:00Z", content_identifier=3, diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index 1264e8121..64f55300e 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -8,18 +8,18 @@ from spdx_tools.spdx3.model.software import Sbom, SBOMType -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_correct_initialization(creation_info): sbom = Sbom( "SPDXRef-Sbom", - creation_information, + creation_info, element=["spdx_id1", "spdx_id2"], root_element=["spdx_id3"], sbom_type=[SBOMType.DESIGN], ) assert sbom.spdx_id == "SPDXRef-Sbom" - assert sbom.creation_info == creation_information + assert sbom.creation_info == creation_info assert sbom.element == ["spdx_id1", "spdx_id2"] assert sbom.root_element == ["spdx_id3"] assert sbom.sbom_type == [SBOMType.DESIGN] diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index 7a3e480a3..caa5e063a 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -9,10 +9,10 @@ @mock.patch("spdx_tools.spdx3.model.software.Snippet", autospec=True) -def test_correct_initialization(creation_information): +def test_correct_initialization(creation_info): snippet = Snippet( "SPDXRef-Snippet", - creation_information, + creation_info, content_identifier="https://content.identifier", purpose=[SoftwarePurpose.SOURCE], byte_range=(3, 4), @@ -20,7 +20,7 @@ def test_correct_initialization(creation_information): ) assert snippet.spdx_id == "SPDXRef-Snippet" - assert snippet.creation_info == creation_information + assert snippet.creation_info == creation_info assert snippet.content_identifier == "https://content.identifier" assert snippet.purpose == [SoftwarePurpose.SOURCE] assert snippet.byte_range == (3, 4) @@ -28,9 +28,9 @@ def test_correct_initialization(creation_information): @mock.patch("spdx_tools.spdx3.model.software.Snippet", autospec=True) -def test_invalid_initialization(creation_information): +def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: - Snippet(2, creation_information, originated_by=34, byte_range="34:45") + Snippet(2, creation_info, originated_by=34, byte_range="34:45") assert len(err.value.args[0]) == 3 for error in err.value.args[0]: diff --git a/tests/spdx3/model/software/test_software_dependency_relationship.py b/tests/spdx3/model/software/test_software_dependency_relationship.py index 7d6e0697c..303896cd7 100644 --- a/tests/spdx3/model/software/test_software_dependency_relationship.py +++ b/tests/spdx3/model/software/test_software_dependency_relationship.py @@ -14,11 +14,11 @@ ) -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_correct_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_correct_initialization(creation_info): relationship = SoftwareDependencyRelationship( "SPDXRef-Relationship", - creation_information, + creation_info, "spdx_id1", RelationshipType.DESCRIBES, ["spdx_id2", "spdx_id3"], @@ -31,7 +31,7 @@ def test_correct_initialization(creation_information): ) assert relationship.spdx_id == "SPDXRef-Relationship" - assert relationship.creation_info == creation_information + assert relationship.creation_info == creation_info assert relationship.from_element == "spdx_id1" assert relationship.to == ["spdx_id2", "spdx_id3"] assert relationship.relationship_type == RelationshipType.DESCRIBES @@ -43,12 +43,12 @@ def test_correct_initialization(creation_information): assert relationship.conditionality == DependencyConditionalityType.PROVIDED -@mock.patch("spdx_tools.spdx3.model.CreationInformation", autospec=True) -def test_invalid_initialization(creation_information): +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) +def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: SoftwareDependencyRelationship( "SPDXRef-Relationship", - creation_information, + creation_info, "spdx_id1", RelationshipType.DESCRIBES, 42, diff --git a/tests/spdx3/model/test_creation_info.py b/tests/spdx3/model/test_creation_info.py new file mode 100644 index 000000000..154ae028d --- /dev/null +++ b/tests/spdx3/model/test_creation_info.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime + +import pytest +from semantic_version import Version + +from spdx_tools.spdx3.model import CreationInfo, ProfileIdentifier +from tests.spdx3.fixtures import creation_info_fixture +from tests.spdx3.model.model_test_utils import get_property_names + + +def test_correct_initialization(): + creation_info = creation_info_fixture() + + for property_name in get_property_names(CreationInfo): + assert getattr(creation_info, property_name) is not None + + assert creation_info.spec_version == Version("3.0.0") + assert creation_info.created == datetime(2022, 12, 1) + assert creation_info.created_by == ["https://spdx.test/tools-python/creation_info_created_by"] + assert creation_info.created_using == ["https://spdx.test/tools-python/creation_info_created_using"] + assert creation_info.profile == [ + ProfileIdentifier.CORE, + ProfileIdentifier.SOFTWARE, + ProfileIdentifier.LICENSING, + ] + assert creation_info.data_license == "CC0-1.0" + assert creation_info.comment == "creationInfoComment" + + +def test_invalid_initialization(): + with pytest.raises(TypeError) as err: + CreationInfo("2.3", "2012-01-01", [], [], "core", 3, []) + + assert len(err.value.args[0]) == 5 + for error in err.value.args[0]: + assert error.startswith("SetterError CreationInfo:") + + +def test_incomplete_initialization(): + with pytest.raises(TypeError) as err: + CreationInfo("2.3") + + assert ( + "__init__() missing 4 required positional arguments: 'created', 'created_by', 'created_using', and 'profile'" + in err.value.args[0] + ) diff --git a/tests/spdx3/model/test_creation_information.py b/tests/spdx3/model/test_creation_information.py deleted file mode 100644 index a86d08d7a..000000000 --- a/tests/spdx3/model/test_creation_information.py +++ /dev/null @@ -1,49 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from datetime import datetime - -import pytest -from semantic_version import Version - -from spdx_tools.spdx3.model import CreationInformation, ProfileIdentifier -from tests.spdx3.fixtures import creation_info_fixture -from tests.spdx3.model.model_test_utils import get_property_names - - -def test_correct_initialization(): - creation_information = creation_info_fixture() - - for property_name in get_property_names(CreationInformation): - assert getattr(creation_information, property_name) is not None - - assert creation_information.spec_version == Version("3.0.0") - assert creation_information.created == datetime(2022, 12, 1) - assert creation_information.created_by == ["https://spdx.test/tools-python/creation_info_created_by"] - assert creation_information.created_using == ["https://spdx.test/tools-python/creation_info_created_using"] - assert creation_information.profile == [ - ProfileIdentifier.CORE, - ProfileIdentifier.SOFTWARE, - ProfileIdentifier.LICENSING, - ] - assert creation_information.data_license == "CC0-1.0" - assert creation_information.comment == "creationInfoComment" - - -def test_invalid_initialization(): - with pytest.raises(TypeError) as err: - CreationInformation("2.3", "2012-01-01", [], [], "core", 3, []) - - assert len(err.value.args[0]) == 5 - for error in err.value.args[0]: - assert error.startswith("SetterError CreationInformation:") - - -def test_incomplete_initialization(): - with pytest.raises(TypeError) as err: - CreationInformation("2.3") - - assert ( - "__init__() missing 4 required positional arguments: 'created', 'created_by', 'created_using', and 'profile'" - in err.value.args[0] - ) From 4d1d828db5b1815ed58c346f01ff8f12c2bde076 Mon Sep 17 00:00:00 2001 From: HarshvMahawar Date: Thu, 18 May 2023 01:06:57 +0530 Subject: [PATCH 226/354] Added fixture dictionaries for software profile Signed-off-by: HarshvMahawar --- tests/spdx3/fixtures.py | 58 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 9b518d2d1..d9f63edff 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -36,6 +36,7 @@ from spdx_tools.spdx3.model.licensing import ( CustomLicense, CustomLicenseAddition, + LicenseField, ListedLicense, ListedLicenseException, ) @@ -54,7 +55,17 @@ VexUnderInvestigationVulnAssessmentRelationship, Vulnerability, ) -from spdx_tools.spdx3.model.software import Sbom, SBOMType +from spdx_tools.spdx3.model.software import ( + DependencyConditionalityType, + File, + Package, + Sbom, + SBOMType, + Snippet, + SoftwareDependencyLinkType, + SoftwareDependencyRelationship, + SoftwarePurpose, +) """Utility methods to create data model instances. All properties have valid defaults, so they don't need to be specified unless relevant for the test.""" @@ -298,6 +309,42 @@ def namespace_map_fixture( "relationship_type": RelationshipType.FIXED_IN, } +ARTIFACT_DICT = { + "originated_by": ["https://spdx.test/tools-python/originatedBy"], + "supplied_by": ["https://spdx.test/tools-python/suppliedBy"], + "built_time": datetime(2004, 1, 1), + "release_time": datetime(2005, 1, 1), + "valid_until_time": datetime(2006, 1, 1), + "standard": ["https://spdx.test/tools-python/standard"], +} + +SOFTWARE_ARTIFACT_DICT = { + "content_identifier": "https://spdx.test/tools-python/contentIdentifier", + "purpose": SoftwarePurpose.OTHER, + "concluded_license": LicenseField, + "declared_license": LicenseField, + "copyright_text": "copyrightText", + "attribution_text": "attributionText", +} + +FILE_DICT = {"content_type": "fileContentType"} + +PACKAGE_DICT = { + "package_version": "packageVersion", + "download_location": "https://spdx.test/tools-python/downloadPackage", + "package_url": "https://spdx.test/tools-python/package", + "homepage": "https://spdx.test/tools-python/homepage", + "source_info": "sourceInfo", +} + +SNIPPET_DICT = {"byte_range": (1024, 2048), "line_range": (1, 4)} + +SOFTWARE_DEPENDENCY_RELATIONSHIP_DICT = { + "software_linkage": SoftwareDependencyLinkType.OTHER, + "conditionality": DependencyConditionalityType.OTHER, +} + + FIXTURE_DICTS = { Agent: [ELEMENT_DICT], Person: [ELEMENT_DICT], @@ -374,6 +421,15 @@ def namespace_map_fixture( VEX_UNDER_INVESTIGATION_VULN_ASSESSMENT_RELATIONSHIP_DICT, ], Vulnerability: [ELEMENT_DICT, VULNERABILITY_DICT], + File: [ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT, FILE_DICT], + Package: [ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT, PACKAGE_DICT], + Snippet: [ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT, SNIPPET_DICT], + SoftwareDependencyRelationship: [ + ELEMENT_DICT, + RELATIONSHIP_DICT, + LIFECYCLE_SCOPED_RELATIONSHIP_DICT, + SOFTWARE_DEPENDENCY_RELATIONSHIP_DICT, + ], } From eff4ef7ab354d55e6f52e0afdd08abdd92d1822a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 22 May 2023 11:56:28 +0200 Subject: [PATCH 227/354] [issue-427] implement bumping of external SPDX elements to imports (ExternalMap) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../bump_from_spdx2/external_element_utils.py | 34 +++++++++++ src/spdx_tools/spdx3/bump_from_spdx2/file.py | 14 +++-- .../spdx3/bump_from_spdx2/package.py | 11 +++- .../spdx3/bump_from_spdx2/snippet.py | 12 +++- .../spdx3/bump_from_spdx2/spdx_document.py | 30 +++++++++- src/spdx_tools/spdx3/model/external_map.py | 2 + .../spdx3/bump/test_external_element_bump.py | 57 +++++++++++++++++++ tests/spdx3/bump/test_file_bump.py | 2 +- tests/spdx3/bump/test_package_bump.py | 8 +-- tests/spdx3/bump/test_snippet_bump.py | 2 +- tests/spdx3/fixtures.py | 8 ++- tests/spdx3/model/test_external_map.py | 1 + 12 files changed, 162 insertions(+), 19 deletions(-) create mode 100644 src/spdx_tools/spdx3/bump_from_spdx2/external_element_utils.py create mode 100644 tests/spdx3/bump/test_external_element_bump.py diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/external_element_utils.py b/src/spdx_tools/spdx3/bump_from_spdx2/external_element_utils.py new file mode 100644 index 000000000..4df5abe0a --- /dev/null +++ b/src/spdx_tools/spdx3/bump_from_spdx2/external_element_utils.py @@ -0,0 +1,34 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from typing import List, Union + +from spdx_tools.spdx3.model import ExternalMap +from spdx_tools.spdx.model import ExternalDocumentRef, File, Package, Snippet + + +def get_full_element_spdx_id_and_set_imports( + element: Union[Package, File, Snippet], + document_namespace: str, + external_document_refs: List[ExternalDocumentRef], + imports: List[ExternalMap], +) -> str: + """ + Returns the spdx_id of the element prefixed with the correct document namespace and, + if the element is from an external document, sets the correct entry in the imports property. + """ + if ":" not in element.spdx_id: + return f"{document_namespace}#{element.spdx_id}" + + external_id, local_id = element.spdx_id.split(":") + external_uri = None + for entry in external_document_refs: + if entry.document_ref_id == external_id: + external_uri = entry.document_uri + break + + if external_uri: + imports.append(ExternalMap(external_id=element.spdx_id, defining_document=f"{external_id}:SPDXRef-DOCUMENT")) + return external_uri + "#" + local_id + + raise ValueError(f"external id {external_id} not found in external document references") diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/file.py b/src/spdx_tools/spdx3/bump_from_spdx2/file.py index 656490fc6..0dd1bce12 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/file.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/file.py @@ -1,13 +1,16 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from typing import List + from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.bump_from_spdx2.external_element_utils import get_full_element_spdx_id_and_set_imports from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model import CreationInfo +from spdx_tools.spdx3.model import CreationInfo, ExternalMap from spdx_tools.spdx3.model.software import File from spdx_tools.spdx3.payload import Payload -from spdx_tools.spdx.model import SpdxNoAssertion +from spdx_tools.spdx.model import ExternalDocumentRef, ExtractedLicensingInfo, SpdxNoAssertion from spdx_tools.spdx.model.file import File as Spdx2_File @@ -16,9 +19,12 @@ def bump_file( payload: Payload, creation_info: CreationInfo, document_namespace: str, - extracted_licensing_info, + extracted_licensing_info: List[ExtractedLicensingInfo], + external_document_refs: List[ExternalDocumentRef], + imports: List[ExternalMap], ): - spdx_id = "#".join([document_namespace, spdx2_file.spdx_id]) + spdx_id = get_full_element_spdx_id_and_set_imports(spdx2_file, document_namespace, external_document_refs, imports) + integrity_methods = [bump_checksum(checksum) for checksum in spdx2_file.checksums] print_missing_conversion( "file.file_type", 0, "different cardinalities, " "https://github.com/spdx/spdx-3-model/issues/82" diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index 819d2cd91..af5eb5aec 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -6,19 +6,21 @@ from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.bump_from_spdx2.external_element_utils import get_full_element_spdx_id_and_set_imports from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import ( CreationInfo, ExternalIdentifier, ExternalIdentifierType, + ExternalMap, ExternalReference, ExternalReferenceType, ) from spdx_tools.spdx3.model.software import Package, SoftwarePurpose from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model import Actor as Spdx2_Actor -from spdx_tools.spdx.model import ExtractedLicensingInfo, SpdxNoAssertion +from spdx_tools.spdx.model import ExternalDocumentRef, ExtractedLicensingInfo, SpdxNoAssertion from spdx_tools.spdx.model.package import ExternalPackageRef from spdx_tools.spdx.model.package import Package as Spdx2_Package @@ -29,8 +31,13 @@ def bump_package( creation_info: CreationInfo, document_namespace: str, extracted_licensing_info: List[ExtractedLicensingInfo], + external_document_refs: List[ExternalDocumentRef], + imports: List[ExternalMap], ): - spdx_id = "#".join([document_namespace, spdx2_package.spdx_id]) + spdx_id = get_full_element_spdx_id_and_set_imports( + spdx2_package, document_namespace, external_document_refs, imports + ) + download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") print_missing_conversion("package2.file_name", 0, "https://github.com/spdx/spdx-3-model/issues/83") if isinstance(spdx2_package.supplier, Spdx2_Actor): diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index 848de6d63..f89a62dae 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -3,12 +3,13 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List +from spdx_tools.spdx3.bump_from_spdx2.external_element_utils import get_full_element_spdx_id_and_set_imports from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model import CreationInfo +from spdx_tools.spdx3.model import CreationInfo, ExternalMap from spdx_tools.spdx3.model.software import Snippet from spdx_tools.spdx3.payload import Payload -from spdx_tools.spdx.model import ExtractedLicensingInfo, SpdxNoAssertion +from spdx_tools.spdx.model import ExternalDocumentRef, ExtractedLicensingInfo, SpdxNoAssertion from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet @@ -18,8 +19,13 @@ def bump_snippet( creation_info: CreationInfo, document_namespace: str, extracted_licensing_info: List[ExtractedLicensingInfo], + external_document_refs: List[ExternalDocumentRef], + imports: List[ExternalMap], ): - spdx_id = "#".join([document_namespace, spdx2_snippet.spdx_id]) + spdx_id = get_full_element_spdx_id_and_set_imports( + spdx2_snippet, document_namespace, external_document_refs, imports + ) + print_missing_conversion("snippet.file_spdx_id", 0, "https://github.com/spdx/spdx-3-model/issues/130") concluded_license = bump_license_expression_or_none_or_no_assertion( spdx2_snippet.license_concluded, extracted_licensing_info diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py index 02d5763a2..a93d762ff 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py @@ -25,13 +25,37 @@ def bump_spdx_document(document: Spdx2_Document) -> Payload: payload.add_element(spdx_document) for spdx2_package in document.packages: - bump_package(spdx2_package, payload, creation_info, document_namespace, document.extracted_licensing_info) + bump_package( + spdx2_package, + payload, + creation_info, + document_namespace, + document.extracted_licensing_info, + document.creation_info.external_document_refs, + spdx_document.imports, + ) for spdx2_file in document.files: - bump_file(spdx2_file, payload, creation_info, document_namespace, document.extracted_licensing_info) + bump_file( + spdx2_file, + payload, + creation_info, + document_namespace, + document.extracted_licensing_info, + document.creation_info.external_document_refs, + spdx_document.imports, + ) for spdx2_snippet in document.snippets: - bump_snippet(spdx2_snippet, payload, creation_info, document_namespace, document.extracted_licensing_info) + bump_snippet( + spdx2_snippet, + payload, + creation_info, + document_namespace, + document.extracted_licensing_info, + document.creation_info.external_document_refs, + spdx_document.imports, + ) bump_relationships(document.relationships, payload, creation_info, document_namespace) diff --git a/src/spdx_tools/spdx3/model/external_map.py b/src/spdx_tools/spdx3/model/external_map.py index e5674f065..91ec7dd2c 100644 --- a/src/spdx_tools/spdx3/model/external_map.py +++ b/src/spdx_tools/spdx3/model/external_map.py @@ -14,12 +14,14 @@ class ExternalMap: external_id: str # anyURI verified_using: List[IntegrityMethod] = field(default_factory=list) location_hint: Optional[str] = None # anyURI + defining_document: Optional[str] = None def __init__( self, external_id: str, verified_using: List[IntegrityMethod] = None, location_hint: Optional[str] = None, + defining_document: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/bump/test_external_element_bump.py b/tests/spdx3/bump/test_external_element_bump.py new file mode 100644 index 000000000..a71af7e89 --- /dev/null +++ b/tests/spdx3/bump/test_external_element_bump.py @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from unittest import TestCase + +from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum +from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document +from spdx_tools.spdx3.model import ExternalMap +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import ExternalDocumentRef +from spdx_tools.spdx.model.document import Document as Spdx2_Document +from tests.spdx.fixtures import ( + checksum_fixture, + creation_info_fixture, + document_fixture, + file_fixture, + package_fixture, + snippet_fixture, +) + + +def test_bump_external_elements(): + external_doc_uri = "https://external-document.uri" + external_doc_id = "DocumentRef-external" + + full_external_doc_id = external_doc_id + ":SPDXRef-DOCUMENT" + package_id = external_doc_id + ":SPDXRef-Package" + file_id = external_doc_id + ":SPDXRef-File" + snippet_id = external_doc_id + ":SPDXRef-Snippet" + document_namespace = document_fixture().creation_info.document_namespace + + spdx2_document: Spdx2_Document = document_fixture( + creation_info=creation_info_fixture( + external_document_refs=[ExternalDocumentRef(external_doc_id, external_doc_uri, checksum_fixture())] + ), + packages=[package_fixture(spdx_id=package_id)], + files=[file_fixture(spdx_id=file_id)], + snippets=[snippet_fixture(spdx_id=snippet_id)], + ) + payload: Payload = bump_spdx_document(spdx2_document) + + expected_imports = [ + ExternalMap(external_id=package_id, defining_document=full_external_doc_id), + ExternalMap(external_id=file_id, defining_document=full_external_doc_id), + ExternalMap(external_id=snippet_id, defining_document=full_external_doc_id), + ExternalMap(external_id=full_external_doc_id, verified_using=[bump_checksum(checksum_fixture())]), + ] + spdx_document = payload.get_element(f"{document_namespace}#SPDXRef-DOCUMENT") + + assert f"{external_doc_uri}#SPDXRef-Package" in payload.get_full_map() + assert f"{external_doc_uri}#SPDXRef-File" in payload.get_full_map() + assert f"{external_doc_uri}#SPDXRef-Snippet" in payload.get_full_map() + + test_case = TestCase() + test_case.maxDiff = None + test_case.assertCountEqual(spdx_document.imports, expected_imports) diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index 3e49efe6a..a21487f52 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -20,7 +20,7 @@ def test_bump_file(creation_info): integrity_method: Hash = Hash(HashAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c") expected_new_file_id = f"{document_namespace}#{spdx2_file.spdx_id}" - bump_file(spdx2_file, payload, creation_info, document_namespace, None) + bump_file(spdx2_file, payload, creation_info, document_namespace, [], [], []) file = payload.get_element(expected_new_file_id) assert isinstance(file, File) diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 7261d1394..8b17598fa 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -45,7 +45,7 @@ def test_bump_package(creation_info, originator, expected_originator, supplier, ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_info, document_namespace, []) + bump_package(spdx2_package, payload, creation_info, document_namespace, [], [], []) package = payload.get_element(expected_new_package_id) assert isinstance(package, Package) @@ -87,7 +87,7 @@ def test_bump_of_single_purl_without_comment(creation_info): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_info, document_namespace, []) + bump_package(spdx2_package, payload, creation_info, document_namespace, [], [], []) package = payload.get_element(expected_new_package_id) assert package.package_url == "purl_locator" @@ -106,7 +106,7 @@ def test_bump_of_single_purl_with_comment(creation_info): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_info, document_namespace, []) + bump_package(spdx2_package, payload, creation_info, document_namespace, [], [], []) package = payload.get_element(expected_new_package_id) assert package.package_url is None @@ -128,7 +128,7 @@ def test_bump_of_multiple_purls(creation_info): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_info, document_namespace, []) + bump_package(spdx2_package, payload, creation_info, document_namespace, [], [], []) package = payload.get_element(expected_new_package_id) assert package.package_url is None diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index b98ae5468..da0dd265f 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -18,7 +18,7 @@ def test_bump_snippet(creation_info): spdx2_snippet: Spdx2_Snippet = snippet_fixture() expected_new_snippet_id = f"{document_namespace}#{spdx2_snippet.spdx_id}" - bump_snippet(spdx2_snippet, payload, creation_info, document_namespace, []) + bump_snippet(spdx2_snippet, payload, creation_info, document_namespace, [], [], []) snippet = payload.get_element(expected_new_snippet_id) assert isinstance(snippet, Snippet) diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index d9f63edff..586ff7a3e 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -145,9 +145,15 @@ def external_map_fixture( external_id="https://spdx.test/tools-python/external_map_external_id", verified_using=None, location_hint="https://spdx.test/tools-python/external_map_location_hint", + defining_document="https://spdx.test/tools-python/defining_document", ) -> ExternalMap: verified_using = [hash_fixture()] if verified_using is None else verified_using - return ExternalMap(external_id=external_id, verified_using=verified_using, location_hint=location_hint) + return ExternalMap( + external_id=external_id, + verified_using=verified_using, + location_hint=location_hint, + defining_document=defining_document, + ) def namespace_map_fixture( diff --git a/tests/spdx3/model/test_external_map.py b/tests/spdx3/model/test_external_map.py index 7a2865cd6..b883b4598 100644 --- a/tests/spdx3/model/test_external_map.py +++ b/tests/spdx3/model/test_external_map.py @@ -18,6 +18,7 @@ def test_correct_initialization(): assert external_map.external_id == "https://spdx.test/tools-python/external_map_external_id" assert external_map.verified_using == [hash_fixture()] assert external_map.location_hint == "https://spdx.test/tools-python/external_map_location_hint" + assert external_map.defining_document == "https://spdx.test/tools-python/defining_document" def test_invalid_initialization(): From 5e5efffa6e1e721566bd5d70d504d147ce033822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 24 May 2023 08:27:12 +0200 Subject: [PATCH 228/354] [issue-427] remove side effect of get_full_element_spdx_id function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../spdx_element_utils.py} | 13 +++++-------- src/spdx_tools/spdx3/bump_from_spdx2/file.py | 11 +++++++++-- src/spdx_tools/spdx3/bump_from_spdx2/package.py | 13 +++++++++---- src/spdx_tools/spdx3/bump_from_spdx2/snippet.py | 13 +++++++++---- tests/spdx3/bump/test_external_element_bump.py | 4 +--- 5 files changed, 33 insertions(+), 21 deletions(-) rename src/spdx_tools/{spdx3/bump_from_spdx2/external_element_utils.py => spdx/spdx_element_utils.py} (64%) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/external_element_utils.py b/src/spdx_tools/spdx/spdx_element_utils.py similarity index 64% rename from src/spdx_tools/spdx3/bump_from_spdx2/external_element_utils.py rename to src/spdx_tools/spdx/spdx_element_utils.py index 4df5abe0a..94d45ba44 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/external_element_utils.py +++ b/src/spdx_tools/spdx/spdx_element_utils.py @@ -1,17 +1,15 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors +# SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 from typing import List, Union -from spdx_tools.spdx3.model import ExternalMap from spdx_tools.spdx.model import ExternalDocumentRef, File, Package, Snippet -def get_full_element_spdx_id_and_set_imports( +def get_full_element_spdx_id( element: Union[Package, File, Snippet], document_namespace: str, external_document_refs: List[ExternalDocumentRef], - imports: List[ExternalMap], ) -> str: """ Returns the spdx_id of the element prefixed with the correct document namespace and, @@ -27,8 +25,7 @@ def get_full_element_spdx_id_and_set_imports( external_uri = entry.document_uri break - if external_uri: - imports.append(ExternalMap(external_id=element.spdx_id, defining_document=f"{external_id}:SPDXRef-DOCUMENT")) - return external_uri + "#" + local_id + if not external_uri: + raise ValueError(f"external id {external_id} not found in external document references") - raise ValueError(f"external id {external_id} not found in external document references") + return external_uri + "#" + local_id diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/file.py b/src/spdx_tools/spdx3/bump_from_spdx2/file.py index 0dd1bce12..93f8495a7 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/file.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/file.py @@ -4,7 +4,6 @@ from typing import List from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum -from spdx_tools.spdx3.bump_from_spdx2.external_element_utils import get_full_element_spdx_id_and_set_imports from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import CreationInfo, ExternalMap @@ -12,6 +11,7 @@ from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model import ExternalDocumentRef, ExtractedLicensingInfo, SpdxNoAssertion from spdx_tools.spdx.model.file import File as Spdx2_File +from spdx_tools.spdx.spdx_element_utils import get_full_element_spdx_id def bump_file( @@ -23,7 +23,14 @@ def bump_file( external_document_refs: List[ExternalDocumentRef], imports: List[ExternalMap], ): - spdx_id = get_full_element_spdx_id_and_set_imports(spdx2_file, document_namespace, external_document_refs, imports) + spdx_id = get_full_element_spdx_id(spdx2_file, document_namespace, external_document_refs) + if ":" in spdx2_file.spdx_id: + imports.append( + ExternalMap( + external_id=spdx2_file.spdx_id, + defining_document=f"{spdx2_file.spdx_id.split(':')[0]}:SPDXRef-DOCUMENT", + ) + ) integrity_methods = [bump_checksum(checksum) for checksum in spdx2_file.checksums] print_missing_conversion( diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index af5eb5aec..80081df65 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -6,7 +6,6 @@ from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum -from spdx_tools.spdx3.bump_from_spdx2.external_element_utils import get_full_element_spdx_id_and_set_imports from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import ( @@ -23,6 +22,7 @@ from spdx_tools.spdx.model import ExternalDocumentRef, ExtractedLicensingInfo, SpdxNoAssertion from spdx_tools.spdx.model.package import ExternalPackageRef from spdx_tools.spdx.model.package import Package as Spdx2_Package +from spdx_tools.spdx.spdx_element_utils import get_full_element_spdx_id def bump_package( @@ -34,9 +34,14 @@ def bump_package( external_document_refs: List[ExternalDocumentRef], imports: List[ExternalMap], ): - spdx_id = get_full_element_spdx_id_and_set_imports( - spdx2_package, document_namespace, external_document_refs, imports - ) + spdx_id = get_full_element_spdx_id(spdx2_package, document_namespace, external_document_refs) + if ":" in spdx2_package.spdx_id: + imports.append( + ExternalMap( + external_id=spdx2_package.spdx_id, + defining_document=f"{spdx2_package.spdx_id.split(':')[0]}:SPDXRef-DOCUMENT", + ) + ) download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") print_missing_conversion("package2.file_name", 0, "https://github.com/spdx/spdx-3-model/issues/83") diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index f89a62dae..78f9bb7d1 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -3,7 +3,6 @@ # SPDX-License-Identifier: Apache-2.0 from typing import List -from spdx_tools.spdx3.bump_from_spdx2.external_element_utils import get_full_element_spdx_id_and_set_imports from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import CreationInfo, ExternalMap @@ -11,6 +10,7 @@ from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model import ExternalDocumentRef, ExtractedLicensingInfo, SpdxNoAssertion from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet +from spdx_tools.spdx.spdx_element_utils import get_full_element_spdx_id def bump_snippet( @@ -22,9 +22,14 @@ def bump_snippet( external_document_refs: List[ExternalDocumentRef], imports: List[ExternalMap], ): - spdx_id = get_full_element_spdx_id_and_set_imports( - spdx2_snippet, document_namespace, external_document_refs, imports - ) + spdx_id = get_full_element_spdx_id(spdx2_snippet, document_namespace, external_document_refs) + if ":" in spdx2_snippet.spdx_id: + imports.append( + ExternalMap( + external_id=spdx2_snippet.spdx_id, + defining_document=f"{spdx2_snippet.spdx_id.split(':')[0]}:SPDXRef-DOCUMENT", + ) + ) print_missing_conversion("snippet.file_spdx_id", 0, "https://github.com/spdx/spdx-3-model/issues/130") concluded_license = bump_license_expression_or_none_or_no_assertion( diff --git a/tests/spdx3/bump/test_external_element_bump.py b/tests/spdx3/bump/test_external_element_bump.py index a71af7e89..887fa5f44 100644 --- a/tests/spdx3/bump/test_external_element_bump.py +++ b/tests/spdx3/bump/test_external_element_bump.py @@ -52,6 +52,4 @@ def test_bump_external_elements(): assert f"{external_doc_uri}#SPDXRef-File" in payload.get_full_map() assert f"{external_doc_uri}#SPDXRef-Snippet" in payload.get_full_map() - test_case = TestCase() - test_case.maxDiff = None - test_case.assertCountEqual(spdx_document.imports, expected_imports) + TestCase().assertCountEqual(spdx_document.imports, expected_imports) From 9fce31dcced447e38bed211453b932893b6f892e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 17 May 2023 14:11:27 +0200 Subject: [PATCH 229/354] [issue-659] make CreationInfo optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/bump_from_spdx2/annotation.py | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/package.py | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/relationship.py | 4 ++-- src/spdx_tools/spdx3/model/agent.py | 2 +- src/spdx_tools/spdx3/model/ai/ai_package.py | 2 +- src/spdx_tools/spdx3/model/annotation.py | 2 +- src/spdx_tools/spdx3/model/bom.py | 2 +- src/spdx_tools/spdx3/model/build/build.py | 2 +- src/spdx_tools/spdx3/model/bundle.py | 2 +- src/spdx_tools/spdx3/model/dataset/dataset.py | 2 +- src/spdx_tools/spdx3/model/element.py | 2 +- .../spdx3/model/lifecycle_scoped_relationship.py | 2 +- src/spdx_tools/spdx3/model/organization.py | 2 +- src/spdx_tools/spdx3/model/person.py | 2 +- src/spdx_tools/spdx3/model/relationship.py | 2 +- .../security/cvss_v2_vuln_assessment_relationship.py | 4 ++-- .../security/cvss_v3_vuln_assessment_relationship.py | 2 +- .../security/epss_vuln_assessment_relationship.py | 4 ++-- .../exploit_catalog_vuln_assessment_relationship.py | 4 ++-- .../security/ssvc_vuln_assessment_relationship.py | 4 ++-- .../vex_affected_vuln_assessment_relationship.py | 4 ++-- .../security/vex_fixed_vuln_assessment_relationship.py | 4 ++-- .../vex_not_affected_vuln_assessment_relationship.py | 4 ++-- ...under_investigation_vuln_assessment_relationship.py | 4 ++-- src/spdx_tools/spdx3/model/security/vulnerability.py | 2 +- src/spdx_tools/spdx3/model/software/file.py | 2 +- src/spdx_tools/spdx3/model/software/package.py | 2 +- src/spdx_tools/spdx3/model/software/sbom.py | 2 +- src/spdx_tools/spdx3/model/software/snippet.py | 2 +- .../model/software/software_dependency_relationship.py | 2 +- src/spdx_tools/spdx3/model/software_agent.py | 2 +- src/spdx_tools/spdx3/model/spdx_document.py | 2 +- src/spdx_tools/spdx3/model/tool.py | 2 +- tests/spdx3/bump/test_relationship_bump.py | 10 +++++----- tests/spdx3/model/ai/test_ai_package.py | 4 ++-- tests/spdx3/model/build/test_build.py | 4 ++-- tests/spdx3/model/dataset/test_dataset.py | 4 ++-- tests/spdx3/model/software/test_file.py | 4 ++-- tests/spdx3/model/software/test_package.py | 4 ++-- tests/spdx3/model/software/test_sbom.py | 4 ++-- tests/spdx3/model/software/test_snippet.py | 4 ++-- .../software/test_software_dependency_relationship.py | 6 +++--- 42 files changed, 64 insertions(+), 64 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py index 63209edc0..18519ec97 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py @@ -41,8 +41,8 @@ def bump_annotation( payload.add_element( Annotation( spdx_id, - creation_info, annotation_type, + creation_info=creation_info, subject=spdx2_annotation.spdx_id, statement=spdx2_annotation.annotation_comment, ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index 80081df65..814e1f849 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -100,8 +100,8 @@ def bump_package( payload.add_element( Package( spdx_id, - creation_info, spdx2_package.name, + creation_info=creation_info, summary=spdx2_package.summary, description=spdx2_package.description, comment=spdx2_package.comment, diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py index bf7c6764b..0dbe264c6 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -204,10 +204,10 @@ def bump_relationship( return SoftwareDependencyRelationship( spdx_id, - creation_info, from_element, relationship_type, to, + creation_info=creation_info, comment=spdx2_relationship.comment, completeness=completeness, scope=parameters.get("scope"), @@ -217,10 +217,10 @@ def bump_relationship( return Relationship( spdx_id, - creation_info, from_element, relationship_type, to, + creation_info=creation_info, comment=spdx2_relationship.comment, completeness=completeness, ) diff --git a/src/spdx_tools/spdx3/model/agent.py b/src/spdx_tools/spdx3/model/agent.py index ced560740..438b9de89 100644 --- a/src/spdx_tools/spdx3/model/agent.py +++ b/src/spdx_tools/spdx3/model/agent.py @@ -13,7 +13,7 @@ class Agent(Element): def __init__( self, spdx_id: str, - creation_info: CreationInfo, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/ai/ai_package.py b/src/spdx_tools/spdx3/model/ai/ai_package.py index 557be1f90..03a698768 100644 --- a/src/spdx_tools/spdx3/model/ai/ai_package.py +++ b/src/spdx_tools/spdx3/model/ai/ai_package.py @@ -41,13 +41,13 @@ class AIPackage(Package): def __init__( self, spdx_id: str, - creation_info: CreationInfo, name: str, supplied_by: List[str], download_location: str, package_version: str, purpose: List[SoftwarePurpose], release_time: datetime, + creation_info: Optional[CreationInfo] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/annotation.py b/src/spdx_tools/spdx3/model/annotation.py index fba272e4d..14bc40d9e 100644 --- a/src/spdx_tools/spdx3/model/annotation.py +++ b/src/spdx_tools/spdx3/model/annotation.py @@ -25,9 +25,9 @@ class Annotation(Element): def __init__( self, spdx_id: str, - creation_info: CreationInfo, annotation_type: AnnotationType, subject: str, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/bom.py b/src/spdx_tools/spdx3/model/bom.py index 7fef82626..2772eb54d 100644 --- a/src/spdx_tools/spdx3/model/bom.py +++ b/src/spdx_tools/spdx3/model/bom.py @@ -24,9 +24,9 @@ class Bom(Bundle): def __init__( self, spdx_id: str, - creation_info: CreationInfo, element: List[str], root_element: List[str], + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/build/build.py b/src/spdx_tools/spdx3/model/build/build.py index aeb70334a..3294c95ea 100644 --- a/src/spdx_tools/spdx3/model/build/build.py +++ b/src/spdx_tools/spdx3/model/build/build.py @@ -25,8 +25,8 @@ class Build(Element): def __init__( self, spdx_id: str, - creation_info: CreationInfo, build_type: str, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/bundle.py b/src/spdx_tools/spdx3/model/bundle.py index 50f44d1d8..04ead471e 100644 --- a/src/spdx_tools/spdx3/model/bundle.py +++ b/src/spdx_tools/spdx3/model/bundle.py @@ -23,9 +23,9 @@ class Bundle(ElementCollection): def __init__( self, spdx_id: str, - creation_info: CreationInfo, element: List[str], root_element: List[str], + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py index 8eacc2716..8080a8dfe 100644 --- a/src/spdx_tools/spdx3/model/dataset/dataset.py +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -47,7 +47,6 @@ class Dataset(Package): def __init__( self, spdx_id: str, - creation_info: CreationInfo, name: str, originated_by: List[str], download_location: str, @@ -55,6 +54,7 @@ def __init__( built_time: datetime, release_time: datetime, dataset_type: str, + creation_info: Optional[CreationInfo] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/element.py b/src/spdx_tools/spdx3/model/element.py index 28e27171e..3b75dcf8a 100644 --- a/src/spdx_tools/spdx3/model/element.py +++ b/src/spdx_tools/spdx3/model/element.py @@ -12,7 +12,7 @@ @dataclass_with_properties class Element(ABC): spdx_id: str # IRI - creation_info: CreationInfo + creation_info: Optional[CreationInfo] = None name: Optional[str] = None summary: Optional[str] = None description: Optional[str] = None diff --git a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py index 497a99a8f..eccc913e9 100644 --- a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py +++ b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py @@ -34,10 +34,10 @@ class LifecycleScopedRelationship(Relationship): def __init__( self, spdx_id: str, - creation_info: CreationInfo, from_element: str, relationship_type: RelationshipType, to: List[str] = None, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/organization.py b/src/spdx_tools/spdx3/model/organization.py index 92531bee2..399079560 100644 --- a/src/spdx_tools/spdx3/model/organization.py +++ b/src/spdx_tools/spdx3/model/organization.py @@ -13,7 +13,7 @@ class Organization(Agent): def __init__( self, spdx_id: str, - creation_info: CreationInfo, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/person.py b/src/spdx_tools/spdx3/model/person.py index 7fc3b7221..266992cdf 100644 --- a/src/spdx_tools/spdx3/model/person.py +++ b/src/spdx_tools/spdx3/model/person.py @@ -13,7 +13,7 @@ class Person(Agent): def __init__( self, spdx_id: str, - creation_info: CreationInfo, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index c1d041f0f..9a207add4 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -97,10 +97,10 @@ class Relationship(Element): def __init__( self, spdx_id: str, - creation_info: CreationInfo, from_element: str, relationship_type: RelationshipType, to: List[str] = None, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py index 4a9f82dde..2b58d6385 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py @@ -26,11 +26,11 @@ class CvssV2VulnAssessmentRelationship(VulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInfo, from_element: str, - to: List[str], relationship_type: RelationshipType, + to: List[str], score: str, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py index 54967a726..cf3b104e0 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py @@ -26,11 +26,11 @@ class CvssV3VulnAssessmentRelationship(VulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInfo, from_element: str, to: List[str], relationship_type: RelationshipType, score: str, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py index 357e90f2c..820e7fe52 100644 --- a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py @@ -25,11 +25,11 @@ class EpssVulnAssessmentRelationship(VulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInfo, from_element: str, - to: List[str], relationship_type: RelationshipType, + to: List[str], probability: int, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py index 71261677b..fdbd8a337 100644 --- a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py @@ -32,13 +32,13 @@ class ExploitCatalogVulnAssessmentRelationship(VulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInfo, from_element: str, - to: List[str], relationship_type: RelationshipType, + to: List[str], catalog_type: ExploitCatalogType, exploited: bool, locator: str, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py index e75ffa4dc..9341eb6d3 100644 --- a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py @@ -32,11 +32,11 @@ class SsvcVulnAssessmentRelationship(VulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInfo, from_element: str, - to: List[str], relationship_type: RelationshipType, + to: List[str], decision: SsvcDecisionType, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py index 6d11ee92d..152ba6c62 100644 --- a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py @@ -26,10 +26,10 @@ class VexAffectedVulnAssessmentRelationship(VexVulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInfo, from_element: str, - to: List[str], relationship_type: RelationshipType, + to: List[str], + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py index f3bfeffb4..bddf492dd 100644 --- a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py @@ -22,10 +22,10 @@ class VexFixedVulnAssessmentRelationship(VexVulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInfo, from_element: str, - to: List[str], relationship_type: RelationshipType, + to: List[str], + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py index 9a1fad5a9..9ddb8d10c 100644 --- a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py @@ -35,10 +35,10 @@ class VexNotAffectedVulnAssessmentRelationship(VexVulnAssessmentRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInfo, from_element: str, - to: List[str], relationship_type: RelationshipType, + to: List[str], + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py index 55729c26d..29edc5074 100644 --- a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py @@ -22,10 +22,10 @@ class VexUnderInvestigationVulnAssessmentRelationship(VexVulnAssessmentRelations def __init__( self, spdx_id: str, - creation_info: CreationInfo, from_element: str, - to: List[str], relationship_type: RelationshipType, + to: List[str], + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/vulnerability.py b/src/spdx_tools/spdx3/model/security/vulnerability.py index 21680fd48..bae08afe3 100644 --- a/src/spdx_tools/spdx3/model/security/vulnerability.py +++ b/src/spdx_tools/spdx3/model/security/vulnerability.py @@ -18,7 +18,7 @@ class Vulnerability(Element): def __init__( self, spdx_id: str, - creation_info: CreationInfo, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py index 30496f17e..22918fda2 100644 --- a/src/spdx_tools/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -19,8 +19,8 @@ class File(SoftwareArtifact): def __init__( self, spdx_id: str, - creation_info: CreationInfo, name: str, + creation_info: Optional[CreationInfo] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py index 37570039f..0becb4f02 100644 --- a/src/spdx_tools/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -23,8 +23,8 @@ class Package(SoftwareArtifact): def __init__( self, spdx_id: str, - creation_info: CreationInfo, name: str, + creation_info: Optional[CreationInfo] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/sbom.py b/src/spdx_tools/spdx3/model/software/sbom.py index e3b019e33..c720bc198 100644 --- a/src/spdx_tools/spdx3/model/software/sbom.py +++ b/src/spdx_tools/spdx3/model/software/sbom.py @@ -36,9 +36,9 @@ class Sbom(Bom): def __init__( self, spdx_id: str, - creation_info: CreationInfo, element: List[str], root_element: List[str], + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py index 81e0ef7a9..3869de8b0 100644 --- a/src/spdx_tools/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -20,7 +20,7 @@ class Snippet(SoftwareArtifact): def __init__( self, spdx_id: str, - creation_info: CreationInfo, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py index fc77aa35e..08cfc3d2c 100644 --- a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py +++ b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py @@ -42,10 +42,10 @@ class SoftwareDependencyRelationship(LifecycleScopedRelationship): def __init__( self, spdx_id: str, - creation_info: CreationInfo, from_element: str, relationship_type: RelationshipType, to: List[str] = None, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/software_agent.py b/src/spdx_tools/spdx3/model/software_agent.py index fbd7d5890..1b5c7292a 100644 --- a/src/spdx_tools/spdx3/model/software_agent.py +++ b/src/spdx_tools/spdx3/model/software_agent.py @@ -13,7 +13,7 @@ class SoftwareAgent(Agent): def __init__( self, spdx_id: str, - creation_info: CreationInfo, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/spdx_document.py b/src/spdx_tools/spdx3/model/spdx_document.py index a5626a1f4..effc46f23 100644 --- a/src/spdx_tools/spdx3/model/spdx_document.py +++ b/src/spdx_tools/spdx3/model/spdx_document.py @@ -24,10 +24,10 @@ class SpdxDocument(Bundle): def __init__( self, spdx_id: str, - creation_info: CreationInfo, name: str, element: List[str], root_element: List[str], + creation_info: Optional[CreationInfo] = None, summary: Optional[str] = None, description: Optional[str] = None, comment: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/tool.py b/src/spdx_tools/spdx3/model/tool.py index da8f01b31..40efc4514 100644 --- a/src/spdx_tools/spdx3/model/tool.py +++ b/src/spdx_tools/spdx3/model/tool.py @@ -13,7 +13,7 @@ class Tool(Element): def __init__( self, spdx_id: str, - creation_info: CreationInfo, + creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/tests/spdx3/bump/test_relationship_bump.py b/tests/spdx3/bump/test_relationship_bump.py index c2ddf47d6..15f82415d 100644 --- a/tests/spdx3/bump/test_relationship_bump.py +++ b/tests/spdx3/bump/test_relationship_bump.py @@ -19,10 +19,10 @@ def test_relationship_bump(creation_info): assert relationship == Relationship( f"{document_namespace}#SPDXRef-Relationship-1", - creation_info, spdx2_relationship.spdx_element_id, RelationshipType.DESCRIBES, [spdx2_relationship.related_spdx_element_id], + creation_info=creation_info, comment=spdx2_relationship.comment, ) @@ -39,10 +39,10 @@ def test_relationships_bump(creation_info): assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-1") == Relationship( f"{document_namespace}#SPDXRef-Relationship-1", - creation_info, relationships[0].spdx_element_id, RelationshipType.DESCRIBES, [relationships[0].related_spdx_element_id, relationships[1].related_spdx_element_id], + creation_info=creation_info, ) @@ -63,27 +63,27 @@ def test_relationships_bump_with_setting_completeness(creation_info): assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-0") == Relationship( f"{document_namespace}#SPDXRef-Relationship-0", - creation_info, relationships[0].spdx_element_id, RelationshipType.DESCRIBES, [], + creation_info=creation_info, comment=relationships[0].comment, completeness=RelationshipCompleteness.NOASSERTION, ) assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-1") == Relationship( f"{document_namespace}#SPDXRef-Relationship-1", - creation_info, relationships[1].spdx_element_id, RelationshipType.DESCRIBES, [relationships[1].related_spdx_element_id], + creation_info=creation_info, comment=relationships[1].comment, ) assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-2") == Relationship( f"{document_namespace}#SPDXRef-Relationship-2", - creation_info, relationships[2].spdx_element_id, RelationshipType.SPECIFICATION_FOR, [], + creation_info=creation_info, completeness=RelationshipCompleteness.COMPLETE, ) diff --git a/tests/spdx3/model/ai/test_ai_package.py b/tests/spdx3/model/ai/test_ai_package.py index d65b822aa..52b2bf8ce 100644 --- a/tests/spdx3/model/ai/test_ai_package.py +++ b/tests/spdx3/model/ai/test_ai_package.py @@ -15,13 +15,13 @@ def test_correct_initialization(creation_info): ai_package = AIPackage( "some_spdx_id", - creation_info, "AI Package name", ["https://namespace.test#supplier"], "https://download.test", "1.2:rc2", [SoftwarePurpose.SOURCE], datetime(12, 5, 23, 11), + creation_info=creation_info, energy_consumption="energy consumption", standard_compliance=["some standard"], limitation="limitation", @@ -66,13 +66,13 @@ def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: AIPackage( "some_spdx_id", - creation_info, "AI Package name", ["https://namespace.test#supplier"], "https://download.test", "1.2:rc2", [SoftwarePurpose.SOURCE], datetime(12, 5, 23, 11), + creation_info, metric={"metric1": "value", "metric2": 250}, ) diff --git a/tests/spdx3/model/build/test_build.py b/tests/spdx3/model/build/test_build.py index d5d0aefa3..6e8671b2f 100644 --- a/tests/spdx3/model/build/test_build.py +++ b/tests/spdx3/model/build/test_build.py @@ -14,7 +14,7 @@ def test_correct_initialization(creation_info): build = Build( "some_spdx_id", - creation_info, + creation_info=creation_info, build_type="build type", build_id="build id", config_source_entrypoint=["entrypoint"], @@ -42,7 +42,7 @@ def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: Build( "some_spdx_id", - creation_info, + creation_info=creation_info, build_type="build type", config_source_digest=["hash_value"], ) diff --git a/tests/spdx3/model/dataset/test_dataset.py b/tests/spdx3/model/dataset/test_dataset.py index be780c8ae..47ccc9e20 100644 --- a/tests/spdx3/model/dataset/test_dataset.py +++ b/tests/spdx3/model/dataset/test_dataset.py @@ -14,7 +14,6 @@ def test_correct_initialization(creation_info): dataset = Dataset( "some_spdx_id", - creation_info, "Dataset name", ["https://namespace.test#originator"], "https://download.test", @@ -22,6 +21,7 @@ def test_correct_initialization(creation_info): datetime(10, 5, 23, 11), datetime(11, 5, 24, 12), "training data", + creation_info=creation_info, data_collection_process="data collection process", intended_use="intended use", dataset_size=420000, @@ -61,7 +61,6 @@ def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: Dataset( "some_spdx_id", - creation_info, "Dataset name", ["https://namespace.test#originator"], "https://download.test", @@ -69,6 +68,7 @@ def test_invalid_initialization(creation_info): datetime(10, 5, 23, 11), datetime(11, 5, 24, 12), "training data", + creation_info=creation_info, sensor={"sensor1": "value", "sensor2": 250}, ) diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py index ea8687c6d..c74861e75 100644 --- a/tests/spdx3/model/software/test_file.py +++ b/tests/spdx3/model/software/test_file.py @@ -12,8 +12,8 @@ def test_correct_initialization(creation_info): file = File( "SPDXRef-File", - creation_info, "Test file", + creation_info=creation_info, verified_using=None, content_identifier="https://any.uri", purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE], @@ -33,8 +33,8 @@ def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: File( 1, - creation_info, "test file", + creation_info=creation_info, content_identifier=3, purpose=SoftwarePurpose.FILE, content_type=SoftwarePurpose.ARCHIVE, diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py index 17312b83c..3e1814fcb 100644 --- a/tests/spdx3/model/software/test_package.py +++ b/tests/spdx3/model/software/test_package.py @@ -13,8 +13,8 @@ def test_correct_initialization(creation_info): package = Package( "SPDXRef-Package", - creation_info, "Test package", + creation_info=creation_info, content_identifier="https://any.uri", originated_by=["https://namespace.test#originator"], supplied_by=["https://namespace.test#supplier"], @@ -53,8 +53,8 @@ def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: Package( "SPDXRef-Package", - creation_info, "Test package", + creation_info=creation_info, built_time="2022-03-04T00:00:00Z", content_identifier=3, purpose=SoftwarePurpose.FILE, diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py index 64f55300e..97e53a93e 100644 --- a/tests/spdx3/model/software/test_sbom.py +++ b/tests/spdx3/model/software/test_sbom.py @@ -12,7 +12,7 @@ def test_correct_initialization(creation_info): sbom = Sbom( "SPDXRef-Sbom", - creation_info, + creation_info=creation_info, element=["spdx_id1", "spdx_id2"], root_element=["spdx_id3"], sbom_type=[SBOMType.DESIGN], @@ -27,7 +27,7 @@ def test_correct_initialization(creation_info): def test_invalid_initialization(): with pytest.raises(TypeError) as err: - Sbom(2, {"creation_info": [3, 4, 5]}, element=[], root_element=[]) + Sbom(2, creation_info={"creation_info": [3, 4, 5]}, element=[], root_element=[]) assert len(err.value.args[0]) == 2 for error in err.value.args[0]: diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index caa5e063a..042493562 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -12,7 +12,7 @@ def test_correct_initialization(creation_info): snippet = Snippet( "SPDXRef-Snippet", - creation_info, + creation_info=creation_info, content_identifier="https://content.identifier", purpose=[SoftwarePurpose.SOURCE], byte_range=(3, 4), @@ -30,7 +30,7 @@ def test_correct_initialization(creation_info): @mock.patch("spdx_tools.spdx3.model.software.Snippet", autospec=True) def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: - Snippet(2, creation_info, originated_by=34, byte_range="34:45") + Snippet(2, creation_info=creation_info, originated_by=34, byte_range="34:45") assert len(err.value.args[0]) == 3 for error in err.value.args[0]: diff --git a/tests/spdx3/model/software/test_software_dependency_relationship.py b/tests/spdx3/model/software/test_software_dependency_relationship.py index 303896cd7..bb495d1bc 100644 --- a/tests/spdx3/model/software/test_software_dependency_relationship.py +++ b/tests/spdx3/model/software/test_software_dependency_relationship.py @@ -18,10 +18,10 @@ def test_correct_initialization(creation_info): relationship = SoftwareDependencyRelationship( "SPDXRef-Relationship", - creation_info, "spdx_id1", RelationshipType.DESCRIBES, ["spdx_id2", "spdx_id3"], + creation_info=creation_info, completeness=RelationshipCompleteness.NOASSERTION, start_time=datetime(11, 11, 11), end_time=datetime(12, 12, 12), @@ -48,10 +48,10 @@ def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: SoftwareDependencyRelationship( "SPDXRef-Relationship", - creation_info, "spdx_id1", RelationshipType.DESCRIBES, - 42, + to=42, + creation_info=creation_info, ) assert len(err.value.args[0]) == 1 From 775bc046fcbea7c0bdb20e34ff403a760f0ed9d2 Mon Sep 17 00:00:00 2001 From: HarshvMahawar Date: Fri, 26 May 2023 14:53:29 +0530 Subject: [PATCH 230/354] Add fixture dictionary for Dataset profile Signed-off-by: HarshvMahawar --- tests/spdx3/fixtures.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 586ff7a3e..1817e444b 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -33,6 +33,7 @@ SpdxDocument, Tool, ) +from spdx_tools.spdx3.model.dataset.dataset import ConfidentialityLevelType, Dataset, DatasetAvailabilityType from spdx_tools.spdx3.model.licensing import ( CustomLicense, CustomLicenseAddition, @@ -350,6 +351,21 @@ def namespace_map_fixture( "conditionality": DependencyConditionalityType.OTHER, } +DATASET_DICT = { + "data_collection_process": "DatasetDataCollectionProcess", + "intended_use": "DatasetIntendedUse", + "dataset_size": 10, + "dataset_noise": "DatasetNoise", + "data_preprocessing": ["DataPreprocessing"], + "sensor": {"SensorKey": "SensorValue"}, + "known_bias": ["DatasetKnownBias"], + "sensitive_personal_information": True, + "anonymization_method_used": ["DatasetAnonymizationMethodUsed"], + "confidentiality_level": ConfidentialityLevelType.CLEAR, + "dataset_update_mechanism": "DatasetUpdateMechanism", + "dataset_availability": DatasetAvailabilityType.QUERY, +} + FIXTURE_DICTS = { Agent: [ELEMENT_DICT], @@ -436,6 +452,7 @@ def namespace_map_fixture( LIFECYCLE_SCOPED_RELATIONSHIP_DICT, SOFTWARE_DEPENDENCY_RELATIONSHIP_DICT, ], + Dataset: [ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT, PACKAGE_DICT, DATASET_DICT], } From 07f4df5fc21ef9c750ea459726475174dc3a111a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 26 Apr 2023 15:47:43 +0200 Subject: [PATCH 231/354] [issue-489] add basic json-ld converter and writer utilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../spdx3/writer/json_ld/SPDX_OWL.json | 1962 +++++++++++++++++ .../spdx3/writer/json_ld/__init__.py | 0 .../spdx3/writer/json_ld/context.json | 238 ++ .../spdx3/writer/json_ld/json_ld_converter.py | 77 + .../spdx3/writer/json_ld/json_ld_writer.py | 20 + src/spdx_tools/spdx3/writer/json_ld/model.ttl | 1654 ++++++++++++++ .../spdx3/writer/json_ld/owl_to_context.py | 48 + tests/spdx3/writer/__init__.py | 0 tests/spdx3/writer/json_ld/__init__.py | 0 .../writer/json_ld/test_json_ld_writer.py | 19 + 10 files changed, 4018 insertions(+) create mode 100644 src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json create mode 100644 src/spdx_tools/spdx3/writer/json_ld/__init__.py create mode 100644 src/spdx_tools/spdx3/writer/json_ld/context.json create mode 100644 src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py create mode 100644 src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py create mode 100644 src/spdx_tools/spdx3/writer/json_ld/model.ttl create mode 100644 src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py create mode 100644 tests/spdx3/writer/__init__.py create mode 100644 tests/spdx3/writer/json_ld/__init__.py create mode 100644 tests/spdx3/writer/json_ld/test_json_ld_writer.py diff --git a/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json b/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json new file mode 100644 index 000000000..f88842ffe --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json @@ -0,0 +1,1962 @@ +{ + "@context": { + "ai": "https://spdx.org/rdf/AI#", + "build": "https://spdx.org/rdf/Build#", + "core": "https://spdx.org/rdf/Core#", + "dataset": "https://spdx.org/rdf/Dataset#", + "ns0": "http://www.w3.org/2003/06/sw-vocab-status/ns#", + "owl": "http://www.w3.org/2002/07/owl#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#", + "software": "https://spdx.org/rdf/Software#", + "xsd": "http://www.w3.org/2001/XMLSchema#" + }, + "@graph": [ + { + "@id": "ai:AIPackage", + "@type": "owl:Class", + "rdfs:comment": "Metadata information that can be added to a package to describe an AI application or trained AI model.", + "rdfs:subClassOf": { + "@id": "https://spdx.org/rdf/AI#/Software/Package" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:autonomyType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "AutonomyType indicates if a human is involved in any of the decisions of the AI software\nor if that software is fully automatic.", + "rdfs:range": { + "@id": "ai:PresenceType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:domain", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Domain describes the domain in which the AI model contained in the AI software\ncan be expected to operate successfully. Examples include computer vision, natural language etc.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:energyConsumption", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "EnergyConsumption captures the amount of energy needed to train and operate the AI model. \nThis value is also known as training energy consumption or inference energy consumption.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:high", + "@type": [ + "owl:NamedIndividual", + "ai:SafetyRiskAssessmentType" + ] + }, + { + "@id": "ai:hyperparameters", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field records important hyperparameter values.\nThese are parameters of the machine learning model that are used to control the learning process,\nfor example the optimization and learning rate used during the training of the model.", + "rdfs:range": { + "@id": "https://spdx.org/rdf/AI#/Core/DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:informationAboutApplication", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "InformationAboutApplication describes any relevant information in free form text about \nhow the AI model is used inside the software, as well as any relevant pre-processing steps, third party APIs etc.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:informationAboutTraining", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "InformationAboutTraining describes the specific steps involved in the training of the AI model.\nFor example, it can be specified whether supervised fine-tuning \nor active learning is used as part of training the model.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:limitations", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Limitations captures limitations of the AI Package (or of the AI models present in the AI package),\nexpressed as free form text. Note that this is not guaranteed to be exhaustive.\nFor instance, a limitation might be that the AI package cannot be used on datasets from a certain demography.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:low", + "@type": [ + "owl:NamedIndividual", + "ai:SafetyRiskAssessmentType" + ] + }, + { + "@id": "ai:medium", + "@type": [ + "owl:NamedIndividual", + "ai:SafetyRiskAssessmentType" + ] + }, + { + "@id": "ai:metrics", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Metrics records the measurements with which the AI model was evaluated. \nThis makes statements about the prediction quality including uncertainty,\naccuracy, characteristics of the tested population, quality, fairness, explainability, robustness etc.", + "rdfs:range": { + "@id": "https://spdx.org/rdf/AI#/Core/DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:metricsDecisionThresholds", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Each metric might be computed based on a decision threshold. \nFor instance, precision or recall is typically computed by checking\nif the probability of the outcome is larger than 0.5.\nEach decision threshold should match with the metrics field defined in the AI Package.", + "rdfs:range": { + "@id": "https://spdx.org/rdf/AI#/Core/DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:modelDataPreprocessingSteps", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ModelDataPreprocessingSteps is a free form text that describes the preprocessing steps\napplied to the training data before training of the model(s) contained in the AI software.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:modelExplainabilityMechanisms", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ModelExplainabilityMechanisms is a free form text that lists the different explainability mechanisms\n(such as SHAP, or other model specific explainability mechanisms) that can be used to explain the model.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:no", + "@type": [ + "owl:NamedIndividual", + "ai:PresenceType" + ] + }, + { + "@id": "ai:noassertion", + "@type": [ + "owl:NamedIndividual", + "ai:PresenceType" + ] + }, + { + "@id": "ai:safetyRiskAssessment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SafetyRiskAssessment categorizes the safety risk impact of the AI software\nin accordance with Article 20 of [EC Regulation No 765/2008](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).", + "rdfs:range": { + "@id": "ai:SafetyRiskAssessmentType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:sensitivePersonalInformation", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SensitivePersonalInformation notes if sensitive personal information\nis used in the training or inference of the AI models.\nThis might include biometric data, addresses or other data that can be used to infer a person's identity.", + "rdfs:range": { + "@id": "ai:PresenceType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:serious", + "@type": [ + "owl:NamedIndividual", + "ai:SafetyRiskAssessmentType" + ] + }, + { + "@id": "ai:standardsCompliance", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "StandardsCompliance captures standards that the AI software complies with. \nThis could include both published and unpublished standards including ISO, IEEE, ETSI etc. \nThese standards could (but not necessarily have to) be used to satisfy a legal or regulatory requirement.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:typeOfModel", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "TypeOfModel records the type of the AI model(s) used in the software. \nFor instance, if it is a supervised model, unsupervised model, reinforcement learning model or a combination of those.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:yes", + "@type": [ + "owl:NamedIndividual", + "ai:PresenceType" + ] + }, + { + "@id": "build:Build", + "@type": "owl:Class", + "rdfs:comment": "A build is a representation of the process in which a piece of software or artifact is built. It encapsulates information related to a build process and\nprovides an element from which relationships can be created to describe the build's inputs, outputs, and related entities (e.g. builders, identities, etc.).\n\nDefinitions of \"BuildType\", \"ConfigSource\", \"Parameters\" and \"Environment\" follow\nthose defined in [SLSA provenance](https://slsa.dev/provenance/v0.2).\n\nExternalIdentifier of type \"urlScheme\" may be used to identify build logs. In this case, the comment of the ExternalIdentifier should be \"LogReference\".\n\nNote that buildStart and buildEnd are optional, and may be omitted to simplify creating reproducible builds.", + "rdfs:subClassOf": { + "@id": "https://spdx.org/rdf/Build#/Core/Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:buildEnd", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "buildEnd describes the time at which a build stops or finishes. This value is typically recorded by the builder.", + "rdfs:range": { + "@id": "xsd:dateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:buildId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A buildId is a locally unique identifier to identify a unique instance of a build. This identifier differs based on build toolchain, platform, or naming convention used by an organization or standard.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:buildStart", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "buildStart is the time at which a build is triggered. The builder typically records this value.", + "rdfs:range": { + "@id": "xsd:dateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:buildType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A buildType is a URI expressing the toolchain, platform, or infrastructure that the build was invoked on. For example, if the build was invoked on GitHub's CI platform using github actions, the buildType can be expressed as `https://github.com/actions`. In contrast, if the build was invoked on a local machine, the buildType can be expressed as `file://username@host/path/to/build`.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:configSourceDigest", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "configSourceDigest is the checksum of the build configuration file used by a builder to execute a build. This Property uses the Core model's [Hash](../../Core/Classes/Hash.md) class.", + "rdfs:range": { + "@id": "https://spdx.org/rdf/Build#/Core/Hash" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:configSourceEntrypoint", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A build entrypoint is the invoked executable of a build which always runs when the build is triggered. For example, when a build is triggered by running a shell script, the entrypoint is `script.sh`. In terms of a declared build, the entrypoint is the position in a configuration file or a build declaration which is always run when the build is triggered. For example, in the following configuration file, the entrypoint of the build is `publish`.\n\n```\nname: Publish packages to PyPI\n\non:\ncreate:\ntags: \"*\"\n\njobs:\npublish:\nruns-on: ubuntu-latest\nif: startsWith(github.ref, 'refs/tags/')\nsteps:\n\n...\n```", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:configSourceUri", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "If a build configuration exists for the toolchain or platform performing the build, the configSourceUri of a build is the URI of that build configuration. For example, a build triggered by a GitHub action is defined by a build configuration YAML file. In this case, the configSourceUri is the URL of that YAML file. \nm", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:environment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "environment is a map of environment variables and values that are set during a build session. This is different from the [parameters](parameters.md) property in that it describes the environment variables set before a build is invoked rather than the variables provided to the builder.", + "rdfs:range": { + "@id": "https://spdx.org/rdf/Build#/Core/DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:parameters", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "parameters is a key-value map of all build parameters and their values that were provided to the builder for a build instance. This is different from the [environment](environment.md) property in that the keys and values are provided as command line arguments or a configuration file to the builder.", + "rdfs:range": { + "@id": "https://spdx.org/rdf/Build#/Core/DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Annotation", + "@type": "owl:Class", + "rdfs:comment": "An Annotation is an assertion made in relation to one or more elements.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:AnonymousPayload", + "@type": "owl:Class", + "rdfs:comment": "TODO", + "rdfs:subClassOf": { + "@id": "core:Payload" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Artifact", + "@type": "owl:Class", + "rdfs:comment": "An artifact is a distinct article or unit within the digital domain,\nsuch as an electronic file, a software package, a device or an element of data.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Bom", + "@type": "owl:Class", + "rdfs:comment": "A Bill Of Materials (BOM) is a container for a grouping of SPDX-3.0 content\ncharacterizing details about a product.\nThis could include details of the content and composition of the product,\nprovenence details of the product and/or\nits composition, licensing information, known quality or security issues, etc.", + "rdfs:subClassOf": { + "@id": "core:Bundle" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:DictionaryEntry", + "@type": "owl:Class", + "rdfs:comment": "The class used for implementing a generic string mapping (also known as associative array, dictionary, or hash map) in SPDX. Each DictionaryEntry contains a key-value pair which maps the key to its associated value. To implement a dictionary, this class is to be used in a collection with unique keys.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:Hash", + "@type": "owl:Class", + "rdfs:comment": "A hash is a grouping of characteristics unique to the result\nof applying a mathematical algorithm\nthat maps data of arbitrary size to a bit string (the hash)\nand is a one-way function, that is,\na function which is practically infeasible to invert.\nThis is commonly used for integrity checking of data.", + "rdfs:subClassOf": { + "@id": "core:IntegrityMethod" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Organization", + "@type": "owl:Class", + "rdfs:comment": "An Organization is a group of people who work together in an organized way for a shared purpose.", + "rdfs:subClassOf": { + "@id": "core:Identity" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Person", + "@type": "owl:Class", + "rdfs:comment": "A Person is an individual human being.", + "rdfs:subClassOf": { + "@id": "core:Identity" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:PositiveIntegerRange", + "@type": "owl:Class", + "rdfs:comment": "PositiveIntegerRange is a tuple of two positive integers that define a range.\n\"begin\" must be less than or equal to \"end\".", + "rdfs:subClassOf": { + "@id": "core:none" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Relationship", + "@type": "owl:Class", + "rdfs:comment": "A Relationship is a grouping of characteristics unique to an assertion\nthat one Element is related to one or more other Elements in some way.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:SpdxDocument", + "@type": "owl:Class", + "rdfs:comment": "An SpdxDocument assembles a collection of Elements under a common string, the name of the document.\nCommonly used when representing a unit of transfer of SPDX Elements.", + "rdfs:subClassOf": { + "@id": "core:Bundle" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:algorithm", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An algorithm specifies the algorithm that was used for calculating the hash value.", + "rdfs:range": { + "@id": "core:HashAlgorithm" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:altDownloadLocation", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "core:altWebPage", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "core:amends", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:ancestor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:annotationType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An annotationType describes the type of an annotation.", + "rdfs:range": { + "@id": "core:AnnotationType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:begin", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "begin is a positive integer that defines the beginning of a range.", + "rdfs:range": { + "@id": "xsd:positiveInteger" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:blake2b256", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:blake2b384", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:blake2b512", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:blake3", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:buildConfigOf", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:buildDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:buildHostOf", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:buildInputOf", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:buildInvokedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:buildOnBehalfOf", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:buildOutputOf", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:buildTool", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:builtTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A builtTime specifies the time an artifact was built.", + "rdfs:range": { + "@id": "xsd:dateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:comment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A comment is an optional field for creators of the Element to provide comments\nto the readers/reviewers of the document.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:complete", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipCompleteness" + ] + }, + { + "@id": "core:completeness", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Completeness gives information about whether the provided relationships are\ncomplete, known to be incomplete or if no assertion is made either way.", + "rdfs:range": { + "@id": "core:RelationshipCompleteness" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:contains", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:contentType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ContentType specifies the media type of an Element.", + "rdfs:range": { + "@id": "core:MediaType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:context", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A context gives information about the circumstances or unifying properties\nthat Elements of the bundle have been assembled under.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:copy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:cpe22", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "core:cpe23", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "core:created", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Created is a date that identifies when the Element was originally created.\nThe time stamp can serve as an indication as to whether the analysis needs to be updated. This is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.", + "rdfs:range": { + "@id": "xsd:dateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:createdBy", + "@type": "owl:ObjectProperty", + "rdfs:comment": "CreatedBy identifies who or what created the Element.\nThe generation method will assist the recipient of the Element in assessing\nthe general reliability/accuracy of the analysis information.", + "rdfs:range": { + "@id": "core:Entity" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:createdUsing", + "@type": "owl:ObjectProperty", + "rdfs:comment": "CreatedUsing identifies the tooling that was used during the creation of the Element.\nThe generation method will assist the recipient of the Element in assessing\nthe general reliability/accuracy of the analysis information.", + "rdfs:range": { + "@id": "core:Tool" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:creationInfo", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "CreationInfo provides information about the creation of the Element.", + "rdfs:range": { + "@id": "core:CreationInfo" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:dataFile", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:dataLicense", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The data license provides the license under which the SPDX documentation of the Element can be used.\nThis is to alleviate any concern that content (the data or database) in an SPDX file\nis subject to any form of intellectual property right that could restrict the re-use\nof the information or the creation of another SPDX file for the same project(s).\nThis approach avoids intellectual property and related restrictions over the SPDX file,\nhowever individuals can still contract with each other to restrict release\nof specific collections of SPDX files (which map to software bill of materials)\nand the identification of the supplier of SPDX files.\nCompliance with this document includes populating the SPDX fields therein\nwith data related to such fields (\"SPDX-Metadata\"). \nThis document contains numerous fields where an SPDX file creator may provide\nrelevant explanatory text in SPDX-Metadata. Without opining on the lawfulness\nof \"database rights\" (in jurisdictions where applicable),\nsuch explanatory text is copyrightable subject matter in most Berne Convention countries.\nBy using the SPDX specification, or any portion hereof,\nyou hereby agree that any copyright rights (as determined by your jurisdiction)\nin any SPDX-Metadata, including without limitation explanatory text,\nshall be subject to the terms of the Creative Commons CC0 1.0 Universal license. \nFor SPDX-Metadata not containing any copyright rights, \nyou hereby agree and acknowledge that the SPDX-Metadata is provided to you “as-is”\nand without any representations or warranties of any kind concerning the SPDX-Metadata,\nexpress, implied, statutory or otherwise, including without limitation warranties\nof title, merchantability, fitness for a particular purpose, non-infringement,\nor the absence of latent or other defects, accuracy, or the presence or absence of errors,\nwhether or not discoverable, all to the greatest extent permissible under applicable law.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:dependencyManifest", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:dependsOn", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:descendant", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:describes", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:description", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field is a detailed description of the Element. It may also be extracted from the Element itself.\nThe intent is to provide recipients of the SPDX file with a detailed technical explanation\nof the functionality, anticipated use, and anticipated implementation of the Element.\nThis field may also include a description of improvements over prior versions of the Element.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:devDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:devTool", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:distributionArtifact", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:documentation", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:dynamicLink", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:element", + "@type": "owl:ObjectProperty", + "rdfs:comment": "This field refers to one or more Elements that are part of an ElementCollection.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:email", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "core:end", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "end is a positive integer that defines the end of a range.", + "rdfs:range": { + "@id": "xsd:positiveInteger" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:example", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:expandedFromArchive", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:extension", + "rdfs:comment": "TODO", + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ExternalId identifies an external Element used within a Document but defined external to that Document.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalIdentifier", + "@type": "owl:ObjectProperty", + "rdfs:comment": "ExternalIdentifier points to a resource outside the scope of SPDX-3.0 content\nthat uniquely identifies an Element.", + "rdfs:range": { + "@id": "core:ExternalIdentifier" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalIdentifierType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An externalIdentifierType specifies the type of the external identifier.", + "rdfs:range": { + "@id": "core:ExternalIdentifierType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalReference", + "@type": "owl:ObjectProperty", + "rdfs:comment": "This field points to a resource outside the scope of the SPDX-3.0 content\nthat provides additional characteristics of an Element.", + "rdfs:range": { + "@id": "core:ExternalReference" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalReferenceType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An externalReferenceType specifies the type of the external reference.", + "rdfs:range": { + "@id": "core:ExternalReferenceType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:fileAdded", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:fileDeleted", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:fileModified", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:from", + "@type": "owl:ObjectProperty", + "rdfs:comment": "This field references the Element on the left-hand side of a relationship.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:generates", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:gitoid", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "core:hashValue", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "HashValue is the result of applying a hash algorithm to an Element.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:imports", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Imports provides an ExternalMap of Element identifiers that are used within a document\nbut defined external to that document.", + "rdfs:range": { + "@id": "core:ExternalMap" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:incomplete", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipCompleteness" + ] + }, + { + "@id": "core:key", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A key used in generic a key-value pair.\nA key-value pair can be used to implement a dictionary which associates a key with a value.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:locationHint", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A locationHint provides an indication of where to retrieve an external Element.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:locator", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A locator provides the location of an external reference.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:md2", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:md4", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:md5", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:md6", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:metafile", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:name", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field identifies the name of an Element as designated by the creator. \nThe name of an Element is an important convention and easier to refer to than the URI.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:namespace", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A namespace provides an unambiguous mechanism for other documents to reference Elements within this document.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:namespaces", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field provides a NamespaceMap applicable to an ElementCollection.", + "rdfs:range": { + "@id": "core:NamespaceMap" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:optionalComponent", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:optionalDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:originatedBy", + "@type": "owl:ObjectProperty", + "rdfs:comment": "OriginatedBy identifies from where or whom the Element originally came.", + "rdfs:range": { + "@id": "core:Identity" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:other", + "@type": [ + "owl:NamedIndividual", + "core:AnnotationType", + "core:ExternalIdentifierType", + "core:ExternalReferenceType", + "core:HashAlgorithm", + "core:RelationshipType" + ] + }, + { + "@id": "core:packages", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:patch", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:pkgUrl", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "core:prefix", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A prefix is a substitute for a URI.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:prerequisite", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:profile", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field provides information about which profiles the Element belongs to.", + "rdfs:range": { + "@id": "core:ProfileIdentifier" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:providedDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:relationshipType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field provides information about the relationship between two Elements.\nFor example, you can represent a relationship between two different Files,\nbetween a Package and a File, between two Packages, or between one SPDXDocument and another SPDXDocument.", + "rdfs:range": { + "@id": "core:RelationshipType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:releaseTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A releaseTime specifies the time an artifact was released.", + "rdfs:range": { + "@id": "xsd:dateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:requirementFor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:review", + "@type": [ + "owl:NamedIndividual", + "core:AnnotationType" + ] + }, + { + "@id": "core:rootElement", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A rootElement of a collection is the top level Element from which all other Elements are reached via relationships.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:runtimeDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:securityAdvisory", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "core:securityFix", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "core:securityOther", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "core:sha1", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:sha224", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:sha256", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:sha384", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:sha3_224", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:sha3_256", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:sha3_384", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:sha3_512", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:sha512", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:spdxId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SpdxId uniquely identifies an Element which may thereby be referenced by other Elements.\nThese references may be internal or external.\nWhile there may be several versions of the same Element, each one needs to be able to be referred to uniquely\nso that relationships between Elements can be clearly articulated.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:spdxPvcSha1", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:spdxPvcSha256", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] + }, + { + "@id": "core:specVersion", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The specVersion provides a reference number that can be used to understand how to parse and interpret an Element.\nIt will enable both future changes to the specification and to support backward compatibility.\nThe major version number shall be incremented when incompatible changes between versions are made\n(one or more sections are created, modified or deleted).\nThe minor version number shall be incremented when backwards compatible changes are made.\n\nHere, parties exchanging information in accordance with the SPDX specification need to provide \n100% transparency as to which SPDX specification version such information is conforming to.", + "rdfs:range": { + "@id": "core:SemVer" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:specificationFor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:statement", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A statement is a commentary on an assertion that an annotator has made.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:staticLink", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:subject", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A subject is an Element an annotator has made an assertion about.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:summary", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A summary is a short description of an Element. Here, the intent is to allow the Element creator to \nprovide concise information about the function or use of the Element.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:suppliedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:swhid", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "core:swid", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "core:test", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:testCase", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:testDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:testTool", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:to", + "@type": "owl:ObjectProperty", + "rdfs:comment": "This field references an Element on the right-hand side of a relationship.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:unknown", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipCompleteness" + ] + }, + { + "@id": "core:urlScheme", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "core:validUntilTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A validUntilTime specifies until when the artifact can be used before its usage needs to be reassessed.", + "rdfs:range": { + "@id": "xsd:dateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:value", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A value used in a generic key-value pair.\nA key-value pair can be used to implement a dictionary which associates a key with a value.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:variant", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:verifiedUsing", + "@type": "owl:ObjectProperty", + "rdfs:comment": "VerifiedUsing provides an IntegrityMethod with which the integrity of an Element can be asserted.", + "rdfs:range": { + "@id": "core:IntegrityMethod" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:Dataset", + "@type": "owl:Class", + "rdfs:comment": "Metadata information that can be added to a dataset that may be used in a software or to train/test an AI package.", + "rdfs:subClassOf": { + "@id": "https://spdx.org/rdf/Dataset#/Software/Package" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:anonymizationMethodUsed", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "AnonymizationMethodUsed describes the methods used to anonymize the dataset (of fields in the dataset).", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:confidentialityLevel", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ConfidentialityLevel describes the levels of confidentiality of the data points contained in the dataset.", + "rdfs:range": { + "@id": "dataset:ConfidentialityLevelType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:dataCollectionProcess", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DataCollectionProcess describes how a dataset was collected.\nExamples include the sources from which a dataset was scrapped or\nthe interview protocol that was used for data collection.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:dataPreprocessing", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DataPreprocessing describes the various preprocessing steps\nthat were applied to the raw data to create the dataset.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetAvailability", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Some datasets are publicly available and can be downloaded directly. Others are only accessible behind a clickthrough, or after filling a registration form. This field will describe the dataset availability from that perspective.", + "rdfs:range": { + "@id": "dataset:DatasetAvailabilityType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetNoise", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DatasetNoise describes what kinds of noises a dataset might encompass.\nThe field uses free form text to specify the fields or the samples that might be noisy.\nAlternatively, it can also be used to describe various noises that could impact the whole dataset.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetSize", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DatasetSize Captures how large a dataset is.\nThe size is to be measured in bytes.", + "rdfs:range": { + "@id": "xsd:nonNegativeInteger" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetUpdateMechanism", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DatasetUpdateMechanism describes a mechanism to update the dataset.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:intendedUse", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "IntendedUse describes what the given dataset should be used for.\nSome datasets are collected to be used only for particular purposes. \nFor example, medical data collected from a specific demography might only be applicable\nfor training machine learning models to make predictions for that demography.\nIn such a case, the intendedUse field would capture this information.\nSimilarly, if a dataset is collected for building a facial recognition model,\nthe intendedUse field would specify that.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:knownBias", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "KnownBias is a free form text field that describes the different biases that the dataset encompasses.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:sensitivePersonalInformation", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SensitivePersonalInformation indicates the presence of sensitive personal data\nor information that allows drawing conclusions about a person's identity.", + "rdfs:range": { + "@id": "dataset:PresenceType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:sensor", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Sensor describes a sensor that was used for collecting the data\nand its calibration value as a key-value pair.", + "rdfs:range": { + "@id": "https://spdx.org/rdf/Dataset#/Core/DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:File", + "@type": "owl:Class", + "rdfs:comment": "TODO This is about the File class.", + "rdfs:subClassOf": { + "@id": "https://spdx.org/rdf/Software#/Core/Artifact" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:Package", + "@type": "owl:Class", + "rdfs:comment": "A package refers to any unit of content that can be associated with a distribution of software.\nTypically, a package is composed of one or more files. \nAny of the following non-limiting examples may be (but are not required to be) represented in SPDX as a package:\n\n - a tarball, zip file or other archive\n - a directory or sub-directory\n - a separately distributed piece of software which another Package or File uses or depends upon (e.g., a Python package, a Go module, ...)\n - a container image, and/or each image layer within a container image\n - a collection of one or more sub-packages\n - a Git repository snapshot from a particular point in time\n\nNote that some of these could be represented in SPDX as a file as well.", + "rdfs:subClassOf": { + "@id": "https://spdx.org/rdf/Software#/Core/Artifact" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:Sbom", + "@type": "owl:Class", + "rdfs:comment": "A Software Bill of Materials (SBOM) is a collection of SPDX Elements describing a single package.\nThis could include details of the content and composition of the product,\nprovenance details of the product and/or\nits composition, licensing information, known quality or security issues, etc.", + "rdfs:subClassOf": { + "@id": "https://spdx.org/rdf/Software#/Core/Bom" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:Snippet", + "@type": "owl:Class", + "rdfs:comment": "A Snippet describes a certain part of a file and can be used when the file is known to have some content\nthat has been included from another original source. Snippets are useful for denoting when part of a file\nmay have been originally created under another license or copied from a place with a known vulnerability.", + "rdfs:subClassOf": { + "@id": "https://spdx.org/rdf/Software#/Core/Artifact" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:application", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:archive", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:bom", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:byteRange", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field defines the byte range in the original host file that the snippet information applies to.\nA range of bytes is independent of various formatting concerns, and the most accurate way \nof referring to the differences. The choice was made to start the numbering of \nthe byte range at 1 to be consistent with the W3C pointer method vocabulary.", + "rdfs:range": { + "@id": "software:positiveIntegerRange" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:configuration", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:container", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:contentIdentifier", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A contentIdentifier is TODO", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:contentType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field is a reasonable estimation of the content type of the Element, from a creator perspective.\nContent type is intrinsic to the Element, independent of how the Element is being used.", + "rdfs:range": { + "@id": "software:mediaType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:data", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:device", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:documentation", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:downloadLocation", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DownloadLocation identifies the download Uniform Resource Identifier \nfor the package at the time that the document was created.\nWhere and how to download the exact package being referenced \nis critical for verification and tracking data.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:executable", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:file", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:filePurpose", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "FilePurpose provides information about the primary purpose of the file.", + "rdfs:range": { + "@id": "software:SoftwarePurpose" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:firmware", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:framework", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:homePage", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "HomePage is a place for the SPDX document creator to record a website that serves as the package's home page.\nThis saves the recipient of the SPDX document who is looking for more info from\nhaving to search for and verify a match between the package and the associated project home page.\nThis link can also be used to reference further information about the package\nreferenced by the SPDX document creator.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:install", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:library", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:lineRange", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field defines the line range in the original host file that the snippet information applies to.\nIf there is a disagreement between the byte range and line range, the byte range values will take precedence.\nA range of lines is a convenient reference for those files where there is a known line delimiter. \nThe choice was made to start the numbering of the lines at 1 to be consistent with the W3C pointer method vocabulary.", + "rdfs:range": { + "@id": "software:positiveIntegerRange" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:module", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:operatingSystem", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:other", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:packagePurpose", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "PackagePurpose provides information about the primary purpose of the package.", + "rdfs:range": { + "@id": "software:SoftwarePurpose" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:packageUrl", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A packageUrl is TODO", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:packageVersion", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A packageVersion is useful for identification purposes and for indicating later changes of the package version.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:patch", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:snippetPurpose", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SnippetPurpose provides information about the primary purpose of the snippet.", + "rdfs:range": { + "@id": "software:SoftwarePurpose" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:source", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:sourceInfo", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SourceInfo records any relevant background information or additional comments\nabout the origin of the package. For example, this field might include comments \nindicating whether the package was pulled from a source code management system \nor has been repackaged. The creator can provide additional information to describe\nany anomalies or discoveries in the determination of the origin of the package.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:CreationInfo", + "@type": "owl:Class", + "rdfs:comment": "The CreationInfo provides information about who created the Element, and when and how it was created. \n\nThe dateTime created is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:ElementCollection", + "@type": "owl:Class", + "rdfs:comment": "An SpdxCollection is a collection of Elements, not necessarily with unifying context.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:ExternalIdentifier", + "@type": "owl:Class", + "rdfs:comment": "An ExternalIdentifier is a reference to a resource outside the scope of SPDX-3.0 content\nthat uniquely identifies an Element.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:ExternalMap", + "@type": "owl:Class", + "rdfs:comment": "An External Map is a map of Element identifiers that are used within a Document\nbut defined external to that Document.\nThe external map provides details about the externally-defined Element\nsuch as its provenance, where to retrieve it, and how to verify its integrity.", + "rdfs:subClassOf": { + "@id": "core:none" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:ExternalReference", + "@type": "owl:Class", + "rdfs:comment": "An External Reference points to a resource outside the scope of the SPDX-3.0 content\nthat provides additional characteristics of an Element.", + "rdfs:subClassOf": { + "@id": "core:none" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:MediaType", + "@type": "owl:Class", + "rdfs:comment": "The MediaType is a String constrained to the RFC 2046 specification. It provides a standardized\nway of indicating the type of content of an Element.\nA list of all possible media types is available at https://www.iana.org/assignments/media-types/media-types.xhtml.", + "rdfs:subClassOf": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:NamespaceMap", + "@type": "owl:Class", + "rdfs:comment": "A namespace map allows the creator of a collection of Elements to use\nshorter identifiers (\"prefixes\") instead of URIs to provide a more\nhuman-readable and smaller serialized representation of the Elements.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:ProfileIdentifier", + "@type": "owl:Class", + "rdfs:comment": "A profile identifier provides the profile that the Element is specified in.", + "rdfs:subClassOf": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:SemVer", + "@type": "owl:Class", + "rdfs:comment": "The semantic version is a String constrained to the SemVer 2.0.0 specification.", + "rdfs:subClassOf": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Tool", + "@type": "owl:Class", + "rdfs:comment": "A Tool is an element of hardware and/or software utilized to carry out a particular function.", + "rdfs:subClassOf": { + "@id": "core:Entity" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Bundle", + "@type": "owl:Class", + "rdfs:comment": "A bundle is a collection of Elements that have a shared context.", + "rdfs:subClassOf": { + "@id": "core:ElementCollection" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:IntegrityMethod", + "@type": "owl:Class", + "rdfs:comment": "An IntegrityMethod provides an independently reproducible mechanism that permits verification\nof a specific Element that correlates to the data in this SPDX document. This identifier enables\na recipient to determine if anything in the original Element has been changed and eliminates\nconfusion over which version or modification of a specific Element is referenced.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:Payload", + "@type": "owl:Class", + "rdfs:comment": "TODO", + "rdfs:subClassOf": { + "@id": "core:none" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:AnnotationType", + "@type": "owl:Class", + "rdfs:comment": "AnnotationType specifies the type of an annotation.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:Entity", + "@type": "owl:Class", + "rdfs:comment": "TODO", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Identity", + "@type": "owl:Class", + "rdfs:comment": "An Identity is a grouping of identifying characteristics unique to an individual or organization.", + "rdfs:subClassOf": { + "@id": "core:Entity" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:RelationshipCompleteness", + "@type": "owl:Class", + "rdfs:comment": "RelationshipCompleteness indicates whether a relationship is complete or \nknown to be incomplete or if there is made no assertion either way.", + "ns0:term_status": "Stable" + }, + { + "@id": "ai:PresenceType", + "@type": "owl:Class", + "rdfs:comment": "This type is used to indicate if a given field is present or absent or unknown.", + "ns0:term_status": "Stable" + }, + { + "@id": "ai:SafetyRiskAssessmentType", + "@type": "owl:Class", + "rdfs:comment": "Lists the different safety risk type values that can be used to describe the safety risk of AI software\naccording to [Article 20 of Regulation 765/2008/EC](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).", + "ns0:term_status": "Stable" + }, + { + "@id": "core:ExternalReferenceType", + "@type": "owl:Class", + "rdfs:comment": "ExteralReferenceType specifies the type of an external reference.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:Element", + "@type": "owl:Class", + "rdfs:comment": "An Element is a representation of a fundamental concept either directly inherent\nto the Bill of Materials (BOM) domain or indirectly related to the BOM domain\nand necessary for contextually characterizing BOM concepts and relationships.\nWithin SPDX-3.0 structure this is the base class acting as a consistent,\nunifying, and interoperable foundation for all explicit\nand inter-relatable content objects.", + "rdfs:subClassOf": { + "@id": "core:Payload" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:ExternalIdentifierType", + "@type": "owl:Class", + "rdfs:comment": "ExteralIdentifierType specifies the type of an external identifier.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:HashAlgorithm", + "@type": "owl:Class", + "rdfs:comment": "A HashAlgorithm is a mathematical algorithm that maps data of arbitrary size to a bit string (the hash)\nand is a one-way function, that is, a function which is practically infeasible to invert.", + "ns0:term_status": "Stable" + }, + { + "@id": "software:SoftwarePurpose", + "@type": "owl:Class", + "rdfs:comment": "This field provides information about the primary purpose of an Element.\nSoftware Purpose is intrinsic to how the Element is being used rather than the content of the Element.\nThis field is a reasonable estimate of the most likely usage of the Element\nfrom the producer and consumer perspective from which both parties can draw conclusions\nabout the context in which the Element exists.", + "ns0:term_status": "Stable" + }, + { + "@id": "core:RelationshipType", + "@type": "owl:Class", + "rdfs:comment": "Provides information about the relationship between two Elements.\nFor example, you can represent a relationship between two different Files,\nbetween a Package and a File, between two Packages, or between one SPDXDocument and another SPDXDocument.\n\nBuild Profile specific RelationshipType descriptions can be found [here](https://github.com/spdx/spdx-3-build-profile/blob/main/model/relationships.md)", + "ns0:term_status": "Stable" + } + ] +} diff --git a/src/spdx_tools/spdx3/writer/json_ld/__init__.py b/src/spdx_tools/spdx3/writer/json_ld/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/writer/json_ld/context.json b/src/spdx_tools/spdx3/writer/json_ld/context.json new file mode 100644 index 000000000..80dd583b4 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/context.json @@ -0,0 +1,238 @@ +{ + "core": "https://spdx.org/rdf/Core/", + "software": "https://spdx.org/rdf/Software/", + "xsd": "http://www.w3.org/2001/XMLSchema/", + "Annotation": "core:Annotation", + "AnonymousPayload": "core:AnonymousPayload", + "Hash": "core:Hash", + "Organization": "core:Organization", + "Person": "core:Person", + "Relationship": "core:Relationship", + "SpdxDocument": "core:SpdxDocument", + "Tool": "core:Tool", + "File": "software:File", + "Package": "software:Package", + "Sbom": "software:Sbom", + "Snippet": "software:Snippet", + "Bom": "core:Bom", + "ElementCollection": "core:ElementCollection", + "ExternalIdentifier": "core:ExternalIdentifier", + "algorithm": { + "@id": "core:algorithm", + "@type": "@vocab", + "@context": { + "@vocab": "core:HashAlgorithm#" + } + }, + "annotationType": { + "@id": "core:annotationType", + "@type": "@vocab", + "@context": { + "@vocab": "core:AnnotationType#" + } + }, + "completeness": { + "@id": "core:completeness", + "@type": "@vocab", + "@context": { + "@vocab": "core:RelationshipCompleteness#" + } + }, + "context": { + "@id": "core:context", + "@type": "xsd:string" + }, + "created": { + "@id": "core:created", + "@type": "xsd:dateTime" + }, + "createdBy": { + "@id": "core:createdBy", + "@type": "core:Entity" + }, + "dataLicense": { + "@id": "core:dataLicense", + "@type": "xsd:string" + }, + "description": { + "@id": "core:description", + "@type": "xsd:string" + }, + "element": { + "@id": "core:element", + "@type": "core:Element" + }, + "externalId": { + "@id": "core:externalId", + "@type": "xsd:anyURI" + }, + "externalIdentifier": { + "@id": "core:externalIdentifier", + "@type": "core:ExternaIdentifier" + }, + "externalReferenceType": { + "@id": "core:externalReferenceType", + "@type": "@vocab", + "@context": { + "@vocab": "core:ExternalReferenceType#" + } + }, + "externalReference": { + "@id": "core:externalReference", + "@type": "core:ExternalReference" + }, + "from": { + "@id": "core:from", + "@type": "core:Element" + }, + "hashValue": { + "@id": "core:hashValue", + "@type": "xsd:string" + }, + "locationHint": { + "@id": "core:locationHint", + "@type": "xsd:anyURI" + }, + "locator": { + "@id": "core:locator", + "@type": "xsd:anyURI" + }, + "namespace": { + "@id": "core:namespace", + "@type": "xsd:anyURI" + }, + "originatedBy": { + "@id": "core:originatedBy", + "@type": "core:Identity" + }, + "prefix": { + "@id": "core:prefix", + "@type": "xsd:string" + }, + "profile": { + "@id": "core:profile", + "@type": "core:ProfileIdentifier" + }, + "relationshipType": { + "@id": "core:relationshipType", + "@type": "@vocab", + "@context": { + "@vocab": "core:RelationshipType#" + } + }, + "rootElement": { + "@id": "core:rootElement", + "@type": "core:Element" + }, + "spdxId": { + "@id": "core:spdxId", + "@type": "xsd:anyURI" + }, + "specVersion": { + "@id": "core:specVersion", + "@type": "core:SemVer" + }, + "statement": { + "@id": "core:statement", + "@type": "xsd:string" + }, + "subject": { + "@id": "core:subject", + "@type": "core:Element" + }, + "summary": { + "@id": "core:summary", + "@type": "xsd:string" + }, + "to": { + "@id": "core:to", + "@type": "core:Element" + }, + "byteRange": { + "@id": "software:byteRange", + "@type": "software:positiveIntegerRange" + }, + "contentType": { + "@id": "core:contentType", + "@type": "core:MediaType" + }, + "downloadLocation": { + "@id": "software:downloadLocation", + "@type": "xsd:anyURI" + }, + "filePurpose": { + "@id": "software:filePurpose", + "@type": "@vocab", + "@context": { + "@vocab": "software:SoftwarePurpose#" + } + }, + "homePage": { + "@id": "software:homePage", + "@type": "xsd:anyURI" + }, + "lineRange": { + "@id": "software:lineRange", + "@type": "software:positiveIntegerRange" + }, + "packagePurpose": { + "@id": "software:packagePurpose", + "@type": "@vocab", + "@context": { + "@vocab": "software:SoftwarePurpose#" + } + }, + "packageUrl": { + "@id": "software:packageUrl", + "@type": "xsd:anyURI" + }, + "snippetPurpose": { + "@id": "software:snippetPurpose", + "@type": "@vocab", + "@context": { + "@vocab": "software:SoftwarePurpose#" + } + }, + "Bundle": "core:Bundle", + "ExternalReference": "core:ExternalReference", + "Payload": "core:Payload", + "ProfileIdentifier": "core:ProfileIdentifier", + "SemVer": "core:SemVer", + "name": { + "@id": "core:name", + "@type": "xsd:string" + }, + "verifiedUsing": { + "@id": "core:verifiedUsing", + "@type": "core:IntegrityMethod" + }, + "Artifact": "core:Artifact", + "MediaType": "core:MediaType", + "creationInfo": { + "@id": "core:creationInfo", + "@type": "core:CreationInformation" + }, + "imports": { + "@id": "core:imports", + "@type": "core:ExternalMap" + }, + "namespaces": { + "@id": "core:namespaces", + "@type": "core:NamespaceMap" + }, + "contentIdentifier": { + "@id": "software:contentIdentifier", + "@type": "xsd:anyURI" + }, + "CreationInformation": "core:CreationInformation", + "Entity": "core:Entity", + "ExternalMap": "core:ExternalMap", + "Identity": "core:Identity", + "IntegrityMethod": "core:IntegrityMethod", + "NamespaceMap": "core:NamespaceMap", + "comment": { + "@id": "core:comment", + "@type": "xsd:string" + }, + "Element": "core:Element" +} diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py new file mode 100644 index 000000000..89c9f2a07 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py @@ -0,0 +1,77 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from datetime import datetime +from enum import Enum +from typing import Dict, Any, List + +from semantic_version import Version + +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string +from spdx_tools.spdx3.model import Element +from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.hash import Hash +from spdx_tools.spdx3.payload import Payload + + +def convert_payload_to_json_ld_list_of_elements(payload: Payload) -> List: + element_list = [] + + for element in payload.get_full_map().values(): + element_dict = _convert_to_json_ld_dict(element) + element_list.append(element_dict) + + return element_list + + +def _convert_to_json_ld_dict(element: Any, alt_creation_info=False, alt_hash=False): + if not element: + return None + + if isinstance(element, (str, int, tuple)): + return element + + if isinstance(element, Version): + return str(element) + + if isinstance(element, datetime): + return datetime_to_iso_string(element) + + if isinstance(element, Enum): + return element.name + + if isinstance(element, list): + return [_convert_to_json_ld_dict(item) for item in element if item] + + if alt_hash and isinstance(element, Hash): + hash_dict = {element.algorithm.name: element.hash_value} + if element.comment: + hash_dict["comment"] = element.comment + return hash_dict + + # if issubclass(element.__class__, Element): + # element_dict = {"@type": element.__class__.__name__} + # else: + # element_dict = {} # typing of non-Element classes should be handled by the @context, I think + + element_dict = {"@type": element.__class__.__name__} + + for attribute_name in vars(element): + attribute_value = getattr(element, attribute_name) + + if alt_creation_info and isinstance(attribute_value, CreationInformation): + for creation_info_attr_name in vars(attribute_value): + creation_info_attr_value = getattr(attribute_value, creation_info_attr_name) + element_dict[snake_case_to_camel_case(creation_info_attr_name)] = _convert_to_json_ld_dict( + creation_info_attr_value) + + elif attribute_value: + if attribute_name == "_spdx_id": + attribute_name = "@id" + else: + attribute_name = snake_case_to_camel_case(attribute_name) + + element_dict[attribute_name] = _convert_to_json_ld_dict(attribute_value) + + return element_dict diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py new file mode 100644 index 000000000..91d120e47 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import json + +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx3.writer.json_ld.json_ld_converter import convert_payload_to_json_ld_list_of_elements + + +def write_payload(payload: Payload, file_name: str): + element_list = convert_payload_to_json_ld_list_of_elements(payload) + + # this will be obsolete as soon as the context is publicly available under some URI + with open("context.json", "r") as infile: + context = json.load(infile) + + complete_dict = {"@context": context, "element": element_list} + + with open(file_name, "w") as out: + json.dump(complete_dict, out, indent=2) diff --git a/src/spdx_tools/spdx3/writer/json_ld/model.ttl b/src/spdx_tools/spdx3/writer/json_ld/model.ttl new file mode 100644 index 000000000..03358cabb --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/model.ttl @@ -0,0 +1,1654 @@ +@prefix ai: . +@prefix build: . +@prefix core: . +@prefix dataset: . +@prefix ns0: . +@prefix owl: . +@prefix rdfs: . +@prefix sh: . +@prefix software: . +@prefix xsd: . + +ai:AIPackage a owl:Class, + sh:NodeShape ; + rdfs:comment "Metadata information that can be added to a package to describe an AI application or trained AI model." ; + rdfs:subClassOf ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:name "standardsCompliance" ; + sh:path ai:standardsCompliance ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "dataPreprocessingSteps" ; + sh:path ai:dataPreprocessingSteps ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "limitations" ; + sh:path ai:limitations ], + [ sh:datatype ai:PresenceType ; + sh:maxCount 1 ; + sh:name "autonomyType" ; + sh:path ai:autonomyType ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "energyConsumption" ; + sh:path ai:energyConsumption ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "informationAboutApplication" ; + sh:path ai:informationAboutApplication ], + [ sh:datatype ; + sh:name "metrics" ; + sh:path ai:metrics ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "modelExplainabilityMechanisms" ; + sh:path ai:modelExplainabilityMechanisms ], + [ sh:datatype ai:PresenceType ; + sh:maxCount 1 ; + sh:name "sensitivePersonalInformation" ; + sh:path ai:sensitivePersonalInformation ], + [ sh:datatype xsd:string ; + sh:name "typeOfModel" ; + sh:path ai:typeOfModel ], + [ sh:datatype ; + sh:name "metricsDecisionThresholds" ; + sh:path ai:metricsDecisionThresholds ], + [ sh:datatype xsd:string ; + sh:name "domain" ; + sh:path ai:domain ], + [ sh:datatype ; + sh:name "hyperparameters" ; + sh:path ai:hyperparameters ], + [ sh:datatype ai:SafetyRiskAssessmentType ; + sh:maxCount 1 ; + sh:name "safetyRiskAssessment" ; + sh:path ai:safetyRiskAssessment ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "informationAboutTraining" ; + sh:path ai:informationAboutTraining ] . + +ai:high a owl:NamedIndividual, + ai:SafetyRiskAssessmentType . + +ai:low a owl:NamedIndividual, + ai:SafetyRiskAssessmentType . + +ai:medium a owl:NamedIndividual, + ai:SafetyRiskAssessmentType . + +ai:modelDataPreprocessingSteps a owl:DatatypeProperty ; + rdfs:comment """ModelDataPreprocessingSteps is a free form text that describes the preprocessing steps +applied to the training data before training of the model(s) contained in the AI software.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:no a owl:NamedIndividual, + ai:PresenceType . + +ai:noassertion a owl:NamedIndividual, + ai:PresenceType . + +ai:serious a owl:NamedIndividual, + ai:SafetyRiskAssessmentType . + +ai:yes a owl:NamedIndividual, + ai:PresenceType . + +build:Build a owl:Class, + sh:NodeShape ; + rdfs:comment """A build is a representation of the process in which a piece of software or artifact is built. It encapsulates information related to a build process and +provides an element from which relationships can be created to describe the build's inputs, outputs, and related entities (e.g. builders, identities, etc.). + +Definitions of "BuildType", "ConfigSource", "Parameters" and "Environment" follow +those defined in [SLSA provenance](https://slsa.dev/provenance/v0.2). + +ExternalIdentifier of type "urlScheme" may be used to identify build logs. In this case, the comment of the ExternalIdentifier should be "LogReference". + +Note that buildStart and buildEnd are optional, and may be omitted to simplify creating reproducible builds.""" ; + rdfs:subClassOf ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "buildId" ; + sh:path build:buildId ], + [ sh:datatype xsd:dateTime ; + sh:maxCount 1 ; + sh:name "buildEnd" ; + sh:path build:buildEnd ], + [ sh:datatype ; + sh:name "parameters" ; + sh:path build:parameters ], + [ sh:datatype xsd:anyURI ; + sh:name "configSourceUri" ; + sh:path build:configSourceUri ], + [ sh:datatype xsd:string ; + sh:name "configSourceEntrypoint" ; + sh:path build:configSourceEntrypoint ], + [ sh:datatype ; + sh:name "environment" ; + sh:path build:environment ], + [ sh:datatype ; + sh:name "configSourceDigest" ; + sh:path build:configSourceDigest ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "buildType" ; + sh:path build:buildType ], + [ sh:datatype xsd:dateTime ; + sh:maxCount 1 ; + sh:name "buildStart" ; + sh:path build:buildStart ] . + +core:Annotation a owl:Class, + sh:NodeShape ; + rdfs:comment "An Annotation is an assertion made in relation to one or more elements." ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:MediaType ; + sh:name "contentType" ; + sh:path core:contentType ], + [ sh:datatype core:AnnotationType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "annotationType" ; + sh:path core:annotationType ], + [ sh:datatype core:Element ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "subject" ; + sh:path core:subject ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "statement" ; + sh:path core:statement ] . + +core:AnonymousPayload a owl:Class, + sh:NodeShape ; + rdfs:comment "TODO" ; + rdfs:subClassOf core:Payload ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:ExternalMap ; + sh:name "imports" ; + sh:path core:imports ], + [ sh:datatype core:CreationInfo ; + sh:maxCount 1 ; + sh:name "creationInfo" ; + sh:path core:creationInfo ], + [ sh:datatype core:NamespaceMap ; + sh:name "namespaces" ; + sh:path core:namespaces ] . + +core:Artifact a owl:Class, + sh:NodeShape ; + rdfs:comment """An artifact is a distinct article or unit within the digital domain, +such as an electronic file, a software package, a device or an element of data.""" ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:Identity ; + sh:name "originatedBy" ; + sh:path core:originatedBy ], + [ sh:datatype xsd:dateTime ; + sh:maxCount 1 ; + sh:name "builtTime" ; + sh:path core:builtTime ], + [ sh:datatype xsd:dateTime ; + sh:maxCount 1 ; + sh:name "validUntilTime" ; + sh:path core:validUntilTime ], + [ sh:datatype xsd:dateTime ; + sh:maxCount 1 ; + sh:name "releaseTime" ; + sh:path core:releaseTime ] . + +core:Bom a owl:Class, + sh:NodeShape ; + rdfs:comment """A Bill Of Materials (BOM) is a container for a grouping of SPDX-3.0 content +characterizing details about a product. +This could include details of the content and composition of the product, +provenence details of the product and/or +its composition, licensing information, known quality or security issues, etc.""" ; + rdfs:subClassOf core:Bundle ; + ns0:term_status "Stable" . + +core:DictionaryEntry a owl:Class, + sh:NodeShape ; + rdfs:comment "The class used for implementing a generic string mapping (also known as associative array, dictionary, or hash map) in SPDX. Each DictionaryEntry contains a key-value pair which maps the key to its associated value. To implement a dictionary, this class is to be used in a collection with unique keys." ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "key" ; + sh:path core:key ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "value" ; + sh:path core:value ] . + +core:Hash a owl:Class, + sh:NodeShape ; + rdfs:comment """A hash is a grouping of characteristics unique to the result +of applying a mathematical algorithm +that maps data of arbitrary size to a bit string (the hash) +and is a one-way function, that is, +a function which is practically infeasible to invert. +This is commonly used for integrity checking of data.""" ; + rdfs:subClassOf core:IntegrityMethod ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "hashValue" ; + sh:path core:hashValue ], + [ sh:datatype core:HashAlgorithm ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "algorithm" ; + sh:path core:algorithm ] . + +core:Organization a owl:Class, + sh:NodeShape ; + rdfs:comment "An Organization is a group of people who work together in an organized way for a shared purpose." ; + rdfs:subClassOf core:Identity ; + ns0:term_status "Stable" . + +core:Person a owl:Class, + sh:NodeShape ; + rdfs:comment "A Person is an individual human being." ; + rdfs:subClassOf core:Identity ; + ns0:term_status "Stable" . + +core:PositiveIntegerRange a owl:Class, + sh:NodeShape ; + rdfs:comment """PositiveIntegerRange is a tuple of two positive integers that define a range. +"begin" must be less than or equal to "end".""" ; + rdfs:subClassOf core:none ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:positiveInteger ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "begin" ; + sh:path core:begin ], + [ sh:datatype xsd:positiveInteger ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "end" ; + sh:path core:end ] . + +core:Relationship a owl:Class, + sh:NodeShape ; + rdfs:comment """A Relationship is a grouping of characteristics unique to an assertion +that one Element is related to one or more other Elements in some way.""" ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:Element ; + sh:minCount 1 ; + sh:name "to" ; + sh:path core:to ], + [ sh:datatype core:Element ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "from" ; + sh:path core:from ], + [ sh:datatype core:RelationshipCompleteness ; + sh:maxCount 1 ; + sh:name "completeness" ; + sh:path core:completeness ], + [ sh:datatype core:RelationshipType ; + sh:maxCount 1 ; + sh:name "relationshipType" ; + sh:path core:relationshipType ] . + +core:SpdxDocument a owl:Class, + sh:NodeShape ; + rdfs:comment """An SpdxDocument assembles a collection of Elements under a common string, the name of the document. +Commonly used when representing a unit of transfer of SPDX Elements.""" ; + rdfs:subClassOf core:Bundle ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "name" ; + sh:path core:name ] . + +core:altDownloadLocation a owl:NamedIndividual, + core:ExternalReferenceType . + +core:altWebPage a owl:NamedIndividual, + core:ExternalReferenceType . + +core:amends a owl:NamedIndividual, + core:RelationshipType . + +core:ancestor a owl:NamedIndividual, + core:RelationshipType . + +core:blake2b256 a owl:NamedIndividual, + core:HashAlgorithm . + +core:blake2b384 a owl:NamedIndividual, + core:HashAlgorithm . + +core:blake2b512 a owl:NamedIndividual, + core:HashAlgorithm . + +core:blake3 a owl:NamedIndividual, + core:HashAlgorithm . + +core:buildConfigOf a owl:NamedIndividual, + core:RelationshipType . + +core:buildDependency a owl:NamedIndividual, + core:RelationshipType . + +core:buildHostOf a owl:NamedIndividual, + core:RelationshipType . + +core:buildInputOf a owl:NamedIndividual, + core:RelationshipType . + +core:buildInvokedBy a owl:NamedIndividual, + core:RelationshipType . + +core:buildOnBehalfOf a owl:NamedIndividual, + core:RelationshipType . + +core:buildOutputOf a owl:NamedIndividual, + core:RelationshipType . + +core:buildTool a owl:NamedIndividual, + core:RelationshipType . + +core:complete a owl:NamedIndividual, + core:RelationshipCompleteness . + +core:contains a owl:NamedIndividual, + core:RelationshipType . + +core:copy a owl:NamedIndividual, + core:RelationshipType . + +core:cpe22 a owl:NamedIndividual, + core:ExternalIdentifierType . + +core:cpe23 a owl:NamedIndividual, + core:ExternalIdentifierType . + +core:dataFile a owl:NamedIndividual, + core:RelationshipType . + +core:dependencyManifest a owl:NamedIndividual, + core:RelationshipType . + +core:dependsOn a owl:NamedIndividual, + core:RelationshipType . + +core:descendant a owl:NamedIndividual, + core:RelationshipType . + +core:describes a owl:NamedIndividual, + core:RelationshipType . + +core:devDependency a owl:NamedIndividual, + core:RelationshipType . + +core:devTool a owl:NamedIndividual, + core:RelationshipType . + +core:distributionArtifact a owl:NamedIndividual, + core:RelationshipType . + +core:documentation a owl:NamedIndividual, + core:RelationshipType . + +core:dynamicLink a owl:NamedIndividual, + core:RelationshipType . + +core:email a owl:NamedIndividual, + core:ExternalIdentifierType . + +core:example a owl:NamedIndividual, + core:RelationshipType . + +core:expandedFromArchive a owl:NamedIndividual, + core:RelationshipType . + +core:fileAdded a owl:NamedIndividual, + core:RelationshipType . + +core:fileDeleted a owl:NamedIndividual, + core:RelationshipType . + +core:fileModified a owl:NamedIndividual, + core:RelationshipType . + +core:generates a owl:NamedIndividual, + core:RelationshipType . + +core:gitoid a owl:NamedIndividual, + core:ExternalIdentifierType . + +core:incomplete a owl:NamedIndividual, + core:RelationshipCompleteness . + +core:md2 a owl:NamedIndividual, + core:HashAlgorithm . + +core:md4 a owl:NamedIndividual, + core:HashAlgorithm . + +core:md5 a owl:NamedIndividual, + core:HashAlgorithm . + +core:md6 a owl:NamedIndividual, + core:HashAlgorithm . + +core:metafile a owl:NamedIndividual, + core:RelationshipType . + +core:optionalComponent a owl:NamedIndividual, + core:RelationshipType . + +core:optionalDependency a owl:NamedIndividual, + core:RelationshipType . + +core:other a owl:NamedIndividual, + core:AnnotationType, + core:ExternalIdentifierType, + core:ExternalReferenceType, + core:HashAlgorithm, + core:RelationshipType . + +core:packages a owl:NamedIndividual, + core:RelationshipType . + +core:patch a owl:NamedIndividual, + core:RelationshipType . + +core:pkgUrl a owl:NamedIndividual, + core:ExternalIdentifierType . + +core:prerequisite a owl:NamedIndividual, + core:RelationshipType . + +core:providedDependency a owl:NamedIndividual, + core:RelationshipType . + +core:requirementFor a owl:NamedIndividual, + core:RelationshipType . + +core:review a owl:NamedIndividual, + core:AnnotationType . + +core:runtimeDependency a owl:NamedIndividual, + core:RelationshipType . + +core:securityAdvisory a owl:NamedIndividual, + core:ExternalReferenceType . + +core:securityFix a owl:NamedIndividual, + core:ExternalReferenceType . + +core:securityOther a owl:NamedIndividual, + core:ExternalReferenceType . + +core:sha1 a owl:NamedIndividual, + core:HashAlgorithm . + +core:sha224 a owl:NamedIndividual, + core:HashAlgorithm . + +core:sha256 a owl:NamedIndividual, + core:HashAlgorithm . + +core:sha384 a owl:NamedIndividual, + core:HashAlgorithm . + +core:sha3_224 a owl:NamedIndividual, + core:HashAlgorithm . + +core:sha3_256 a owl:NamedIndividual, + core:HashAlgorithm . + +core:sha3_384 a owl:NamedIndividual, + core:HashAlgorithm . + +core:sha3_512 a owl:NamedIndividual, + core:HashAlgorithm . + +core:sha512 a owl:NamedIndividual, + core:HashAlgorithm . + +core:spdxPvcSha1 a owl:NamedIndividual, + core:HashAlgorithm . + +core:spdxPvcSha256 a owl:NamedIndividual, + core:HashAlgorithm . + +core:specificationFor a owl:NamedIndividual, + core:RelationshipType . + +core:staticLink a owl:NamedIndividual, + core:RelationshipType . + +core:suppliedBy a owl:NamedIndividual, + core:RelationshipType . + +core:swhid a owl:NamedIndividual, + core:ExternalIdentifierType . + +core:swid a owl:NamedIndividual, + core:ExternalIdentifierType . + +core:test a owl:NamedIndividual, + core:RelationshipType . + +core:testCase a owl:NamedIndividual, + core:RelationshipType . + +core:testDependency a owl:NamedIndividual, + core:RelationshipType . + +core:testTool a owl:NamedIndividual, + core:RelationshipType . + +core:unknown a owl:NamedIndividual, + core:RelationshipCompleteness . + +core:urlScheme a owl:NamedIndividual, + core:ExternalIdentifierType . + +core:variant a owl:NamedIndividual, + core:RelationshipType . + +dataset:Dataset a owl:Class, + sh:NodeShape ; + rdfs:comment "Metadata information that can be added to a dataset that may be used in a software or to train/test an AI package." ; + rdfs:subClassOf ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:nonNegativeInteger ; + sh:maxCount 1 ; + sh:name "datasetSize" ; + sh:path dataset:datasetSize ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "datasetUpdateMechanism" ; + sh:path dataset:datasetUpdateMechanism ], + [ sh:datatype ; + sh:name "sensor" ; + sh:path dataset:sensor ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "dataPreprocessing" ; + sh:path dataset:dataPreprocessing ], + [ sh:datatype dataset:ConfidentialityLevelType ; + sh:name "confidentialityLevelType" ; + sh:path dataset:confidentialityLevelType ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "dataCollectionProcess" ; + sh:path dataset:dataCollectionProcess ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "knownBias" ; + sh:path dataset:knownBias ], + [ sh:datatype xsd:string ; + sh:name "anonymizationMethodUsed" ; + sh:path dataset:anonymizationMethodUsed ], + [ sh:datatype dataset:DatasetAvailabilityType ; + sh:maxCount 1 ; + sh:name "datasetAvailability" ; + sh:path dataset:datasetAvailability ], + [ sh:datatype dataset:PresenceType ; + sh:name "sensitivePersonalInformationType" ; + sh:path dataset:sensitivePersonalInformationType ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "datasetNoise" ; + sh:path dataset:datasetNoise ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "intendedUse" ; + sh:path dataset:intendedUse ] . + +dataset:confidentialityLevel a owl:DatatypeProperty ; + rdfs:comment "ConfidentialityLevel describes the levels of confidentiality of the data points contained in the dataset." ; + rdfs:range dataset:ConfidentialityLevelType ; + ns0:term_status "Stable" . + +dataset:sensitivePersonalInformation a owl:DatatypeProperty ; + rdfs:comment """SensitivePersonalInformation indicates the presence of sensitive personal data +or information that allows drawing conclusions about a person's identity.""" ; + rdfs:range dataset:PresenceType ; + ns0:term_status "Stable" . + +software:File a owl:Class, + sh:NodeShape ; + rdfs:comment "TODO This is about the File class." ; + rdfs:subClassOf ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "contentIdentifier" ; + sh:path software:contentIdentifier ], + [ sh:datatype software:SoftwarePurpose ; + sh:name "filePurpose" ; + sh:path software:filePurpose ], + [ sh:datatype software:MediaType ; + sh:maxCount 1 ; + sh:name "contentType" ; + sh:path software:contentType ] . + +software:Package a owl:Class, + sh:NodeShape ; + rdfs:comment """A package refers to any unit of content that can be associated with a distribution of software. +Typically, a package is composed of one or more files. +Any of the following non-limiting examples may be (but are not required to be) represented in SPDX as a package: + + - a tarball, zip file or other archive + - a directory or sub-directory + - a separately distributed piece of software which another Package or File uses or depends upon (e.g., a Python package, a Go module, ...) + - a container image, and/or each image layer within a container image + - a collection of one or more sub-packages + - a Git repository snapshot from a particular point in time + +Note that some of these could be represented in SPDX as a file as well.""" ; + rdfs:subClassOf ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "downloadLocation" ; + sh:path software:downloadLocation ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "packageUrl" ; + sh:path software:packageUrl ], + [ sh:datatype software:SoftwarePurpose ; + sh:name "packagePurpose" ; + sh:path software:packagePurpose ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "contentIdentifier" ; + sh:path software:contentIdentifier ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "homePage" ; + sh:path software:homePage ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "packageVersion" ; + sh:path software:packageVersion ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "sourceInfo" ; + sh:path software:sourceInfo ] . + +software:Sbom a owl:Class, + sh:NodeShape ; + rdfs:comment """A Software Bill of Materials (SBOM) is a collection of SPDX Elements describing a single package. +This could include details of the content and composition of the product, +provenance details of the product and/or +its composition, licensing information, known quality or security issues, etc.""" ; + rdfs:subClassOf ; + ns0:term_status "Stable" . + +software:Snippet a owl:Class, + sh:NodeShape ; + rdfs:comment """A Snippet describes a certain part of a file and can be used when the file is known to have some content +that has been included from another original source. Snippets are useful for denoting when part of a file +may have been originally created under another license or copied from a place with a known vulnerability.""" ; + rdfs:subClassOf ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype ; + sh:maxCount 1 ; + sh:name "lineRange" ; + sh:path software:lineRange ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "contentIdentifier" ; + sh:path software:contentIdentifier ], + [ sh:datatype ; + sh:maxCount 1 ; + sh:name "byteRange" ; + sh:path software:byteRange ], + [ sh:datatype software:SoftwarePurpose ; + sh:name "snippetPurpose" ; + sh:path software:snippetPurpose ] . + +software:application a owl:NamedIndividual, + software:SoftwarePurpose . + +software:archive a owl:NamedIndividual, + software:SoftwarePurpose . + +software:bom a owl:NamedIndividual, + software:SoftwarePurpose . + +software:configuration a owl:NamedIndividual, + software:SoftwarePurpose . + +software:container a owl:NamedIndividual, + software:SoftwarePurpose . + +software:data a owl:NamedIndividual, + software:SoftwarePurpose . + +software:device a owl:NamedIndividual, + software:SoftwarePurpose . + +software:documentation a owl:NamedIndividual, + software:SoftwarePurpose . + +software:executable a owl:NamedIndividual, + software:SoftwarePurpose . + +software:file a owl:NamedIndividual, + software:SoftwarePurpose . + +software:firmware a owl:NamedIndividual, + software:SoftwarePurpose . + +software:framework a owl:NamedIndividual, + software:SoftwarePurpose . + +software:install a owl:NamedIndividual, + software:SoftwarePurpose . + +software:library a owl:NamedIndividual, + software:SoftwarePurpose . + +software:module a owl:NamedIndividual, + software:SoftwarePurpose . + +software:operatingSystem a owl:NamedIndividual, + software:SoftwarePurpose . + +software:other a owl:NamedIndividual, + software:SoftwarePurpose . + +software:patch a owl:NamedIndividual, + software:SoftwarePurpose . + +software:source a owl:NamedIndividual, + software:SoftwarePurpose . + +ai:autonomyType a owl:DatatypeProperty ; + rdfs:comment """AutonomyType indicates if a human is involved in any of the decisions of the AI software +or if that software is fully automatic.""" ; + rdfs:range ai:PresenceType ; + ns0:term_status "Stable" . + +ai:domain a owl:DatatypeProperty ; + rdfs:comment """Domain describes the domain in which the AI model contained in the AI software +can be expected to operate successfully. Examples include computer vision, natural language etc.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:energyConsumption a owl:DatatypeProperty ; + rdfs:comment """EnergyConsumption captures the amount of energy needed to train and operate the AI model. +This value is also known as training energy consumption or inference energy consumption.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:hyperparameters a owl:DatatypeProperty ; + rdfs:comment """This field records important hyperparameter values. +These are parameters of the machine learning model that are used to control the learning process, +for example the optimization and learning rate used during the training of the model.""" ; + rdfs:range ; + ns0:term_status "Stable" . + +ai:informationAboutApplication a owl:DatatypeProperty ; + rdfs:comment """InformationAboutApplication describes any relevant information in free form text about +how the AI model is used inside the software, as well as any relevant pre-processing steps, third party APIs etc.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:informationAboutTraining a owl:DatatypeProperty ; + rdfs:comment """InformationAboutTraining describes the specific steps involved in the training of the AI model. +For example, it can be specified whether supervised fine-tuning +or active learning is used as part of training the model.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:limitations a owl:DatatypeProperty ; + rdfs:comment """Limitations captures limitations of the AI Package (or of the AI models present in the AI package), +expressed as free form text. Note that this is not guaranteed to be exhaustive. +For instance, a limitation might be that the AI package cannot be used on datasets from a certain demography.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:metrics a owl:DatatypeProperty ; + rdfs:comment """Metrics records the measurements with which the AI model was evaluated. +This makes statements about the prediction quality including uncertainty, +accuracy, characteristics of the tested population, quality, fairness, explainability, robustness etc.""" ; + rdfs:range ; + ns0:term_status "Stable" . + +ai:metricsDecisionThresholds a owl:DatatypeProperty ; + rdfs:comment """Each metric might be computed based on a decision threshold. +For instance, precision or recall is typically computed by checking +if the probability of the outcome is larger than 0.5. +Each decision threshold should match with the metrics field defined in the AI Package.""" ; + rdfs:range ; + ns0:term_status "Stable" . + +ai:modelExplainabilityMechanisms a owl:DatatypeProperty ; + rdfs:comment """ModelExplainabilityMechanisms is a free form text that lists the different explainability mechanisms +(such as SHAP, or other model specific explainability mechanisms) that can be used to explain the model.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:safetyRiskAssessment a owl:DatatypeProperty ; + rdfs:comment """SafetyRiskAssessment categorizes the safety risk impact of the AI software +in accordance with Article 20 of [EC Regulation No 765/2008](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).""" ; + rdfs:range ai:SafetyRiskAssessmentType ; + ns0:term_status "Stable" . + +ai:sensitivePersonalInformation a owl:DatatypeProperty ; + rdfs:comment """SensitivePersonalInformation notes if sensitive personal information +is used in the training or inference of the AI models. +This might include biometric data, addresses or other data that can be used to infer a person's identity.""" ; + rdfs:range ai:PresenceType ; + ns0:term_status "Stable" . + +ai:standardsCompliance a owl:DatatypeProperty ; + rdfs:comment """StandardsCompliance captures standards that the AI software complies with. +This could include both published and unpublished standards including ISO, IEEE, ETSI etc. +These standards could (but not necessarily have to) be used to satisfy a legal or regulatory requirement.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:typeOfModel a owl:DatatypeProperty ; + rdfs:comment """TypeOfModel records the type of the AI model(s) used in the software. +For instance, if it is a supervised model, unsupervised model, reinforcement learning model or a combination of those.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +build:buildEnd a owl:DatatypeProperty ; + rdfs:comment "buildEnd describes the time at which a build stops or finishes. This value is typically recorded by the builder." ; + rdfs:range xsd:dateTime ; + ns0:term_status "Stable" . + +build:buildId a owl:DatatypeProperty ; + rdfs:comment "A buildId is a locally unique identifier to identify a unique instance of a build. This identifier differs based on build toolchain, platform, or naming convention used by an organization or standard." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +build:buildStart a owl:DatatypeProperty ; + rdfs:comment "buildStart is the time at which a build is triggered. The builder typically records this value." ; + rdfs:range xsd:dateTime ; + ns0:term_status "Stable" . + +build:buildType a owl:DatatypeProperty ; + rdfs:comment "A buildType is a URI expressing the toolchain, platform, or infrastructure that the build was invoked on. For example, if the build was invoked on GitHub's CI platform using github actions, the buildType can be expressed as `https://github.com/actions`. In contrast, if the build was invoked on a local machine, the buildType can be expressed as `file://username@host/path/to/build`." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +build:configSourceDigest a owl:DatatypeProperty ; + rdfs:comment "configSourceDigest is the checksum of the build configuration file used by a builder to execute a build. This Property uses the Core model's [Hash](../../Core/Classes/Hash.md) class." ; + rdfs:range ; + ns0:term_status "Stable" . + +build:configSourceEntrypoint a owl:DatatypeProperty ; + rdfs:comment """A build entrypoint is the invoked executable of a build which always runs when the build is triggered. For example, when a build is triggered by running a shell script, the entrypoint is `script.sh`. In terms of a declared build, the entrypoint is the position in a configuration file or a build declaration which is always run when the build is triggered. For example, in the following configuration file, the entrypoint of the build is `publish`. + +``` +name: Publish packages to PyPI + +on: +create: +tags: "*" + +jobs: +publish: +runs-on: ubuntu-latest +if: startsWith(github.ref, 'refs/tags/') +steps: + +... +```""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +build:configSourceUri a owl:DatatypeProperty ; + rdfs:comment """If a build configuration exists for the toolchain or platform performing the build, the configSourceUri of a build is the URI of that build configuration. For example, a build triggered by a GitHub action is defined by a build configuration YAML file. In this case, the configSourceUri is the URL of that YAML file. +m""" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +build:environment a owl:DatatypeProperty ; + rdfs:comment "environment is a map of environment variables and values that are set during a build session. This is different from the [parameters](parameters.md) property in that it describes the environment variables set before a build is invoked rather than the variables provided to the builder." ; + rdfs:range ; + ns0:term_status "Stable" . + +build:parameters a owl:DatatypeProperty ; + rdfs:comment "parameters is a key-value map of all build parameters and their values that were provided to the builder for a build instance. This is different from the [environment](environment.md) property in that the keys and values are provided as command line arguments or a configuration file to the builder." ; + rdfs:range ; + ns0:term_status "Stable" . + +core:ElementCollection a owl:Class, + sh:NodeShape ; + rdfs:comment "An SpdxCollection is a collection of Elements, not necessarily with unifying context." ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:Element ; + sh:minCount 1 ; + sh:name "element" ; + sh:path core:element ], + [ sh:datatype core:Element ; + sh:minCount 1 ; + sh:name "rootElement" ; + sh:path core:rootElement ], + [ sh:datatype core:NamespaceMap ; + sh:name "namespaces" ; + sh:path core:namespaces ], + [ sh:datatype core:ExternalMap ; + sh:name "imports" ; + sh:path core:imports ] . + +core:algorithm a owl:DatatypeProperty ; + rdfs:comment "An algorithm specifies the algorithm that was used for calculating the hash value." ; + rdfs:range core:HashAlgorithm ; + ns0:term_status "Stable" . + +core:annotationType a owl:DatatypeProperty ; + rdfs:comment "An annotationType describes the type of an annotation." ; + rdfs:range core:AnnotationType ; + ns0:term_status "Stable" . + +core:begin a owl:DatatypeProperty ; + rdfs:comment "begin is a positive integer that defines the beginning of a range." ; + rdfs:range xsd:positiveInteger ; + ns0:term_status "Stable" . + +core:builtTime a owl:DatatypeProperty ; + rdfs:comment "A builtTime specifies the time an artifact was built." ; + rdfs:range xsd:dateTime ; + ns0:term_status "Stable" . + +core:completeness a owl:DatatypeProperty ; + rdfs:comment """Completeness gives information about whether the provided relationships are +complete, known to be incomplete or if no assertion is made either way.""" ; + rdfs:range core:RelationshipCompleteness ; + ns0:term_status "Stable" . + +core:context a owl:DatatypeProperty ; + rdfs:comment """A context gives information about the circumstances or unifying properties +that Elements of the bundle have been assembled under.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:created a owl:DatatypeProperty ; + rdfs:comment """Created is a date that identifies when the Element was originally created. +The time stamp can serve as an indication as to whether the analysis needs to be updated. This is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.""" ; + rdfs:range xsd:dateTime ; + ns0:term_status "Stable" . + +core:createdBy a owl:ObjectProperty ; + rdfs:comment """CreatedBy identifies who or what created the Element. +The generation method will assist the recipient of the Element in assessing +the general reliability/accuracy of the analysis information.""" ; + rdfs:range core:Entity ; + ns0:term_status "Stable" . + +core:createdUsing a owl:ObjectProperty ; + rdfs:comment """CreatedUsing identifies the tooling that was used during the creation of the Element. +The generation method will assist the recipient of the Element in assessing +the general reliability/accuracy of the analysis information.""" ; + rdfs:range core:Tool ; + ns0:term_status "Stable" . + +core:dataLicense a owl:DatatypeProperty ; + rdfs:comment """The data license provides the license under which the SPDX documentation of the Element can be used. +This is to alleviate any concern that content (the data or database) in an SPDX file +is subject to any form of intellectual property right that could restrict the re-use +of the information or the creation of another SPDX file for the same project(s). +This approach avoids intellectual property and related restrictions over the SPDX file, +however individuals can still contract with each other to restrict release +of specific collections of SPDX files (which map to software bill of materials) +and the identification of the supplier of SPDX files. +Compliance with this document includes populating the SPDX fields therein +with data related to such fields ("SPDX-Metadata"). +This document contains numerous fields where an SPDX file creator may provide +relevant explanatory text in SPDX-Metadata. Without opining on the lawfulness +of "database rights" (in jurisdictions where applicable), +such explanatory text is copyrightable subject matter in most Berne Convention countries. +By using the SPDX specification, or any portion hereof, +you hereby agree that any copyright rights (as determined by your jurisdiction) +in any SPDX-Metadata, including without limitation explanatory text, +shall be subject to the terms of the Creative Commons CC0 1.0 Universal license. +For SPDX-Metadata not containing any copyright rights, +you hereby agree and acknowledge that the SPDX-Metadata is provided to you “as-is” +and without any representations or warranties of any kind concerning the SPDX-Metadata, +express, implied, statutory or otherwise, including without limitation warranties +of title, merchantability, fitness for a particular purpose, non-infringement, +or the absence of latent or other defects, accuracy, or the presence or absence of errors, +whether or not discoverable, all to the greatest extent permissible under applicable law.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:description a owl:DatatypeProperty ; + rdfs:comment """This field is a detailed description of the Element. It may also be extracted from the Element itself. +The intent is to provide recipients of the SPDX file with a detailed technical explanation +of the functionality, anticipated use, and anticipated implementation of the Element. +This field may also include a description of improvements over prior versions of the Element.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:element a owl:ObjectProperty ; + rdfs:comment "This field refers to one or more Elements that are part of an ElementCollection." ; + rdfs:range core:Element ; + ns0:term_status "Stable" . + +core:end a owl:DatatypeProperty ; + rdfs:comment "end is a positive integer that defines the end of a range." ; + rdfs:range xsd:positiveInteger ; + ns0:term_status "Stable" . + +core:extension rdfs:comment "TODO" ; + ns0:term_status "Stable" . + +core:externalId a owl:DatatypeProperty ; + rdfs:comment "ExternalId identifies an external Element used within a Document but defined external to that Document." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:externalIdentifier a owl:ObjectProperty ; + rdfs:comment """ExternalIdentifier points to a resource outside the scope of SPDX-3.0 content +that uniquely identifies an Element.""" ; + rdfs:range core:ExternalIdentifier ; + ns0:term_status "Stable" . + +core:externalIdentifierType a owl:DatatypeProperty ; + rdfs:comment "An externalIdentifierType specifies the type of the external identifier." ; + rdfs:range core:ExternalIdentifierType ; + ns0:term_status "Stable" . + +core:externalReference a owl:ObjectProperty ; + rdfs:comment """This field points to a resource outside the scope of the SPDX-3.0 content +that provides additional characteristics of an Element.""" ; + rdfs:range core:ExternalReference ; + ns0:term_status "Stable" . + +core:externalReferenceType a owl:DatatypeProperty ; + rdfs:comment "An externalReferenceType specifies the type of the external reference." ; + rdfs:range core:ExternalReferenceType ; + ns0:term_status "Stable" . + +core:from a owl:ObjectProperty ; + rdfs:comment "This field references the Element on the left-hand side of a relationship." ; + rdfs:range core:Element ; + ns0:term_status "Stable" . + +core:hashValue a owl:DatatypeProperty ; + rdfs:comment "HashValue is the result of applying a hash algorithm to an Element." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:key a owl:DatatypeProperty ; + rdfs:comment """A key used in generic a key-value pair. +A key-value pair can be used to implement a dictionary which associates a key with a value.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:locationHint a owl:DatatypeProperty ; + rdfs:comment "A locationHint provides an indication of where to retrieve an external Element." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:locator a owl:DatatypeProperty ; + rdfs:comment "A locator provides the location of an external reference." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:namespace a owl:DatatypeProperty ; + rdfs:comment "A namespace provides an unambiguous mechanism for other documents to reference Elements within this document." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:originatedBy a owl:ObjectProperty ; + rdfs:comment "OriginatedBy identifies from where or whom the Element originally came." ; + rdfs:range core:Identity ; + ns0:term_status "Stable" . + +core:prefix a owl:DatatypeProperty ; + rdfs:comment "A prefix is a substitute for a URI." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:profile a owl:DatatypeProperty ; + rdfs:comment "This field provides information about which profiles the Element belongs to." ; + rdfs:range core:ProfileIdentifier ; + ns0:term_status "Stable" . + +core:relationshipType a owl:DatatypeProperty ; + rdfs:comment """This field provides information about the relationship between two Elements. +For example, you can represent a relationship between two different Files, +between a Package and a File, between two Packages, or between one SPDXDocument and another SPDXDocument.""" ; + rdfs:range core:RelationshipType ; + ns0:term_status "Stable" . + +core:releaseTime a owl:DatatypeProperty ; + rdfs:comment "A releaseTime specifies the time an artifact was released." ; + rdfs:range xsd:dateTime ; + ns0:term_status "Stable" . + +core:rootElement a owl:ObjectProperty ; + rdfs:comment "A rootElement of a collection is the top level Element from which all other Elements are reached via relationships." ; + rdfs:range core:Element ; + ns0:term_status "Stable" . + +core:spdxId a owl:DatatypeProperty ; + rdfs:comment """SpdxId uniquely identifies an Element which may thereby be referenced by other Elements. +These references may be internal or external. +While there may be several versions of the same Element, each one needs to be able to be referred to uniquely +so that relationships between Elements can be clearly articulated.""" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:specVersion a owl:DatatypeProperty ; + rdfs:comment """The specVersion provides a reference number that can be used to understand how to parse and interpret an Element. +It will enable both future changes to the specification and to support backward compatibility. +The major version number shall be incremented when incompatible changes between versions are made +(one or more sections are created, modified or deleted). +The minor version number shall be incremented when backwards compatible changes are made. + +Here, parties exchanging information in accordance with the SPDX specification need to provide +100% transparency as to which SPDX specification version such information is conforming to.""" ; + rdfs:range core:SemVer ; + ns0:term_status "Stable" . + +core:statement a owl:DatatypeProperty ; + rdfs:comment "A statement is a commentary on an assertion that an annotator has made." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:subject a owl:ObjectProperty ; + rdfs:comment "A subject is an Element an annotator has made an assertion about." ; + rdfs:range core:Element ; + ns0:term_status "Stable" . + +core:summary a owl:DatatypeProperty ; + rdfs:comment """A summary is a short description of an Element. Here, the intent is to allow the Element creator to +provide concise information about the function or use of the Element.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:to a owl:ObjectProperty ; + rdfs:comment "This field references an Element on the right-hand side of a relationship." ; + rdfs:range core:Element ; + ns0:term_status "Stable" . + +core:validUntilTime a owl:DatatypeProperty ; + rdfs:comment "A validUntilTime specifies until when the artifact can be used before its usage needs to be reassessed." ; + rdfs:range xsd:dateTime ; + ns0:term_status "Stable" . + +core:value a owl:DatatypeProperty ; + rdfs:comment """A value used in a generic key-value pair. +A key-value pair can be used to implement a dictionary which associates a key with a value.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:anonymizationMethodUsed a owl:DatatypeProperty ; + rdfs:comment "AnonymizationMethodUsed describes the methods used to anonymize the dataset (of fields in the dataset)." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:dataCollectionProcess a owl:DatatypeProperty ; + rdfs:comment """DataCollectionProcess describes how a dataset was collected. +Examples include the sources from which a dataset was scrapped or +the interview protocol that was used for data collection.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:dataPreprocessing a owl:DatatypeProperty ; + rdfs:comment """DataPreprocessing describes the various preprocessing steps +that were applied to the raw data to create the dataset.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:datasetAvailability a owl:DatatypeProperty ; + rdfs:comment "Some datasets are publicly available and can be downloaded directly. Others are only accessible behind a clickthrough, or after filling a registration form. This field will describe the dataset availability from that perspective." ; + rdfs:range dataset:DatasetAvailabilityType ; + ns0:term_status "Stable" . + +dataset:datasetNoise a owl:DatatypeProperty ; + rdfs:comment """DatasetNoise describes what kinds of noises a dataset might encompass. +The field uses free form text to specify the fields or the samples that might be noisy. +Alternatively, it can also be used to describe various noises that could impact the whole dataset.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:datasetSize a owl:DatatypeProperty ; + rdfs:comment """DatasetSize Captures how large a dataset is. +The size is to be measured in bytes.""" ; + rdfs:range xsd:nonNegativeInteger ; + ns0:term_status "Stable" . + +dataset:datasetUpdateMechanism a owl:DatatypeProperty ; + rdfs:comment "DatasetUpdateMechanism describes a mechanism to update the dataset." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:intendedUse a owl:DatatypeProperty ; + rdfs:comment """IntendedUse describes what the given dataset should be used for. +Some datasets are collected to be used only for particular purposes. +For example, medical data collected from a specific demography might only be applicable +for training machine learning models to make predictions for that demography. +In such a case, the intendedUse field would capture this information. +Similarly, if a dataset is collected for building a facial recognition model, +the intendedUse field would specify that.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:knownBias a owl:DatatypeProperty ; + rdfs:comment "KnownBias is a free form text field that describes the different biases that the dataset encompasses." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +dataset:sensor a owl:DatatypeProperty ; + rdfs:comment """Sensor describes a sensor that was used for collecting the data +and its calibration value as a key-value pair.""" ; + rdfs:range ; + ns0:term_status "Stable" . + +software:byteRange a owl:DatatypeProperty ; + rdfs:comment """This field defines the byte range in the original host file that the snippet information applies to. +A range of bytes is independent of various formatting concerns, and the most accurate way +of referring to the differences. The choice was made to start the numbering of +the byte range at 1 to be consistent with the W3C pointer method vocabulary.""" ; + rdfs:range software:positiveIntegerRange ; + ns0:term_status "Stable" . + +software:contentType a owl:DatatypeProperty ; + rdfs:comment """This field is a reasonable estimation of the content type of the Element, from a creator perspective. +Content type is intrinsic to the Element, independent of how the Element is being used.""" ; + rdfs:range software:mediaType ; + ns0:term_status "Stable" . + +software:downloadLocation a owl:DatatypeProperty ; + rdfs:comment """DownloadLocation identifies the download Uniform Resource Identifier +for the package at the time that the document was created. +Where and how to download the exact package being referenced +is critical for verification and tracking data.""" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +software:filePurpose a owl:DatatypeProperty ; + rdfs:comment "FilePurpose provides information about the primary purpose of the file." ; + rdfs:range software:SoftwarePurpose ; + ns0:term_status "Stable" . + +software:homePage a owl:DatatypeProperty ; + rdfs:comment """HomePage is a place for the SPDX document creator to record a website that serves as the package's home page. +This saves the recipient of the SPDX document who is looking for more info from +having to search for and verify a match between the package and the associated project home page. +This link can also be used to reference further information about the package +referenced by the SPDX document creator.""" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +software:lineRange a owl:DatatypeProperty ; + rdfs:comment """This field defines the line range in the original host file that the snippet information applies to. +If there is a disagreement between the byte range and line range, the byte range values will take precedence. +A range of lines is a convenient reference for those files where there is a known line delimiter. +The choice was made to start the numbering of the lines at 1 to be consistent with the W3C pointer method vocabulary.""" ; + rdfs:range software:positiveIntegerRange ; + ns0:term_status "Stable" . + +software:packagePurpose a owl:DatatypeProperty ; + rdfs:comment "PackagePurpose provides information about the primary purpose of the package." ; + rdfs:range software:SoftwarePurpose ; + ns0:term_status "Stable" . + +software:packageUrl a owl:DatatypeProperty ; + rdfs:comment "A packageUrl is TODO" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +software:packageVersion a owl:DatatypeProperty ; + rdfs:comment "A packageVersion is useful for identification purposes and for indicating later changes of the package version." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +software:snippetPurpose a owl:DatatypeProperty ; + rdfs:comment "SnippetPurpose provides information about the primary purpose of the snippet." ; + rdfs:range software:SoftwarePurpose ; + ns0:term_status "Stable" . + +software:sourceInfo a owl:DatatypeProperty ; + rdfs:comment """SourceInfo records any relevant background information or additional comments +about the origin of the package. For example, this field might include comments +indicating whether the package was pulled from a source code management system +or has been repackaged. The creator can provide additional information to describe +any anomalies or discoveries in the determination of the origin of the package.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:Bundle a owl:Class, + sh:NodeShape ; + rdfs:comment "A bundle is a collection of Elements that have a shared context." ; + rdfs:subClassOf core:ElementCollection ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "context" ; + sh:path core:context ] . + +core:ExternalIdentifier a owl:Class, + sh:NodeShape ; + rdfs:comment """An ExternalIdentifier is a reference to a resource outside the scope of SPDX-3.0 content +that uniquely identifies an Element.""" ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:ExternalIdentifierType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "externalIdentifierType" ; + sh:path core:externalIdentifierType ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "identifier" ; + sh:path core:identifier ] . + +core:ExternalReference a owl:Class, + sh:NodeShape ; + rdfs:comment """An External Reference points to a resource outside the scope of the SPDX-3.0 content +that provides additional characteristics of an Element.""" ; + rdfs:subClassOf core:none ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:anyURI ; + sh:name "locator" ; + sh:path core:locator ], + [ sh:datatype core:MediaType ; + sh:maxCount 1 ; + sh:name "contentType" ; + sh:path core:contentType ], + [ sh:datatype core:ExternalReferenceType ; + sh:maxCount 1 ; + sh:name "externalReferenceType" ; + sh:path core:externalReferenceType ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ] . + +core:Payload a owl:Class, + sh:NodeShape ; + rdfs:comment "TODO" ; + rdfs:subClassOf core:none ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:CreationInfo ; + sh:maxCount 1 ; + sh:name "creationInfo" ; + sh:path core:creationInfo ], + [ sh:datatype core:ExternalMap ; + sh:name "imports" ; + sh:path core:imports ], + [ sh:datatype core:NamespaceMap ; + sh:name "namespaces" ; + sh:path core:namespaces ] . + +core:ProfileIdentifier a owl:Class, + sh:NodeShape ; + rdfs:comment "A profile identifier provides the profile that the Element is specified in." ; + rdfs:subClassOf xsd:string ; + ns0:term_status "Stable" . + +core:SemVer a owl:Class, + sh:NodeShape ; + rdfs:comment "The semantic version is a String constrained to the SemVer 2.0.0 specification." ; + rdfs:subClassOf xsd:string ; + ns0:term_status "Stable" . + +core:Tool a owl:Class, + sh:NodeShape ; + rdfs:comment "A Tool is an element of hardware and/or software utilized to carry out a particular function." ; + rdfs:subClassOf core:Entity ; + ns0:term_status "Stable" . + +core:contentType a owl:DatatypeProperty ; + rdfs:comment "ContentType specifies the media type of an Element." ; + rdfs:range core:MediaType ; + ns0:term_status "Stable" . + +core:name a owl:DatatypeProperty ; + rdfs:comment """This field identifies the name of an Element as designated by the creator. +The name of an Element is an important convention and easier to refer to than the URI.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:verifiedUsing a owl:ObjectProperty ; + rdfs:comment "VerifiedUsing provides an IntegrityMethod with which the integrity of an Element can be asserted." ; + rdfs:range core:IntegrityMethod ; + ns0:term_status "Stable" . + +core:MediaType a owl:Class, + sh:NodeShape ; + rdfs:comment """The MediaType is a String constrained to the RFC 2046 specification. It provides a standardized +way of indicating the type of content of an Element. +A list of all possible media types is available at https://www.iana.org/assignments/media-types/media-types.xhtml.""" ; + rdfs:subClassOf xsd:string ; + ns0:term_status "Stable" . + +core:creationInfo a owl:DatatypeProperty ; + rdfs:comment "CreationInfo provides information about the creation of the Element." ; + rdfs:range core:CreationInfo ; + ns0:term_status "Stable" . + +core:imports a owl:DatatypeProperty ; + rdfs:comment """Imports provides an ExternalMap of Element identifiers that are used within a document +but defined external to that document.""" ; + rdfs:range core:ExternalMap ; + ns0:term_status "Stable" . + +core:namespaces a owl:DatatypeProperty ; + rdfs:comment "This field provides a NamespaceMap applicable to an ElementCollection." ; + rdfs:range core:NamespaceMap ; + ns0:term_status "Stable" . + +software:contentIdentifier a owl:DatatypeProperty ; + rdfs:comment "A contentIdentifier is TODO" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:AnnotationType a owl:Class ; + rdfs:comment "AnnotationType specifies the type of an annotation." ; + ns0:term_status "Stable" . + +core:CreationInfo a owl:Class, + sh:NodeShape ; + rdfs:comment """The CreationInfo provides information about who created the Element, and when and how it was created. + +The dateTime created is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.""" ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:ProfileIdentifier ; + sh:minCount 1 ; + sh:name "profile" ; + sh:path core:profile ], + [ sh:datatype core:Entity ; + sh:minCount 1 ; + sh:name "createdBy" ; + sh:path core:createdBy ], + [ sh:datatype core:SemVer ; + sh:name "specVersion" ; + sh:path core:specVersion ], + [ sh:datatype core:Tool ; + sh:name "createdUsing" ; + sh:path core:createdUsing ], + [ sh:datatype xsd:string ; + sh:name "dataLicense" ; + sh:path core:dataLicense ], + [ sh:datatype xsd:dateTime ; + sh:name "created" ; + sh:path core:created ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ] . + +core:Entity a owl:Class, + sh:NodeShape ; + rdfs:comment "TODO" ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" . + +core:ExternalMap a owl:Class, + sh:NodeShape ; + rdfs:comment """An External Map is a map of Element identifiers that are used within a Document +but defined external to that Document. +The external map provides details about the externally-defined Element +such as its provenance, where to retrieve it, and how to verify its integrity.""" ; + rdfs:subClassOf core:none ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "externalId" ; + sh:path core:externalId ], + [ sh:datatype core:IntegrityMethod ; + sh:name "verifiedUsing" ; + sh:path core:verifiedUsing ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "locationHint" ; + sh:path core:locationHint ] . + +core:Identity a owl:Class, + sh:NodeShape ; + rdfs:comment "An Identity is a grouping of identifying characteristics unique to an individual or organization." ; + rdfs:subClassOf core:Entity ; + ns0:term_status "Stable" . + +core:IntegrityMethod a owl:Class, + sh:NodeShape ; + rdfs:comment """An IntegrityMethod provides an independently reproducible mechanism that permits verification +of a specific Element that correlates to the data in this SPDX document. This identifier enables +a recipient to determine if anything in the original Element has been changed and eliminates +confusion over which version or modification of a specific Element is referenced.""" ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ] . + +core:NamespaceMap a owl:Class, + sh:NodeShape ; + rdfs:comment """A namespace map allows the creator of a collection of Elements to use +shorter identifiers ("prefixes") instead of URIs to provide a more +human-readable and smaller serialized representation of the Elements.""" ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "prefix" ; + sh:path core:prefix ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "namespace" ; + sh:path core:namespace ] . + +core:RelationshipCompleteness a owl:Class ; + rdfs:comment """RelationshipCompleteness indicates whether a relationship is complete or +known to be incomplete or if there is made no assertion either way.""" ; + ns0:term_status "Stable" . + +core:comment a owl:DatatypeProperty ; + rdfs:comment """A comment is an optional field for creators of the Element to provide comments +to the readers/reviewers of the document.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +ai:SafetyRiskAssessmentType a owl:Class ; + rdfs:comment """Lists the different safety risk type values that can be used to describe the safety risk of AI software +according to [Article 20 of Regulation 765/2008/EC](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).""" ; + ns0:term_status "Stable" . + +ai:PresenceType a owl:Class ; + rdfs:comment "This type is used to indicate if a given field is present or absent or unknown." ; + ns0:term_status "Stable" . + +core:ExternalReferenceType a owl:Class ; + rdfs:comment "ExteralReferenceType specifies the type of an external reference." ; + ns0:term_status "Stable" . + +core:ExternalIdentifierType a owl:Class ; + rdfs:comment "ExteralIdentifierType specifies the type of an external identifier." ; + ns0:term_status "Stable" . + +core:Element a owl:Class, + sh:NodeShape ; + rdfs:comment """An Element is a representation of a fundamental concept either directly inherent +to the Bill of Materials (BOM) domain or indirectly related to the BOM domain +and necessary for contextually characterizing BOM concepts and relationships. +Within SPDX-3.0 structure this is the base class acting as a consistent, +unifying, and interoperable foundation for all explicit +and inter-relatable content objects.""" ; + rdfs:subClassOf core:Payload ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "spdxId" ; + sh:path core:spdxId ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "summary" ; + sh:path core:summary ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "description" ; + sh:path core:description ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "name" ; + sh:path core:name ], + [ sh:datatype core:CreationInfo ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "creationInfo" ; + sh:path core:creationInfo ], + [ sh:datatype core:Extension ; + sh:name "extension" ; + sh:path core:extension ], + [ sh:datatype core:ExternalIdentifier ; + sh:name "externalIdentifier" ; + sh:path core:externalIdentifier ], + [ sh:datatype core:IntegrityMethod ; + sh:name "verifiedUsing" ; + sh:path core:verifiedUsing ], + [ sh:datatype core:ExternalReference ; + sh:name "externalReference" ; + sh:path core:externalReference ] . + +core:HashAlgorithm a owl:Class ; + rdfs:comment """A HashAlgorithm is a mathematical algorithm that maps data of arbitrary size to a bit string (the hash) +and is a one-way function, that is, a function which is practically infeasible to invert.""" ; + ns0:term_status "Stable" . + +software:SoftwarePurpose a owl:Class ; + rdfs:comment """This field provides information about the primary purpose of an Element. +Software Purpose is intrinsic to how the Element is being used rather than the content of the Element. +This field is a reasonable estimate of the most likely usage of the Element +from the producer and consumer perspective from which both parties can draw conclusions +about the context in which the Element exists.""" ; + ns0:term_status "Stable" . + +core:RelationshipType a owl:Class ; + rdfs:comment """Provides information about the relationship between two Elements. +For example, you can represent a relationship between two different Files, +between a Package and a File, between two Packages, or between one SPDXDocument and another SPDXDocument. + +Build Profile specific RelationshipType descriptions can be found [here](https://github.com/spdx/spdx-3-build-profile/blob/main/model/relationships.md)""" ; + ns0:term_status "Stable" . + diff --git a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py new file mode 100644 index 000000000..8bf122ec2 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import json + +# current workflow: markdown files + spec_parser -> model.ttl -> convert to json_ld: SPDX_OWL.json -> use the function below (needs to be fixed) to generate context.json +# TODO: Enums should look like this: +# "annotationType": { +# "@id": "core:annotationType", +# "@type": "@vocab", +# "@context": { +# "@vocab": "core:AnnotationType#" <- or "/" at the end, who knows +# } +# }, + +def convert_spdx_owl_to_jsonld_context(): + with open("SPDX_OWL.json", "r") as infile: + owl_dict = json.load(infile) + + context_dict = { + "core": "https://spdx.org/rdf/Core/", + "software": "https://spdx.org/rdf/Software/", + "xsd": "http://www.w3.org/2001/XMLSchema/", + } + + for node in owl_dict["@graph"]: + print(node) + node_type = node["@type"] + + if "owl:NamedIndividual" in node_type: + continue + elif node_type in ["owl:DatatypeProperty", "owl:ObjectProperty"]: + name = node["@id"].split(":")[-1] + context_dict[name] = {"@id": node["@id"], "@type": node["rdfs:range"]["@id"]} + + elif node_type == "owl:Class": + name = node["@id"].split(":")[-1] + context_dict[name] = node["@id"] + + elif isinstance(node_type, list): + name = node["@id"].split(":")[-1] + context_dict[name] = node["@id"] + + else: + print(f"unknown node_type: {node_type}") + + with open("src/spdx_tools/spdx3/writer/json_ld/context.json", "w") as infile: + json.dump(context_dict, infile) diff --git a/tests/spdx3/writer/__init__.py b/tests/spdx3/writer/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/writer/json_ld/__init__.py b/tests/spdx3/writer/json_ld/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/writer/json_ld/test_json_ld_writer.py b/tests/spdx3/writer/json_ld/test_json_ld_writer.py new file mode 100644 index 000000000..fcdf9864b --- /dev/null +++ b/tests/spdx3/writer/json_ld/test_json_ld_writer.py @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + +from spdx_tools.spdx.model.document import Document as Spdx2_Document +from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document +from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload + +from tests.spdx.fixtures import document_fixture + + +def test_json_writer(): + spdx2_document: Spdx2_Document = document_fixture() + # spdx2_document: Spdx2_Document = parse_file("/home/armin/PycharmProjects/tools-python/SPDXExample-v2.3.spdx.json") + payload: Payload = bump_spdx_document(spdx2_document) + + # this currently generates an actual file to look at, this should be changed to a temp file later + write_payload(payload, "SPDX3_jsonld_test.json") From cd1f04e414b08c8b1ab15d0237f3323721c0b102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 27 Apr 2023 14:33:02 +0200 Subject: [PATCH 232/354] [issue-489] try to add pyshacl validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/validation/__init__.py | 0 .../spdx3/validation/json_ld/__init__.py | 0 .../validation/json_ld/shacl_validation.py | 21 +++++++++++++++++++ tests/spdx3/validation/__init__.py | 0 tests/spdx3/validation/json_ld/__init__.py | 0 .../json_ld/test_shacl_validation.py | 12 +++++++++++ 6 files changed, 33 insertions(+) create mode 100644 src/spdx_tools/spdx3/validation/__init__.py create mode 100644 src/spdx_tools/spdx3/validation/json_ld/__init__.py create mode 100644 src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py create mode 100644 tests/spdx3/validation/__init__.py create mode 100644 tests/spdx3/validation/json_ld/__init__.py create mode 100644 tests/spdx3/validation/json_ld/test_shacl_validation.py diff --git a/src/spdx_tools/spdx3/validation/__init__.py b/src/spdx_tools/spdx3/validation/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/validation/json_ld/__init__.py b/src/spdx_tools/spdx3/validation/json_ld/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py new file mode 100644 index 000000000..7cd14ebb0 --- /dev/null +++ b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from pyshacl import validate +from rdflib import Graph + + +def validate_against_shacl_from_file(data_file: str, shacl_file: str): + data_graph = Graph() + with open(data_file) as file: + data_graph.parse(file, format="json-ld") + + shacl_graph = Graph() + with open(shacl_file) as file: + shacl_graph.parse(file, format="ttl") + + return validate_against_shacl(data_graph, shacl_graph) + + +def validate_against_shacl(data_graph: Graph, shacl_graph: Graph): + return validate(data_graph=data_graph, shacl_graph=shacl_graph) diff --git a/tests/spdx3/validation/__init__.py b/tests/spdx3/validation/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/validation/json_ld/__init__.py b/tests/spdx3/validation/json_ld/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/validation/json_ld/test_shacl_validation.py b/tests/spdx3/validation/json_ld/test_shacl_validation.py new file mode 100644 index 000000000..2546452d4 --- /dev/null +++ b/tests/spdx3/validation/json_ld/test_shacl_validation.py @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.spdx3.validation.json_ld.shacl_validation import validate_against_shacl_from_file + + +def test_shacl_validation(): + some_return = validate_against_shacl_from_file( + data_file="/home/armin/PycharmProjects/tools-python/tests/SPDX3_jsonld_test.json", + shacl_file="/home/armin/PycharmProjects/tools-python/src/spdx_tools/spdx3/writer/json_ld/model.ttl") + + print(some_return) From 5895d6015b68474d0b79420f9dd80e4d7093b96f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 9 May 2023 13:36:00 +0200 Subject: [PATCH 233/354] [issue-489] update OWL, context, and context generation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../spdx3/writer/json_ld/SPDX_OWL.json | 5162 ++++++++++++++--- .../spdx3/writer/json_ld/context.json | 549 +- src/spdx_tools/spdx3/writer/json_ld/model.ttl | 2610 +++++++-- .../spdx3/writer/json_ld/owl_to_context.py | 45 +- 4 files changed, 6963 insertions(+), 1403 deletions(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json b/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json index f88842ffe..ab59eba44 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json +++ b/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json @@ -1,51 +1,174 @@ { "@context": { - "ai": "https://spdx.org/rdf/AI#", - "build": "https://spdx.org/rdf/Build#", - "core": "https://spdx.org/rdf/Core#", - "dataset": "https://spdx.org/rdf/Dataset#", + "ai": "https://spdx.org/rdf/AI/", + "build": "https://spdx.org/rdf/Build/", + "core": "https://spdx.org/rdf/Core/", + "dataset": "https://spdx.org/rdf/Dataset/", + "licensing": "https://spdx.org/rdf/Licensing/", "ns0": "http://www.w3.org/2003/06/sw-vocab-status/ns#", "owl": "http://www.w3.org/2002/07/owl#", "rdfs": "http://www.w3.org/2000/01/rdf-schema#", - "software": "https://spdx.org/rdf/Software#", + "security": "https://spdx.org/rdf/Security/", + "sh": "http://www.w3.org/ns/shacl#", + "software": "https://spdx.org/rdf/Software/", "xsd": "http://www.w3.org/2001/XMLSchema#" }, "@graph": [ { "@id": "ai:AIPackage", - "@type": "owl:Class", - "rdfs:comment": "Metadata information that can be added to a package to describe an AI application or trained AI model.", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "Metadata information that can be added to a package to describe an AI application or trained AI model.\nExternal property restriction on /Core/Artifact/suppliedBy: minCount: 1\nExternal property restriction on /Software/Package/downloadLocation: minCount: 1\nExternal property restriction on /Software/Package/packageVersion: minCount: 1\nExternal property restriction on /Software/SoftwareArtifact/purpose: minCount: 1\nExternal property restriction on /Core/Relationship/relationshipType: minCount: 1\nExternal property restriction on /Core/Artifact/releaseTime: minCount: 1", "rdfs:subClassOf": { - "@id": "https://spdx.org/rdf/AI#/Software/Package" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "ai:autonomyType", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "AutonomyType indicates if a human is involved in any of the decisions of the AI software\nor if that software is fully automatic.", - "rdfs:range": { - "@id": "ai:PresenceType" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "ai:domain", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "Domain describes the domain in which the AI model contained in the AI software\ncan be expected to operate successfully. Examples include computer vision, natural language etc.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "ai:energyConsumption", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "EnergyConsumption captures the amount of energy needed to train and operate the AI model. \nThis value is also known as training energy consumption or inference energy consumption.", - "rdfs:range": { - "@id": "xsd:string" + "@id": "software:Package" }, - "ns0:term_status": "Stable" + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "ai:PresenceType" + }, + "sh:maxCount": 1, + "sh:name": "sensitivePersonalInformation", + "sh:path": { + "@id": "ai:sensitivePersonalInformation" + } + }, + { + "sh:datatype": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "metricDecisionThreshold", + "sh:path": { + "@id": "ai:metricDecisionThreshold" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "modelExplainability", + "sh:path": { + "@id": "ai:modelExplainability" + } + }, + { + "sh:datatype": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "metric", + "sh:path": { + "@id": "ai:metric" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "standardCompliance", + "sh:path": { + "@id": "ai:standardCompliance" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "domain", + "sh:path": { + "@id": "ai:domain" + } + }, + { + "sh:datatype": { + "@id": "ai:SafetyRiskAssessmentType" + }, + "sh:maxCount": 1, + "sh:name": "safetyRiskAssessment", + "sh:path": { + "@id": "ai:safetyRiskAssessment" + } + }, + { + "sh:datatype": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "hyperparameter", + "sh:path": { + "@id": "ai:hyperparameter" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "typeOfModel", + "sh:path": { + "@id": "ai:typeOfModel" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "energyConsumption", + "sh:path": { + "@id": "ai:energyConsumption" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "informationAboutApplication", + "sh:path": { + "@id": "ai:informationAboutApplication" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "modelDataPreprocessing", + "sh:path": { + "@id": "ai:modelDataPreprocessing" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "informationAboutTraining", + "sh:path": { + "@id": "ai:informationAboutTraining" + } + }, + { + "sh:datatype": { + "@id": "ai:PresenceType" + }, + "sh:maxCount": 1, + "sh:name": "autonomyType", + "sh:path": { + "@id": "ai:autonomyType" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "limitation", + "sh:path": { + "@id": "ai:limitation" + } + } + ] }, { "@id": "ai:high", @@ -54,42 +177,6 @@ "ai:SafetyRiskAssessmentType" ] }, - { - "@id": "ai:hyperparameters", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "This field records important hyperparameter values.\nThese are parameters of the machine learning model that are used to control the learning process,\nfor example the optimization and learning rate used during the training of the model.", - "rdfs:range": { - "@id": "https://spdx.org/rdf/AI#/Core/DictionaryEntry" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "ai:informationAboutApplication", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "InformationAboutApplication describes any relevant information in free form text about \nhow the AI model is used inside the software, as well as any relevant pre-processing steps, third party APIs etc.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "ai:informationAboutTraining", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "InformationAboutTraining describes the specific steps involved in the training of the AI model.\nFor example, it can be specified whether supervised fine-tuning \nor active learning is used as part of training the model.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "ai:limitations", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "Limitations captures limitations of the AI Package (or of the AI models present in the AI package),\nexpressed as free form text. Note that this is not guaranteed to be exhaustive.\nFor instance, a limitation might be that the AI package cannot be used on datasets from a certain demography.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, { "@id": "ai:low", "@type": [ @@ -104,42 +191,6 @@ "ai:SafetyRiskAssessmentType" ] }, - { - "@id": "ai:metrics", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "Metrics records the measurements with which the AI model was evaluated. \nThis makes statements about the prediction quality including uncertainty,\naccuracy, characteristics of the tested population, quality, fairness, explainability, robustness etc.", - "rdfs:range": { - "@id": "https://spdx.org/rdf/AI#/Core/DictionaryEntry" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "ai:metricsDecisionThresholds", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "Each metric might be computed based on a decision threshold. \nFor instance, precision or recall is typically computed by checking\nif the probability of the outcome is larger than 0.5.\nEach decision threshold should match with the metrics field defined in the AI Package.", - "rdfs:range": { - "@id": "https://spdx.org/rdf/AI#/Core/DictionaryEntry" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "ai:modelDataPreprocessingSteps", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "ModelDataPreprocessingSteps is a free form text that describes the preprocessing steps\napplied to the training data before training of the model(s) contained in the AI software.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "ai:modelExplainabilityMechanisms", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "ModelExplainabilityMechanisms is a free form text that lists the different explainability mechanisms\n(such as SHAP, or other model specific explainability mechanisms) that can be used to explain the model.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, { "@id": "ai:no", "@type": [ @@ -148,30 +199,12 @@ ] }, { - "@id": "ai:noassertion", + "@id": "ai:noAssertion", "@type": [ "owl:NamedIndividual", "ai:PresenceType" ] }, - { - "@id": "ai:safetyRiskAssessment", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "SafetyRiskAssessment categorizes the safety risk impact of the AI software\nin accordance with Article 20 of [EC Regulation No 765/2008](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).", - "rdfs:range": { - "@id": "ai:SafetyRiskAssessmentType" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "ai:sensitivePersonalInformation", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "SensitivePersonalInformation notes if sensitive personal information\nis used in the training or inference of the AI models.\nThis might include biometric data, addresses or other data that can be used to infer a person's identity.", - "rdfs:range": { - "@id": "ai:PresenceType" - }, - "ns0:term_status": "Stable" - }, { "@id": "ai:serious", "@type": [ @@ -179,24 +212,6 @@ "ai:SafetyRiskAssessmentType" ] }, - { - "@id": "ai:standardsCompliance", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "StandardsCompliance captures standards that the AI software complies with. \nThis could include both published and unpublished standards including ISO, IEEE, ETSI etc. \nThese standards could (but not necessarily have to) be used to satisfy a legal or regulatory requirement.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "ai:typeOfModel", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "TypeOfModel records the type of the AI model(s) used in the software. \nFor instance, if it is a supervised model, unsupervised model, reinforcement learning model or a combination of those.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, { "@id": "ai:yes", "@type": [ @@ -206,148 +221,207 @@ }, { "@id": "build:Build", - "@type": "owl:Class", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], "rdfs:comment": "A build is a representation of the process in which a piece of software or artifact is built. It encapsulates information related to a build process and\nprovides an element from which relationships can be created to describe the build's inputs, outputs, and related entities (e.g. builders, identities, etc.).\n\nDefinitions of \"BuildType\", \"ConfigSource\", \"Parameters\" and \"Environment\" follow\nthose defined in [SLSA provenance](https://slsa.dev/provenance/v0.2).\n\nExternalIdentifier of type \"urlScheme\" may be used to identify build logs. In this case, the comment of the ExternalIdentifier should be \"LogReference\".\n\nNote that buildStart and buildEnd are optional, and may be omitted to simplify creating reproducible builds.", "rdfs:subClassOf": { - "@id": "https://spdx.org/rdf/Build#/Core/Element" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "build:buildEnd", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "buildEnd describes the time at which a build stops or finishes. This value is typically recorded by the builder.", - "rdfs:range": { - "@id": "xsd:dateTime" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "build:buildId", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A buildId is a locally unique identifier to identify a unique instance of a build. This identifier differs based on build toolchain, platform, or naming convention used by an organization or standard.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "build:buildStart", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "buildStart is the time at which a build is triggered. The builder typically records this value.", - "rdfs:range": { - "@id": "xsd:dateTime" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "build:buildType", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A buildType is a URI expressing the toolchain, platform, or infrastructure that the build was invoked on. For example, if the build was invoked on GitHub's CI platform using github actions, the buildType can be expressed as `https://github.com/actions`. In contrast, if the build was invoked on a local machine, the buildType can be expressed as `file://username@host/path/to/build`.", - "rdfs:range": { - "@id": "xsd:anyURI" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "build:configSourceDigest", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "configSourceDigest is the checksum of the build configuration file used by a builder to execute a build. This Property uses the Core model's [Hash](../../Core/Classes/Hash.md) class.", - "rdfs:range": { - "@id": "https://spdx.org/rdf/Build#/Core/Hash" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "build:configSourceEntrypoint", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A build entrypoint is the invoked executable of a build which always runs when the build is triggered. For example, when a build is triggered by running a shell script, the entrypoint is `script.sh`. In terms of a declared build, the entrypoint is the position in a configuration file or a build declaration which is always run when the build is triggered. For example, in the following configuration file, the entrypoint of the build is `publish`.\n\n```\nname: Publish packages to PyPI\n\non:\ncreate:\ntags: \"*\"\n\njobs:\npublish:\nruns-on: ubuntu-latest\nif: startsWith(github.ref, 'refs/tags/')\nsteps:\n\n...\n```", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "build:configSourceUri", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "If a build configuration exists for the toolchain or platform performing the build, the configSourceUri of a build is the URI of that build configuration. For example, a build triggered by a GitHub action is defined by a build configuration YAML file. In this case, the configSourceUri is the URL of that YAML file. \nm", - "rdfs:range": { - "@id": "xsd:anyURI" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "build:environment", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "environment is a map of environment variables and values that are set during a build session. This is different from the [parameters](parameters.md) property in that it describes the environment variables set before a build is invoked rather than the variables provided to the builder.", - "rdfs:range": { - "@id": "https://spdx.org/rdf/Build#/Core/DictionaryEntry" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "build:parameters", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "parameters is a key-value map of all build parameters and their values that were provided to the builder for a build instance. This is different from the [environment](environment.md) property in that the keys and values are provided as command line arguments or a configuration file to the builder.", - "rdfs:range": { - "@id": "https://spdx.org/rdf/Build#/Core/DictionaryEntry" + "@id": "core:Element" }, - "ns0:term_status": "Stable" + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "buildStartTime", + "sh:path": { + "@id": "build:buildStartTime" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "buildEndTime", + "sh:path": { + "@id": "build:buildEndTime" + } + }, + { + "sh:datatype": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "parameters", + "sh:path": { + "@id": "build:parameters" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:name": "configSourceUri", + "sh:path": { + "@id": "build:configSourceUri" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "buildType", + "sh:path": { + "@id": "build:buildType" + } + }, + { + "sh:datatype": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "environment", + "sh:path": { + "@id": "build:environment" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "configSourceEntrypoint", + "sh:path": { + "@id": "build:configSourceEntrypoint" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "buildId", + "sh:path": { + "@id": "build:buildId" + } + }, + { + "sh:datatype": { + "@id": "core:Hash" + }, + "sh:name": "configSourceDigest", + "sh:path": { + "@id": "build:configSourceDigest" + } + } + ] }, { "@id": "core:Annotation", - "@type": "owl:Class", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], "rdfs:comment": "An Annotation is an assertion made in relation to one or more elements.", "rdfs:subClassOf": { "@id": "core:Element" }, - "ns0:term_status": "Stable" + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:Element" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "subject", + "sh:path": { + "@id": "core:subject" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "statement", + "sh:path": { + "@id": "core:statement" + } + }, + { + "sh:datatype": { + "@id": "core:MediaType" + }, + "sh:name": "contentType", + "sh:path": { + "@id": "core:contentType" + } + }, + { + "sh:datatype": { + "@id": "core:AnnotationType" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "annotationType", + "sh:path": { + "@id": "core:annotationType" + } + } + ] }, { "@id": "core:AnonymousPayload", - "@type": "owl:Class", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], "rdfs:comment": "TODO", "rdfs:subClassOf": { "@id": "core:Payload" }, - "ns0:term_status": "Stable" - }, - { - "@id": "core:Artifact", - "@type": "owl:Class", - "rdfs:comment": "An artifact is a distinct article or unit within the digital domain,\nsuch as an electronic file, a software package, a device or an element of data.", - "rdfs:subClassOf": { - "@id": "core:Element" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "core:Bom", - "@type": "owl:Class", - "rdfs:comment": "A Bill Of Materials (BOM) is a container for a grouping of SPDX-3.0 content\ncharacterizing details about a product.\nThis could include details of the content and composition of the product,\nprovenence details of the product and/or\nits composition, licensing information, known quality or security issues, etc.", - "rdfs:subClassOf": { - "@id": "core:Bundle" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "core:DictionaryEntry", - "@type": "owl:Class", - "rdfs:comment": "The class used for implementing a generic string mapping (also known as associative array, dictionary, or hash map) in SPDX. Each DictionaryEntry contains a key-value pair which maps the key to its associated value. To implement a dictionary, this class is to be used in a collection with unique keys.", - "ns0:term_status": "Stable" - }, - { - "@id": "core:Hash", - "@type": "owl:Class", - "rdfs:comment": "A hash is a grouping of characteristics unique to the result\nof applying a mathematical algorithm\nthat maps data of arbitrary size to a bit string (the hash)\nand is a one-way function, that is,\na function which is practically infeasible to invert.\nThis is commonly used for integrity checking of data.", - "rdfs:subClassOf": { - "@id": "core:IntegrityMethod" - }, - "ns0:term_status": "Stable" + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:ExternalMap" + }, + "sh:name": "imports", + "sh:path": { + "@id": "core:imports" + } + }, + { + "sh:datatype": { + "@id": "core:CreationInfo" + }, + "sh:maxCount": 1, + "sh:name": "creationInfo", + "sh:path": { + "@id": "core:creationInfo" + } + }, + { + "sh:datatype": { + "@id": "core:NamespaceMap" + }, + "sh:name": "namespaces", + "sh:path": { + "@id": "core:namespaces" + } + } + ] }, { "@id": "core:Organization", - "@type": "owl:Class", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], "rdfs:comment": "An Organization is a group of people who work together in an organized way for a shared purpose.", "rdfs:subClassOf": { "@id": "core:Identity" @@ -356,7 +430,10 @@ }, { "@id": "core:Person", - "@type": "owl:Class", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], "rdfs:comment": "A Person is an individual human being.", "rdfs:subClassOf": { "@id": "core:Identity" @@ -364,40 +441,41 @@ "ns0:term_status": "Stable" }, { - "@id": "core:PositiveIntegerRange", - "@type": "owl:Class", - "rdfs:comment": "PositiveIntegerRange is a tuple of two positive integers that define a range.\n\"begin\" must be less than or equal to \"end\".", + "@id": "core:SpdxDocument", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An SpdxDocument assembles a collection of Elements under a common string, the name of the document.\nCommonly used when representing a unit of transfer of SPDX Elements.\nExternal property restriction on /Core/Element/name: minCount: 1", "rdfs:subClassOf": { - "@id": "core:none" + "@id": "core:Bundle" }, - "ns0:term_status": "Stable" + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "name", + "sh:path": { + "@id": "core:name" + } + } + }, + { + "@id": "core:affects", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { - "@id": "core:Relationship", - "@type": "owl:Class", - "rdfs:comment": "A Relationship is a grouping of characteristics unique to an assertion\nthat one Element is related to one or more other Elements in some way.", - "rdfs:subClassOf": { - "@id": "core:Element" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "core:SpdxDocument", - "@type": "owl:Class", - "rdfs:comment": "An SpdxDocument assembles a collection of Elements under a common string, the name of the document.\nCommonly used when representing a unit of transfer of SPDX Elements.", - "rdfs:subClassOf": { - "@id": "core:Bundle" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "core:algorithm", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "An algorithm specifies the algorithm that was used for calculating the hash value.", - "rdfs:range": { - "@id": "core:HashAlgorithm" - }, - "ns0:term_status": "Stable" + "@id": "core:ai", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] }, { "@id": "core:altDownloadLocation", @@ -428,22 +506,18 @@ ] }, { - "@id": "core:annotationType", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "An annotationType describes the type of an annotation.", - "rdfs:range": { - "@id": "core:AnnotationType" - }, - "ns0:term_status": "Stable" + "@id": "core:availableFrom", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { - "@id": "core:begin", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "begin is a positive integer that defines the beginning of a range.", - "rdfs:range": { - "@id": "xsd:positiveInteger" - }, - "ns0:term_status": "Stable" + "@id": "core:binaryArtifact", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] }, { "@id": "core:blake2b256", @@ -473,6 +547,14 @@ "core:HashAlgorithm" ] }, + { + "@id": "core:build", + "@type": [ + "owl:NamedIndividual", + "core:LifecycleScopeType", + "core:ProfileIdentifierType" + ] + }, { "@id": "core:buildConfigOf", "@type": [ @@ -508,6 +590,13 @@ "core:RelationshipType" ] }, + { + "@id": "core:buildMeta", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, { "@id": "core:buildOnBehalfOf", "@type": [ @@ -523,29 +612,25 @@ ] }, { - "@id": "core:buildTool", + "@id": "core:buildSystem", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { - "@id": "core:builtTime", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A builtTime specifies the time an artifact was built.", - "rdfs:range": { - "@id": "xsd:dateTime" - }, - "ns0:term_status": "Stable" + "@id": "core:buildTool", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { - "@id": "core:comment", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A comment is an optional field for creators of the Element to provide comments\nto the readers/reviewers of the document.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" + "@id": "core:chat", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] }, { "@id": "core:complete", @@ -554,15 +639,6 @@ "core:RelationshipCompleteness" ] }, - { - "@id": "core:completeness", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "Completeness gives information about whether the provided relationships are\ncomplete, known to be incomplete or if no assertion is made either way.", - "rdfs:range": { - "@id": "core:RelationshipCompleteness" - }, - "ns0:term_status": "Stable" - }, { "@id": "core:contains", "@type": [ @@ -571,22 +647,11 @@ ] }, { - "@id": "core:contentType", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "ContentType specifies the media type of an Element.", - "rdfs:range": { - "@id": "core:MediaType" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "core:context", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A context gives information about the circumstances or unifying properties\nthat Elements of the bundle have been assembled under.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" + "@id": "core:coordinatedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { "@id": "core:copy", @@ -595,6 +660,13 @@ "core:RelationshipType" ] }, + { + "@id": "core:core", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, { "@id": "core:cpe22", "@type": [ @@ -610,40 +682,18 @@ ] }, { - "@id": "core:created", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "Created is a date that identifies when the Element was originally created.\nThe time stamp can serve as an indication as to whether the analysis needs to be updated. This is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.", - "rdfs:range": { - "@id": "xsd:dateTime" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "core:createdBy", - "@type": "owl:ObjectProperty", - "rdfs:comment": "CreatedBy identifies who or what created the Element.\nThe generation method will assist the recipient of the Element in assessing\nthe general reliability/accuracy of the analysis information.", - "rdfs:range": { - "@id": "core:Entity" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "core:createdUsing", - "@type": "owl:ObjectProperty", - "rdfs:comment": "CreatedUsing identifies the tooling that was used during the creation of the Element.\nThe generation method will assist the recipient of the Element in assessing\nthe general reliability/accuracy of the analysis information.", - "rdfs:range": { - "@id": "core:Tool" - }, - "ns0:term_status": "Stable" + "@id": "core:crystalsDilithium", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] }, { - "@id": "core:creationInfo", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "CreationInfo provides information about the creation of the Element.", - "rdfs:range": { - "@id": "core:CreationInfo" - }, - "ns0:term_status": "Stable" + "@id": "core:crystalsKyber", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] }, { "@id": "core:dataFile", @@ -653,13 +703,11 @@ ] }, { - "@id": "core:dataLicense", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "The data license provides the license under which the SPDX documentation of the Element can be used.\nThis is to alleviate any concern that content (the data or database) in an SPDX file\nis subject to any form of intellectual property right that could restrict the re-use\nof the information or the creation of another SPDX file for the same project(s).\nThis approach avoids intellectual property and related restrictions over the SPDX file,\nhowever individuals can still contract with each other to restrict release\nof specific collections of SPDX files (which map to software bill of materials)\nand the identification of the supplier of SPDX files.\nCompliance with this document includes populating the SPDX fields therein\nwith data related to such fields (\"SPDX-Metadata\"). \nThis document contains numerous fields where an SPDX file creator may provide\nrelevant explanatory text in SPDX-Metadata. Without opining on the lawfulness\nof \"database rights\" (in jurisdictions where applicable),\nsuch explanatory text is copyrightable subject matter in most Berne Convention countries.\nBy using the SPDX specification, or any portion hereof,\nyou hereby agree that any copyright rights (as determined by your jurisdiction)\nin any SPDX-Metadata, including without limitation explanatory text,\nshall be subject to the terms of the Creative Commons CC0 1.0 Universal license. \nFor SPDX-Metadata not containing any copyright rights, \nyou hereby agree and acknowledge that the SPDX-Metadata is provided to you “as-is”\nand without any representations or warranties of any kind concerning the SPDX-Metadata,\nexpress, implied, statutory or otherwise, including without limitation warranties\nof title, merchantability, fitness for a particular purpose, non-infringement,\nor the absence of latent or other defects, accuracy, or the presence or absence of errors,\nwhether or not discoverable, all to the greatest extent permissible under applicable law.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" + "@id": "core:dataset", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] }, { "@id": "core:dependencyManifest", @@ -690,13 +738,11 @@ ] }, { - "@id": "core:description", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "This field is a detailed description of the Element. It may also be extracted from the Element itself.\nThe intent is to provide recipients of the SPDX file with a detailed technical explanation\nof the functionality, anticipated use, and anticipated implementation of the Element.\nThis field may also include a description of improvements over prior versions of the Element.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" + "@id": "core:design", + "@type": [ + "owl:NamedIndividual", + "core:LifecycleScopeType" + ] }, { "@id": "core:devDependency", @@ -712,6 +758,13 @@ "core:RelationshipType" ] }, + { + "@id": "core:development", + "@type": [ + "owl:NamedIndividual", + "core:LifecycleScopeType" + ] + }, { "@id": "core:distributionArtifact", "@type": [ @@ -723,24 +776,23 @@ "@id": "core:documentation", "@type": [ "owl:NamedIndividual", + "core:ExternalReferenceType", "core:RelationshipType" ] }, { - "@id": "core:dynamicLink", + "@id": "core:doesNotAffect", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:element", - "@type": "owl:ObjectProperty", - "rdfs:comment": "This field refers to one or more Elements that are part of an ElementCollection.", - "rdfs:range": { - "@id": "core:Element" - }, - "ns0:term_status": "Stable" + "@id": "core:dynamicLink", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { "@id": "core:email", @@ -749,15 +801,6 @@ "core:ExternalIdentifierType" ] }, - { - "@id": "core:end", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "end is a positive integer that defines the end of a range.", - "rdfs:range": { - "@id": "xsd:positiveInteger" - }, - "ns0:term_status": "Stable" - }, { "@id": "core:example", "@type": [ @@ -773,84 +816,67 @@ ] }, { - "@id": "core:extension", - "rdfs:comment": "TODO", - "ns0:term_status": "Stable" - }, - { - "@id": "core:externalId", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "ExternalId identifies an external Element used within a Document but defined external to that Document.", - "rdfs:range": { - "@id": "xsd:anyURI" - }, - "ns0:term_status": "Stable" + "@id": "core:exploitCreatedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { - "@id": "core:externalIdentifier", - "@type": "owl:ObjectProperty", - "rdfs:comment": "ExternalIdentifier points to a resource outside the scope of SPDX-3.0 content\nthat uniquely identifies an Element.", - "rdfs:range": { - "@id": "core:ExternalIdentifier" - }, - "ns0:term_status": "Stable" + "@id": "core:falcon", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] }, { - "@id": "core:externalIdentifierType", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "An externalIdentifierType specifies the type of the external identifier.", - "rdfs:range": { - "@id": "core:ExternalIdentifierType" - }, - "ns0:term_status": "Stable" + "@id": "core:fileAdded", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { - "@id": "core:externalReference", - "@type": "owl:ObjectProperty", - "rdfs:comment": "This field points to a resource outside the scope of the SPDX-3.0 content\nthat provides additional characteristics of an Element.", - "rdfs:range": { - "@id": "core:ExternalReference" - }, - "ns0:term_status": "Stable" + "@id": "core:fileDeleted", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { - "@id": "core:externalReferenceType", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "An externalReferenceType specifies the type of the external reference.", - "rdfs:range": { - "@id": "core:ExternalReferenceType" - }, - "ns0:term_status": "Stable" + "@id": "core:fileModified", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { - "@id": "core:fileAdded", + "@id": "core:fixedBy", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:fileDeleted", + "@id": "core:fixedIn", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:fileModified", + "@id": "core:foundBy", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:from", - "@type": "owl:ObjectProperty", - "rdfs:comment": "This field references the Element on the left-hand side of a relationship.", - "rdfs:range": { - "@id": "core:Element" - }, - "ns0:term_status": "Stable" + "@id": "core:funding", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] }, { "@id": "core:generates", @@ -867,22 +893,46 @@ ] }, { - "@id": "core:hashValue", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "HashValue is the result of applying a hash algorithm to an Element.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" + "@id": "core:hasAssociatedVulnerability", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { - "@id": "core:imports", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "Imports provides an ExternalMap of Element identifiers that are used within a document\nbut defined external to that document.", - "rdfs:range": { - "@id": "core:ExternalMap" - }, - "ns0:term_status": "Stable" + "@id": "core:hasCvssV2AssessmentFor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:hasCvssV3AssessmentFor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:hasEpssAssessmentFor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:hasExploitCatalogAssessmentFor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:hasSsvcAssessmentFor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { "@id": "core:incomplete", @@ -892,31 +942,32 @@ ] }, { - "@id": "core:key", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A key used in generic a key-value pair.\nA key-value pair can be used to implement a dictionary which associates a key with a value.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" + "@id": "core:issueTracker", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] }, { - "@id": "core:locationHint", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A locationHint provides an indication of where to retrieve an external Element.", - "rdfs:range": { - "@id": "xsd:anyURI" - }, - "ns0:term_status": "Stable" + "@id": "core:license", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] }, { - "@id": "core:locator", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A locator provides the location of an external reference.", - "rdfs:range": { - "@id": "xsd:anyURI" - }, - "ns0:term_status": "Stable" + "@id": "core:licensing", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, + { + "@id": "core:mailingList", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] }, { "@id": "core:md2", @@ -954,31 +1005,18 @@ ] }, { - "@id": "core:name", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "This field identifies the name of an Element as designated by the creator. \nThe name of an Element is an important convention and easier to refer to than the URI.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "core:namespace", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A namespace provides an unambiguous mechanism for other documents to reference Elements within this document.", - "rdfs:range": { - "@id": "xsd:anyURI" - }, - "ns0:term_status": "Stable" + "@id": "core:metrics", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] }, { - "@id": "core:namespaces", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "This field provides a NamespaceMap applicable to an ElementCollection.", - "rdfs:range": { - "@id": "core:NamespaceMap" - }, - "ns0:term_status": "Stable" + "@id": "core:noAssertion", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipCompleteness" + ] }, { "@id": "core:optionalComponent", @@ -994,15 +1032,6 @@ "core:RelationshipType" ] }, - { - "@id": "core:originatedBy", - "@type": "owl:ObjectProperty", - "rdfs:comment": "OriginatedBy identifies from where or whom the Element originally came.", - "rdfs:range": { - "@id": "core:Identity" - }, - "ns0:term_status": "Stable" - }, { "@id": "core:other", "@type": [ @@ -1011,6 +1040,7 @@ "core:ExternalIdentifierType", "core:ExternalReferenceType", "core:HashAlgorithm", + "core:LifecycleScopeType", "core:RelationshipType" ] }, @@ -1035,15 +1065,6 @@ "core:ExternalIdentifierType" ] }, - { - "@id": "core:prefix", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A prefix is a substitute for a URI.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, { "@id": "core:prerequisite", "@type": [ @@ -1052,38 +1073,46 @@ ] }, { - "@id": "core:profile", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "This field provides information about which profiles the Element belongs to.", - "rdfs:range": { - "@id": "core:ProfileIdentifier" - }, - "ns0:term_status": "Stable" + "@id": "core:providedDependency", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { - "@id": "core:providedDependency", + "@id": "core:publishedBy", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:relationshipType", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "This field provides information about the relationship between two Elements.\nFor example, you can represent a relationship between two different Files,\nbetween a Package and a File, between two Packages, or between one SPDXDocument and another SPDXDocument.", - "rdfs:range": { - "@id": "core:RelationshipType" - }, - "ns0:term_status": "Stable" + "@id": "core:releaseHistory", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] }, { - "@id": "core:releaseTime", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A releaseTime specifies the time an artifact was released.", - "rdfs:range": { - "@id": "xsd:dateTime" - }, - "ns0:term_status": "Stable" + "@id": "core:releaseNotes", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "core:reportedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:republishedBy", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] }, { "@id": "core:requirementFor", @@ -1100,13 +1129,11 @@ ] }, { - "@id": "core:rootElement", - "@type": "owl:ObjectProperty", - "rdfs:comment": "A rootElement of a collection is the top level Element from which all other Elements are reached via relationships.", - "rdfs:range": { - "@id": "core:Element" - }, - "ns0:term_status": "Stable" + "@id": "core:runtime", + "@type": [ + "owl:NamedIndividual", + "core:LifecycleScopeType" + ] }, { "@id": "core:runtimeDependency", @@ -1115,6 +1142,13 @@ "core:RelationshipType" ] }, + { + "@id": "core:security", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, { "@id": "core:securityAdvisory", "@type": [ @@ -1200,13 +1234,25 @@ ] }, { - "@id": "core:spdxId", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "SpdxId uniquely identifies an Element which may thereby be referenced by other Elements.\nThese references may be internal or external.\nWhile there may be several versions of the same Element, each one needs to be able to be referred to uniquely\nso that relationships between Elements can be clearly articulated.", - "rdfs:range": { - "@id": "xsd:anyURI" - }, - "ns0:term_status": "Stable" + "@id": "core:socialMedia", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "core:software", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, + { + "@id": "core:sourceArtifact", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] }, { "@id": "core:spdxPvcSha1", @@ -1222,15 +1268,6 @@ "core:HashAlgorithm" ] }, - { - "@id": "core:specVersion", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "The specVersion provides a reference number that can be used to understand how to parse and interpret an Element.\nIt will enable both future changes to the specification and to support backward compatibility.\nThe major version number shall be incremented when incompatible changes between versions are made\n(one or more sections are created, modified or deleted).\nThe minor version number shall be incremented when backwards compatible changes are made.\n\nHere, parties exchanging information in accordance with the SPDX specification need to provide \n100% transparency as to which SPDX specification version such information is conforming to.", - "rdfs:range": { - "@id": "core:SemVer" - }, - "ns0:term_status": "Stable" - }, { "@id": "core:specificationFor", "@type": [ @@ -1239,13 +1276,11 @@ ] }, { - "@id": "core:statement", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A statement is a commentary on an assertion that an annotator has made.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" + "@id": "core:sphincsPlus", + "@type": [ + "owl:NamedIndividual", + "core:HashAlgorithm" + ] }, { "@id": "core:staticLink", @@ -1255,28 +1290,10 @@ ] }, { - "@id": "core:subject", - "@type": "owl:ObjectProperty", - "rdfs:comment": "A subject is an Element an annotator has made an assertion about.", - "rdfs:range": { - "@id": "core:Element" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "core:summary", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A summary is a short description of an Element. Here, the intent is to allow the Element creator to \nprovide concise information about the function or use of the Element.", - "rdfs:range": { - "@id": "xsd:string" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "core:suppliedBy", + "@id": "core:support", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { @@ -1297,6 +1314,7 @@ "@id": "core:test", "@type": [ "owl:NamedIndividual", + "core:LifecycleScopeType", "core:RelationshipType" ] }, @@ -1322,498 +1340,3477 @@ ] }, { - "@id": "core:to", + "@id": "core:underInvestigationFor", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:urlScheme", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "core:usage", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ] + }, + { + "@id": "core:variant", + "@type": [ + "owl:NamedIndividual", + "core:RelationshipType" + ] + }, + { + "@id": "core:vcs", + "@type": [ + "owl:NamedIndividual", + "core:ExternalReferenceType" + ] + }, + { + "@id": "dataset:Amber", + "@type": [ + "owl:NamedIndividual", + "dataset:ConfidentialityLevelType" + ] + }, + { + "@id": "dataset:Clear", + "@type": [ + "owl:NamedIndividual", + "dataset:ConfidentialityLevelType" + ] + }, + { + "@id": "dataset:Clickthrough", + "@type": [ + "owl:NamedIndividual", + "dataset:DatasetAvailabilityType" + ] + }, + { + "@id": "dataset:Dataset", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "Metadata information that can be added to a dataset that may be used in a software or to train/test an AI package.\nExternal property restriction on /Core/Artifact/originatedBy: minCount: 1\nExternal property restriction on /Software/Package/downloadLocation: minCount: 1\nExternal property restriction on /Software/SoftwareArtifact/purpose: minCount: 1\nExternal property restriction on /Core/Artifact/releaseTime: minCount: 1\nExternal property restriction on /Core/Artifact/builtTime: minCount: 1", + "rdfs:subClassOf": { + "@id": "software:Package" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "dataPreprocessing", + "sh:path": { + "@id": "dataset:dataPreprocessing" + } + }, + { + "sh:datatype": { + "@id": "xsd:nonNegativeInteger" + }, + "sh:maxCount": 1, + "sh:name": "datasetSize", + "sh:path": { + "@id": "dataset:datasetSize" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "dataCollectionProcess", + "sh:path": { + "@id": "dataset:dataCollectionProcess" + } + }, + { + "sh:datatype": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "sensor", + "sh:path": { + "@id": "dataset:sensor" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "knownBias", + "sh:path": { + "@id": "dataset:knownBias" + } + }, + { + "sh:datatype": { + "@id": "dataset:PresenceType" + }, + "sh:maxCount": 1, + "sh:name": "sensitivePersonalInformation", + "sh:path": { + "@id": "dataset:sensitivePersonalInformation" + } + }, + { + "sh:datatype": { + "@id": "dataset:ConfidentialityLevelType" + }, + "sh:maxCount": 1, + "sh:name": "confidentialityLevel", + "sh:path": { + "@id": "dataset:confidentialityLevel" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "intendedUse", + "sh:path": { + "@id": "dataset:intendedUse" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "datasetUpdateMechanism", + "sh:path": { + "@id": "dataset:datasetUpdateMechanism" + } + }, + { + "sh:datatype": { + "@id": "dataset:DatasetAvailabilityType" + }, + "sh:maxCount": 1, + "sh:name": "datasetAvailability", + "sh:path": { + "@id": "dataset:datasetAvailability" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "anonymizationMethodUsed", + "sh:path": { + "@id": "dataset:anonymizationMethodUsed" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "datasetType", + "sh:path": { + "@id": "dataset:datasetType" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "datasetNoise", + "sh:path": { + "@id": "dataset:datasetNoise" + } + } + ] + }, + { + "@id": "dataset:Direct-Download", + "@type": [ + "owl:NamedIndividual", + "dataset:DatasetAvailabilityType" + ] + }, + { + "@id": "dataset:Green", + "@type": [ + "owl:NamedIndividual", + "dataset:ConfidentialityLevelType" + ] + }, + { + "@id": "dataset:Query", + "@type": [ + "owl:NamedIndividual", + "dataset:DatasetAvailabilityType" + ] + }, + { + "@id": "dataset:Red", + "@type": [ + "owl:NamedIndividual", + "dataset:ConfidentialityLevelType" + ] + }, + { + "@id": "dataset:Registration", + "@type": [ + "owl:NamedIndividual", + "dataset:DatasetAvailabilityType" + ] + }, + { + "@id": "dataset:Scraping-Script", + "@type": [ + "owl:NamedIndividual", + "dataset:DatasetAvailabilityType" + ] + }, + { + "@id": "licensing:ConjunctiveLicenseSet", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A ConjunctiveLicenseSet indicates that _each_ of its subsidiary\nAnyLicenseInfos apply. In other words, a ConjunctiveLicenseSet of two or\nmore licenses represents a licensing situation where _all_ of the specified\nlicenses are to be complied with. It is represented in the SPDX License\nExpression Syntax by the `AND` operator.\n\nIt is syntactically correct to specify a ConjunctiveLicenseSet where the\nsubsidiary AnyLicenseInfos may be \"incompatible\" according to a particular\ninterpretation of the corresponding Licenses. The SPDX License Expression\nSyntax does not take into account interpretation of license texts, which is\nleft to the consumer of SPDX data to determine for themselves.", + "rdfs:subClassOf": { + "@id": "licensing:AnyLicenseInfo" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "licensing:AnyLicenseInfo" + }, + "sh:minCount": 2, + "sh:name": "member", + "sh:path": { + "@id": "licensing:member" + } + } + }, + { + "@id": "licensing:CustomLicense", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A CustomLicense represents a License that is not listed on the SPDX License\nList at https://spdx.org/licenses, and is therefore defined by an SPDX data\ncreator.", + "rdfs:subClassOf": { + "@id": "licensing:License" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:CustomLicenseAddition", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A CustomLicenseAddition represents an addition to a License that is not listed\non the SPDX Exceptions List at https://spdx.org/licenses/exceptions-index.html,\nand is therefore defined by an SPDX data creator.\n\nIt is intended to represent additional language which is meant to be added to\na License, but which is not itself a standalone License.", + "rdfs:subClassOf": { + "@id": "licensing:LicenseAddition" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:DisjunctiveLicenseSet", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A DisjunctiveLicenseSet indicates that _only one_ of its subsidiary\nAnyLicenseInfos is required to apply. In other words, a\nDisjunctiveLicenseSet of two or more licenses represents a licensing\nsituation where _only one_ of the specified licenses are to be complied with.\nA consumer of SPDX data would typically understand this to permit the recipient\nof the licensed content to choose which of the corresponding license they\nwould prefer to use. It is represented in the SPDX License Expression Syntax\nby the `OR` operator.", + "rdfs:subClassOf": { + "@id": "licensing:AnyLicenseInfo" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "licensing:AnyLicenseInfo" + }, + "sh:minCount": 2, + "sh:name": "member", + "sh:path": { + "@id": "licensing:member" + } + } + }, + { + "@id": "licensing:ListedLicense", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A ListedLicense represents a License that is listed on the SPDX License List\nat https://spdx.org/licenses.", + "rdfs:subClassOf": { + "@id": "licensing:License" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "deprecatedVersion", + "sh:path": { + "@id": "licensing:deprecatedVersion" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "listVersionAdded", + "sh:path": { + "@id": "licensing:listVersionAdded" + } + } + ] + }, + { + "@id": "licensing:ListedLicenseException", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A ListedLicenseException represents an exception to a License (in other words,\nan exception to a license condition or an additional permission beyond those\ngranted in a License) which is listed on the SPDX Exceptions List at\nhttps://spdx.org/licenses/exceptions-index.html.", + "rdfs:subClassOf": { + "@id": "licensing:LicenseAddition" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "listVersionAdded", + "sh:path": { + "@id": "licensing:listVersionAdded" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "deprecatedVersion", + "sh:path": { + "@id": "licensing:deprecatedVersion" + } + } + ] + }, + { + "@id": "licensing:NoAssertionLicense", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A NoAssertionLicense is the primary value that is used by a concludedLicense\nor declaredLicense field that indicates that the SPDX data creator is making\nno assertion about the license information for the corresponding software\nPackage, File or Snippet.\n\nThe specific meaning of NoAssertionLicense in the context of a\nconcludedLicense or declaredLicense field is more fully set forth in the\nProperty definitions for those fields.", + "rdfs:subClassOf": { + "@id": "licensing:LicenseField" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:NoneLicense", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A NoneLicense is the primary value that is used by a concludedLicense or\ndeclaredLicense field that indicates the absence of license information from\nthe corresponding software Package, File or Snippet.\n\nThe specific meaning of NoneLicense in the context of a concludedLicense or\ndeclaredLicense field is more fully set forth in the Property definitions for\nthose fields.", + "rdfs:subClassOf": { + "@id": "licensing:LicenseField" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:OrLaterOperator", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An OrLaterOperator indicates that this portion of the AnyLicenseInfo\nrepresents either (1) the specified version of the corresponding License, or\n(2) any later version of that License. It is represented in the SPDX License\nExpression Syntax by the `+` operator.\n\nIt is context-dependent, and unspecified by SPDX, as to what constitutes a\n\"later version\" of any particular License. Some Licenses may not be versioned,\nor may not have clearly-defined ordering for versions. The consumer of SPDX\ndata will need to determine for themselves what meaning to attribute to a\n\"later version\" operator for a particular License.", + "rdfs:subClassOf": { + "@id": "licensing:AnyLicenseInfo" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "licensing:License" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "subjectLicense", + "sh:path": { + "@id": "licensing:subjectLicense" + } + } + }, + { + "@id": "licensing:WithAdditionOperator", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A WithAdditionOperator indicates that the designated License is subject to the\ndesignated LicenseAddition, which might be a license exception on the SPDX\nExceptions List (ListedLicenseException) or may be other additional text\n(CustomLicenseAddition). It is represented in the SPDX License Expression\nSyntax by the `WITH` operator.", + "rdfs:subClassOf": { + "@id": "licensing:AnyLicenseInfo" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "licensing:License" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "subjectLicense", + "sh:path": { + "@id": "licensing:subjectLicense" + } + }, + { + "sh:datatype": { + "@id": "licensing:LicenseAddition" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "subjectAddition", + "sh:path": { + "@id": "licensing:subjectAddition" + } + } + ] + }, + { + "@id": "security:CvssV2VulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A CvssV2VulnAssessmentRelationship relationship describes the determined score and vector of a vulnerability using version 2.0 of the Common Vulnerability Scoring System\n(CVSS) as defined on [https://www.first.org/cvss/v2/guide](https://www.first.org/cvss/v2/guide). It is intented to communicate the results of using a CVSS calculator.\n\n**Constraints**\n\nThe value of severity must be one of 'low', 'medium' or 'high'\n\n**Syntax**\n\n```json\n{\n \"@type\": \"CvssV2VulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:cvssv2-cve-2020-28498\",\n \"relationshipType\": \"hasCvssV2AssessmentFor\",\n \"score\": 4.3,\n \"vector\": \"(AV:N/AC:M/Au:N/C:P/I:N/A:N)\",\n \"severity\": \"low\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"externalReferences\": [\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://nvd.nist.gov/vuln/detail/CVE-2020-28498\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityFix\",\n \"locator\": \"https://github.com/indutny/elliptic/commit/441b742\"\n }\n ],\n \"suppliedBy\": [\"urn:spdx.dev:agent-my-security-vendor\"],\n \"publishedTime\": \"2023-05-06T10:06:13Z\"\n},\n{\n \"@type\": \"Relationship\",\n \"@id\": \"urn:spdx.dev:vulnAgentRel-1\", \n \"relationshipType\": \"publishedBy\", \n \"from\": \"urn:spdx.dev:cvssv2-cve-2020-28498\",\n \"to\": [\"urn:spdx.dev:agent-snyk\"],\n \"startTime\": \"2021-03-08T16:06:50Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "vector", + "sh:path": { + "@id": "security:vector" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "severity", + "sh:path": { + "@id": "security:severity" + } + }, + { + "sh:datatype": { + "@id": "xsd:decimal" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "score", + "sh:path": { + "@id": "security:score" + } + } + ] + }, + { + "@id": "security:CvssV3VulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A CvssV3VulnAssessmentRelationship relationship describes the determined score,\nseverity, and vector of a vulnerability using version 3.1 of the Common\nVulnerability Scoring System (CVSS) as defined on \n[https://www.first.org/cvss/v3.1/specification-document](https://www.first.org/cvss/v3.1/specification-document). It is intented to communicate the results of using a CVSS calculator.\n\n**Constraints**\n\nThe value of severity must be one of 'none', 'low', 'medium', 'high' or 'critical'.\nAbsence of the property shall be interpreted as 'none'.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"CvssV3VulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:cvssv3-cve-2020-28498\",\n \"relationshipType\": \"hasCvssV3AssessmentFor\",\n \"severity\": \"medium\",\n \"score\": 6.8,\n \"vector\": \"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"externalReferences\": [\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://nvd.nist.gov/vuln/detail/CVE-2020-28498\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityFix\",\n \"locator\": \"https://github.com/indutny/elliptic/commit/441b742\"\n }\n ],\n \"suppliedBy\": [\"urn:spdx.dev:agent-my-security-vendor\"],\n \"publishedTime\": \"2023-05-06T10:06:13Z\"\n},\n{\n \"@type\": \"Relationship\",\n \"@id\": \"urn:spdx.dev:vulnAgentRel-1\",\n \"relationshipType\": \"publishedBy\",\n \"from\": \"urn:spdx.dev:cvssv3-cve-2020-28498\",\n \"to\": \"urn:spdx.dev:agent-snyk\",\n \"startTime\": \"2021-03-08T16:06:50Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:decimal" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "score", + "sh:path": { + "@id": "security:score" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "vector", + "sh:path": { + "@id": "security:vector" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "severity", + "sh:path": { + "@id": "security:severity" + } + } + ] + }, + { + "@id": "security:EpssVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An EpssVulnAssessmentRelationship relationship describes the likelihood or\nprobability that a vulnerability will be exploited in the wild using the Exploit\nPrediction Scoring System (EPSS) as defined on \n[https://www.first.org/epss/model](https://www.first.org/epss/model).\n\n**Syntax**\n\n```json\n{\n \"@type\": \"EpssVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:epss-1\",\n \"relationshipType\": \"hasEpssAssessmentFor\",\n \"probability\": 80,\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "severity", + "sh:path": { + "@id": "security:severity" + } + }, + { + "sh:datatype": { + "@id": "xsd:nonNegativeInteger" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "probability", + "sh:path": { + "@id": "security:probability" + } + } + ] + }, + { + "@id": "security:ExploitCatalogVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An ExploitCatalogVulnAssessmentRelationship describes if a vulnerability is\nlisted in any exploit catalog such as the CISA Known Exploited Vulnerabilities\nCatalog (KEV) \n[https://www.cisa.gov/known-exploited-vulnerabilities-catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog).\n\n**Syntax**\n\n```json\n{\n \"@type\": \"ExploitCatalogVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:exploit-catalog-1\",\n \"relationshipType\": \"hasExploitCatalogAssessmentFor\",\n \"catalogType\": \"kev\",\n \"locator\": \"https://www.cisa.gov/known-exploited-vulnerabilities-catalog\",\n \"exploited\": \"true\",\n \"from\": \"urn:spdx.dev:vuln-cve-2023-2136\",\n \"to\": [\"urn:product-google-chrome-112.0.5615.136\"],\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "security:ExploitCatalogType" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "catalogType", + "sh:path": { + "@id": "security:catalogType" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "locator", + "sh:path": { + "@id": "security:locator" + } + }, + { + "sh:datatype": { + "@id": "xsd:boolean" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "exploited", + "sh:path": { + "@id": "security:exploited" + } + } + ] + }, + { + "@id": "security:SsvcVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An SsvcVulnAssessmentRelationship describes the decision made using the\nStakeholder-Specific Vulnerability Categorization (SSVC) decision tree as\ndefined on [https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc](https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc).\nIt is intended to communicate the results of using the CISA SSVC Calculator.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"SsvcVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:ssvc-1\",\n \"relationshipType\": \"hasSsvcAssessmentFor\",\n \"decisionType\": \"act\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "security:SsvcDecisionType" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "decisionType", + "sh:path": { + "@id": "security:decisionType" + } + } + }, + { + "@id": "security:VexAffectedVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "VexAffectedVulnAssessmentRelationship connects a vulnerability and a number\nof elements. The relationship marks these elements as products affected by the\nvulnerability. This relationship corresponds to the VEX affected status.\n\n**Constraints**\n\nWhen linking elements using a VexAffectedVulnAssessmentRelationship, the\nfollowing requirements must be observed:\n\n- Elements linked with a VulnVexAffectedAssessmentRelationship are constrained\nto the affects relationship type.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"VexAffectedVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:vex-affected-1\",\n \"relationshipType\": \"affects\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"actionStatement\": \"Upgrade to version 1.4 of ACME application.\",\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VexVulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:dateTime" + }, + "sh:name": "actionStatementTime", + "sh:path": { + "@id": "security:actionStatementTime" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "actionStatement", + "sh:path": { + "@id": "security:actionStatement" + } + } + ] + }, + { + "@id": "security:VexFixedVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "VexFixedVulnAssessmentRelationship links a vulnerability to a number of elements\nrepresenting VEX products where a vulnerability has been fixed and are no longer\naffected. It represents the VEX fixed status.\n\n**Constraints**\n\nWhen linking elements using a VexFixedVulnAssessmentRelationship, the following\nrequirements must be observed:\n\n- Elements linked with a VulnVexFixedAssessmentRelationship are constrained to\nusing the fixedIn relationship type.\n- The from: end of the relationship must ve a /Security/Vulnerability classed\nelement.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"VexFixedVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:vex-fixed-in-1\",\n \"relationshipType\": \"fixedIn\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.4\",\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VexVulnAssessmentRelationship" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:VexNotAffectedVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "VexNotAffectedVulnAssessmentRelationship connects a vulnerability and a number\nof elements designating them as products not affected by the vulnerability.\nThis relationship corresponds to the VEX not_affected status.\n\n**Constraints**\n\nWhen linking elements using a VexNotVulnAffectedAssessmentRelationship, the\nfollowing requirements must be observed:\n\n* Relating elements with a VexNotAffectedVulnAssessmentRelationship is restricted\nto the doesNotAffect relationship type.\n* The from: end of the relationship must be a /Security/Vulnerability classed\nelement.\n* Both impactStatement and justificationType properties have a cardinality of\n0..1 making them optional. Nevertheless, to produce a valid VEX not_affected\nstatement, one of them MUST be defined. This is specified in the Minimum Elements\nfor VEX.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"VexNotAffectedVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:vex-not-affected-1\",\n \"relationshipType\": \"doesNotAffect\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"justificationType\": \"componentNotPresent\",\n \"impactStatement\": \"Not using this vulnerable part of this library.\",\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VexVulnAssessmentRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:dateTime" + }, + "sh:maxCount": 1, + "sh:name": "impactStatementTime", + "sh:path": { + "@id": "security:impactStatementTime" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "impactStatement", + "sh:path": { + "@id": "security:impactStatement" + } + }, + { + "sh:datatype": { + "@id": "security:VexJustificationType" + }, + "sh:maxCount": 1, + "sh:name": "justificationType", + "sh:path": { + "@id": "security:justificationType" + } + } + ] + }, + { + "@id": "security:VexUnderInvestigationVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "VexUnderInvestigationVulnAssessmentRelationship links a vulnerability to a\nnumber of products stating the vulnerability's impact on them is being\ninvestigated. It represents the VEX under_investigation status.\n\n**Constraints**\n\nWhen linking elements using a VexUnderInvestigationVulnAssessmentRelationship\nthe following requirements must be observed:\n\n- Elements linked with a VexUnderInvestigationVulnAssessmentRelationship are\nconstrained to using the underInvestigationFor relationship type.\n- The from: end of the relationship must ve a /Security/Vulnerability classed\nelement.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"VexUnderInvestigationVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:vex-underInvestigation-1\",\n \"relationshipType\": \"underInvestigationFor\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "security:VexVulnAssessmentRelationship" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:Vulnerability", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "Specifies a vulnerability and its associated information.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"Vulnerability\",\n \"@id\": \"urn:spdx.dev:vuln-1\",\n \"summary\": \"Use of a Broken or Risky Cryptographic Algorithm\",\n \"description\": \"The npm package `elliptic` before version 6.5.4 are vulnerable to Cryptographic Issues via the secp256k1 implementation in elliptic/ec/key.js. There is no check to confirm that the public key point passed into the derive function actually exists on the secp256k1 curve. This results in the potential for the private key used in this implementation to be revealed after a number of ECDH operations are performed.\", \n \"modified\": \"2021-03-08T16:02:43Z\",\n \"published\": \"2021-03-08T16:06:50Z\",\n \"externalIdentifiers\": [\n {\n \"@type\": \"ExternalIdentifier\",\n \"externalIdentifierType\": \"cve\",\n \"identifier\": \"CVE-2020-2849\",\n \"identifierLocator\": [\n \"https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-28498\",\n \"https://www.cve.org/CVERecord?id=CVE-2020-28498\"\n ],\n \"issuingAuthority\": \"urn:spdx.dev:agent-cve.org\"\n },\n {\n \"type\": \"ExternalIdentifier\",\n \"externalIdentifierType\": \"securityOther\",\n \"identifier\": \"GHSA-r9p9-mrjm-926w\",\n \"identifierLocator\": \"https://github.com/advisories/GHSA-r9p9-mrjm-926w\"\n },\n {\n \"type\": \"ExternalIdentifier\",\n \"externalIdentifierType\": \"securityOther\",\n \"identifier\": \"SNYK-JS-ELLIPTIC-1064899\",\n \"identifierLocator\": \"https://security.snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899\"\n }\n ],\n \"externalReferences\": [\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://nvd.nist.gov/vuln/detail/CVE-2020-28498\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://ubuntu.com/security/CVE-2020-28498\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityOther\",\n \"locator\": \"https://github.com/indutny/elliptic/pull/244/commits\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityOther\",\n \"locator\": \"https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/secp256k1_twist_attacks.md\"\n }\n ]\n},\n{\n \"@type\": \"Relationship\",\n \"@id\": \"urn:spdx.dev:vulnRelationship-1\",\n \"relationshipType\": \"hasAssociatedVulnerability\",\n \"from\": \"urn:npm-elliptic-6.5.2\",\n \"to\": [\"urn:spdx.dev:vuln-1\"],\n \"startTime\": \"2021-03-08T16:06:50Z\"\n},\n{\n \"@type\": \"Relationship\",\n \"@id\": \"urn:spdx.dev:vulnAgentRel-1\", \n \"relationshipType\": \"publishedBy\", \n \"from\": \"urn:spdx.dev:vuln-1\",\n \"to\": [\"urn:spdx.dev:agent-snyk\"],\n \"startTime\": \"2021-03-08T16:06:50Z\"\n}\n```", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "publishedTime", + "sh:path": { + "@id": "security:publishedTime" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "withdrawnTime", + "sh:path": { + "@id": "security:withdrawnTime" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "modifiedTime", + "sh:path": { + "@id": "security:modifiedTime" + } + } + ] + }, + { + "@id": "security:act", + "@type": [ + "owl:NamedIndividual", + "security:SsvcDecisionType" + ] + }, + { + "@id": "security:attend", + "@type": [ + "owl:NamedIndividual", + "security:SsvcDecisionType" + ] + }, + { + "@id": "security:componentNotPresent", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "security:inlineMitigationsAlreadyExist", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "security:kev", + "@type": [ + "owl:NamedIndividual", + "security:ExploitCatalogType" + ] + }, + { + "@id": "security:other", + "@type": [ + "owl:NamedIndividual", + "security:ExploitCatalogType" + ] + }, + { + "@id": "security:track", + "@type": [ + "owl:NamedIndividual", + "security:SsvcDecisionType" + ] + }, + { + "@id": "security:trackStar", + "@type": [ + "owl:NamedIndividual", + "security:SsvcDecisionType" + ] + }, + { + "@id": "security:vulnerableCodeCannotBeControlledByAdversary", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "security:vulnerableCodeNotInExecutePath", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "security:vulnerableCodeNotPresent", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "security:withdrawn", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Specified the time and date when a vulnerability was withdrawn.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:File", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "Refers to any object that stores content on a computer.\nThe type of content can optionally be provided in the contentType property.\nExternal property restriction on /Core/Element/name: minCount: 1", + "rdfs:subClassOf": { + "@id": "software:SoftwareArtifact" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "core:MediaType" + }, + "sh:maxCount": 1, + "sh:name": "contentType", + "sh:path": { + "@id": "software:contentType" + } + } + }, + { + "@id": "software:Sbom", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Software Bill of Materials (SBOM) is a collection of SPDX Elements describing a single package.\nThis could include details of the content and composition of the product,\nprovenance details of the product and/or\nits composition, licensing information, known quality or security issues, etc.", + "rdfs:subClassOf": { + "@id": "core:Bom" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "software:SBOMType" + }, + "sh:name": "sbomType", + "sh:path": { + "@id": "software:sbomType" + } + } + }, + { + "@id": "software:Snippet", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Snippet describes a certain part of a file and can be used when the file is known to have some content\nthat has been included from another original source. Snippets are useful for denoting when part of a file\nmay have been originally created under another license or copied from a place with a known vulnerability.", + "rdfs:subClassOf": { + "@id": "software:SoftwareArtifact" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:PositiveIntegerRange" + }, + "sh:maxCount": 1, + "sh:name": "lineRange", + "sh:path": { + "@id": "software:lineRange" + } + }, + { + "sh:datatype": { + "@id": "core:PositiveIntegerRange" + }, + "sh:maxCount": 1, + "sh:name": "byteRange", + "sh:path": { + "@id": "software:byteRange" + } + } + ] + }, + { + "@id": "software:SoftwareDependencyRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "TODO", + "rdfs:subClassOf": { + "@id": "core:LifecycleScopedRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "software:DependencyConditionalityType" + }, + "sh:maxCount": 1, + "sh:name": "conditionality", + "sh:path": { + "@id": "software:conditionality" + } + }, + { + "sh:datatype": { + "@id": "software:SoftwareDependencyLinkType" + }, + "sh:maxCount": 1, + "sh:name": "softwareLinkage", + "sh:path": { + "@id": "software:softwareLinkage" + } + } + ] + }, + { + "@id": "software:analyzed", + "@type": [ + "owl:NamedIndividual", + "software:SBOMType" + ] + }, + { + "@id": "software:application", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:archive", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:bom", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:build", + "@type": [ + "owl:NamedIndividual", + "software:SBOMType" + ] + }, + { + "@id": "software:configuration", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:container", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:data", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:deployed", + "@type": [ + "owl:NamedIndividual", + "software:SBOMType" + ] + }, + { + "@id": "software:design", + "@type": [ + "owl:NamedIndividual", + "software:SBOMType" + ] + }, + { + "@id": "software:device", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:documentation", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:dynamic", + "@type": [ + "owl:NamedIndividual", + "software:SoftwareDependencyLinkType" + ] + }, + { + "@id": "software:evidence", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:executable", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:file", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:firmware", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:framework", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:install", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:library", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:manifest", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:module", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:operatingSystem", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:optional", + "@type": [ + "owl:NamedIndividual", + "software:DependencyConditionalityType" + ] + }, + { + "@id": "software:other", + "@type": [ + "owl:NamedIndividual", + "software:DependencyConditionalityType", + "software:SoftwareDependencyLinkType", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:patch", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:prerequisite", + "@type": [ + "owl:NamedIndividual", + "software:DependencyConditionalityType" + ] + }, + { + "@id": "software:provided", + "@type": [ + "owl:NamedIndividual", + "software:DependencyConditionalityType" + ] + }, + { + "@id": "software:required", + "@type": [ + "owl:NamedIndividual", + "software:DependencyConditionalityType" + ] + }, + { + "@id": "software:requirement", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:runtime", + "@type": [ + "owl:NamedIndividual", + "software:SBOMType" + ] + }, + { + "@id": "software:source", + "@type": [ + "owl:NamedIndividual", + "software:SBOMType", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:specification", + "@type": [ + "owl:NamedIndividual", + "software:SoftwarePurpose" + ] + }, + { + "@id": "software:static", + "@type": [ + "owl:NamedIndividual", + "software:SoftwareDependencyLinkType" + ] + }, + { + "@id": "software:tool", + "@type": [ + "owl:NamedIndividual", + "software:SoftwareDependencyLinkType" + ] + }, + { + "@id": "ai:autonomyType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "AutonomyType indicates if a human is involved in any of the decisions of the AI software\nor if that software is fully automatic.", + "rdfs:range": { + "@id": "ai:PresenceType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:domain", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Domain describes the domain in which the AI model contained in the AI software\ncan be expected to operate successfully. Examples include computer vision, natural language etc.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:energyConsumption", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "EnergyConsumption captures the amount of energy needed to train and operate the AI model. \nThis value is also known as training energy consumption or inference energy consumption.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:hyperparameter", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field records a hyperparameter value.\nHyperparameters are parameters of the machine learning model that are used to control the learning process,\nfor example the optimization and learning rate used during the training of the model.", + "rdfs:range": { + "@id": "core:DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:informationAboutApplication", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "InformationAboutApplication describes any relevant information in free form text about \nhow the AI model is used inside the software, as well as any relevant pre-processing steps, third party APIs etc.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:informationAboutTraining", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "InformationAboutTraining describes the specific steps involved in the training of the AI model.\nFor example, it can be specified whether supervised fine-tuning \nor active learning is used as part of training the model.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:limitation", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Limitation captures a limitation of the AI Package (or of the AI models present in the AI package),\nexpressed as free form text. Note that this is not guaranteed to be exhaustive.\nFor instance, a limitation might be that the AI package cannot be used on datasets from a certain demography.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:metric", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Metric records the measurement with which the AI model was evaluated. \nThis makes statements about the prediction quality including uncertainty,\naccuracy, characteristics of the tested population, quality, fairness, explainability, robustness etc.", + "rdfs:range": { + "@id": "core:DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:metricDecisionThreshold", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Each metric might be computed based on a decision threshold. \nFor instance, precision or recall is typically computed by checking\nif the probability of the outcome is larger than 0.5.\nEach decision threshold should match with a metric field defined in the AI Package.", + "rdfs:range": { + "@id": "core:DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:modelDataPreprocessing", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ModelDataPreprocessing is a free form text that describes the preprocessing steps\napplied to the training data before training of the model(s) contained in the AI software.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:modelExplainability", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ModelExplainability is a free form text that lists the different explainability mechanisms\n(such as SHAP, or other model specific explainability mechanisms) that can be used to explain the model.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:safetyRiskAssessment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SafetyRiskAssessment categorizes the safety risk impact of the AI software\nin accordance with Article 20 of [EC Regulation No 765/2008](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).", + "rdfs:range": { + "@id": "ai:SafetyRiskAssessmentType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:sensitivePersonalInformation", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SensitivePersonalInformation notes if sensitive personal information\nis used in the training or inference of the AI models.\nThis might include biometric data, addresses or other data that can be used to infer a person's identity.", + "rdfs:range": { + "@id": "ai:PresenceType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:standardCompliance", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "StandardCompliance captures a standard that the AI software complies with. \nThis includes both published and unpublished standards, for example ISO, IEEE, ETSI etc. \nThe standard could (but not necessarily have to) be used to satisfy a legal or regulatory requirement.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "ai:typeOfModel", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "TypeOfModel records the type of the AI model(s) used in the software. \nFor instance, if it is a supervised model, unsupervised model, reinforcement learning model or a combination of those.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:buildEndTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "buildEndTime describes the time at which a build stops or finishes. This value is typically recorded by the builder.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:buildId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A buildId is a locally unique identifier to identify a unique instance of a build. This identifier differs based on build toolchain, platform, or naming convention used by an organization or standard.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:buildStartTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "buildStartTime is the time at which a build is triggered. The builder typically records this value.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:buildType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A buildType is a URI expressing the toolchain, platform, or infrastructure that the build was invoked on. For example, if the build was invoked on GitHub's CI platform using github actions, the buildType can be expressed as `https://github.com/actions`. In contrast, if the build was invoked on a local machine, the buildType can be expressed as `file://username@host/path/to/build`.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:configSourceDigest", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "configSourceDigest is the checksum of the build configuration file used by a builder to execute a build. This Property uses the Core model's [Hash](../../Core/Classes/Hash.md) class.", + "rdfs:range": { + "@id": "core:Hash" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:configSourceEntrypoint", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A build entrypoint is the invoked executable of a build which always runs when the build is triggered. For example, when a build is triggered by running a shell script, the entrypoint is `script.sh`. In terms of a declared build, the entrypoint is the position in a configuration file or a build declaration which is always run when the build is triggered. For example, in the following configuration file, the entrypoint of the build is `publish`.\n\n```\nname: Publish packages to PyPI\n\non:\ncreate:\ntags: \"*\"\n\njobs:\npublish:\nruns-on: ubuntu-latest\nif: startsWith(github.ref, 'refs/tags/')\nsteps:\n\n...\n```", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:configSourceUri", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "If a build configuration exists for the toolchain or platform performing the build, the configSourceUri of a build is the URI of that build configuration. For example, a build triggered by a GitHub action is defined by a build configuration YAML file. In this case, the configSourceUri is the URL of that YAML file. \nm", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:environment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "environment is a map of environment variables and values that are set during a build session. This is different from the [parameters](parameters.md) property in that it describes the environment variables set before a build is invoked rather than the variables provided to the builder.", + "rdfs:range": { + "@id": "core:DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "build:parameters", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "parameters is a key-value map of all build parameters and their values that were provided to the builder for a build instance. This is different from the [environment](environment.md) property in that the keys and values are provided as command line arguments or a configuration file to the builder.", + "rdfs:range": { + "@id": "core:DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Artifact", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An artifact is a distinct article or unit within the digital domain,\nsuch as an electronic file, a software package, a device or an element of data.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:Identity" + }, + "sh:name": "suppliedBy", + "sh:path": { + "@id": "core:suppliedBy" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "validUntilTime", + "sh:path": { + "@id": "core:validUntilTime" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "standard", + "sh:path": { + "@id": "core:standard" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "releaseTime", + "sh:path": { + "@id": "core:releaseTime" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "builtTime", + "sh:path": { + "@id": "core:builtTime" + } + }, + { + "sh:datatype": { + "@id": "core:Identity" + }, + "sh:name": "originatedBy", + "sh:path": { + "@id": "core:originatedBy" + } + } + ] + }, + { + "@id": "core:Bom", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Bill Of Materials (BOM) is a container for a grouping of SPDX-3.0 content\ncharacterizing details about a product.\nThis could include details of the content and composition of the product,\nprovenence details of the product and/or\nits composition, licensing information, known quality or security issues, etc.", + "rdfs:subClassOf": { + "@id": "core:Bundle" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:ElementCollection", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An SpdxCollection is a collection of Elements, not necessarily with unifying context.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:Element" + }, + "sh:minCount": 1, + "sh:name": "rootElement", + "sh:path": { + "@id": "core:rootElement" + } + }, + { + "sh:datatype": { + "@id": "core:ExternalMap" + }, + "sh:name": "imports", + "sh:path": { + "@id": "core:imports" + } + }, + { + "sh:datatype": { + "@id": "core:Element" + }, + "sh:minCount": 1, + "sh:name": "element", + "sh:path": { + "@id": "core:element" + } + }, + { + "sh:datatype": { + "@id": "core:NamespaceMap" + }, + "sh:name": "namespaces", + "sh:path": { + "@id": "core:namespaces" + } + } + ] + }, + { + "@id": "core:LifecycleScopedRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "TODO", + "rdfs:subClassOf": { + "@id": "core:Relationship" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "core:LifecycleScopeType" + }, + "sh:maxCount": 1, + "sh:name": "scope", + "sh:path": { + "@id": "core:scope" + } + } + }, + { + "@id": "core:algorithm", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An algorithm specifies the algorithm that was used for calculating the hash value.", + "rdfs:range": { + "@id": "core:HashAlgorithm" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:annotationType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An annotationType describes the type of an annotation.", + "rdfs:range": { + "@id": "core:AnnotationType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:begin", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "begin is a positive integer that defines the beginning of a range.", + "rdfs:range": { + "@id": "xsd:positiveInteger" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:builtTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A builtTime specifies the time an artifact was built.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:completeness", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Completeness gives information about whether the provided relationships are\ncomplete, known to be incomplete or if no assertion is made either way.", + "rdfs:range": { + "@id": "core:RelationshipCompleteness" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:context", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A context gives information about the circumstances or unifying properties\nthat Elements of the bundle have been assembled under.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:created", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Created is a date that identifies when the Element was originally created.\nThe time stamp can serve as an indication as to whether the analysis needs to be updated. This is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:createdBy", + "@type": "owl:ObjectProperty", + "rdfs:comment": "CreatedBy identifies who or what created the Element.\nThe generation method will assist the recipient of the Element in assessing\nthe general reliability/accuracy of the analysis information.", + "rdfs:range": { + "@id": "core:Entity" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:createdUsing", + "@type": "owl:ObjectProperty", + "rdfs:comment": "CreatedUsing identifies the tooling that was used during the creation of the Element.\nThe generation method will assist the recipient of the Element in assessing\nthe general reliability/accuracy of the analysis information.", + "rdfs:range": { + "@id": "core:Tool" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:dataLicense", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The data license provides the license under which the SPDX documentation of the Element can be used.\nThis is to alleviate any concern that content (the data or database) in an SPDX file\nis subject to any form of intellectual property right that could restrict the re-use\nof the information or the creation of another SPDX file for the same project(s).\nThis approach avoids intellectual property and related restrictions over the SPDX file,\nhowever individuals can still contract with each other to restrict release\nof specific collections of SPDX files (which map to software bill of materials)\nand the identification of the supplier of SPDX files.\nCompliance with this document includes populating the SPDX fields therein\nwith data related to such fields (\"SPDX-Metadata\"). \nThis document contains numerous fields where an SPDX file creator may provide\nrelevant explanatory text in SPDX-Metadata. Without opining on the lawfulness\nof \"database rights\" (in jurisdictions where applicable),\nsuch explanatory text is copyrightable subject matter in most Berne Convention countries.\nBy using the SPDX specification, or any portion hereof,\nyou hereby agree that any copyright rights (as determined by your jurisdiction)\nin any SPDX-Metadata, including without limitation explanatory text,\nshall be subject to the terms of the Creative Commons CC0 1.0 Universal license. \nFor SPDX-Metadata not containing any copyright rights, \nyou hereby agree and acknowledge that the SPDX-Metadata is provided to you “as-is”\nand without any representations or warranties of any kind concerning the SPDX-Metadata,\nexpress, implied, statutory or otherwise, including without limitation warranties\nof title, merchantability, fitness for a particular purpose, non-infringement,\nor the absence of latent or other defects, accuracy, or the presence or absence of errors,\nwhether or not discoverable, all to the greatest extent permissible under applicable law.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:description", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field is a detailed description of the Element. It may also be extracted from the Element itself.\nThe intent is to provide recipients of the SPDX file with a detailed technical explanation\nof the functionality, anticipated use, and anticipated implementation of the Element.\nThis field may also include a description of improvements over prior versions of the Element.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:element", + "@type": "owl:ObjectProperty", + "rdfs:comment": "This field refers to one or more Elements that are part of an ElementCollection.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:end", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "end is a positive integer that defines the end of a range.", + "rdfs:range": { + "@id": "xsd:positiveInteger" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:endTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A endTime specifies the time from which element is no applicable / valid.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:extension", + "@type": [ + "owl:NamedIndividual", + "core:ProfileIdentifierType" + ], + "rdfs:comment": "TODO", + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ExternalId identifies an external Element used within a Document but defined external to that Document.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalIdentifier", + "@type": "owl:ObjectProperty", + "rdfs:comment": "ExternalIdentifier points to a resource outside the scope of SPDX-3.0 content\nthat uniquely identifies an Element.", + "rdfs:range": { + "@id": "core:ExternalIdentifier" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalIdentifierType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An externalIdentifierType specifies the type of the external identifier.", + "rdfs:range": { + "@id": "core:ExternalIdentifierType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalReference", + "@type": "owl:ObjectProperty", + "rdfs:comment": "This field points to a resource outside the scope of the SPDX-3.0 content\nthat provides additional characteristics of an Element.", + "rdfs:range": { + "@id": "core:ExternalReference" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:externalReferenceType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An externalReferenceType specifies the type of the external reference.", + "rdfs:range": { + "@id": "core:ExternalReferenceType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:from", + "@type": "owl:ObjectProperty", + "rdfs:comment": "This field references the Element on the left-hand side of a relationship.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:hashValue", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "HashValue is the result of applying a hash algorithm to an Element.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:identifier", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An identifier uniquely identifies an external element.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:identifierLocator", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A identifierLocator is TODO", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:issuingAuthority", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A issuingAuthority is TODO", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:key", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A key used in generic a key-value pair.\nA key-value pair can be used to implement a dictionary which associates a key with a value.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:locationHint", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A locationHint provides an indication of where to retrieve an external Element.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:locator", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A locator provides the location of an external reference.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:namespace", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A namespace provides an unambiguous mechanism for other documents to reference Elements within this document.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:originatedBy", + "@type": "owl:ObjectProperty", + "rdfs:comment": "OriginatedBy identifies from where or whom the Element originally came.", + "rdfs:range": { + "@id": "core:Identity" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:prefix", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A prefix is a substitute for a URI.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:profile", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field provides information about which profiles the Element belongs to.", + "rdfs:range": { + "@id": "core:ProfileIdentifierType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:relationshipType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field provides information about the relationship between two Elements.\nFor example, you can represent a relationship between two different Files,\nbetween a Package and a File, between two Packages, or between one SPDXDocument and another SPDXDocument.", + "rdfs:range": { + "@id": "core:RelationshipType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:releaseTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A releaseTime specifies the time an artifact was released.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:rootElement", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A rootElement of a collection is the top level Element from which all other Elements are reached via relationships.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:scope", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A scope is TODO", + "rdfs:range": { + "@id": "core:LifecycleScopeType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:spdxId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SpdxId uniquely identifies an Element which may thereby be referenced by other Elements.\nThese references may be internal or external.\nWhile there may be several versions of the same Element, each one needs to be able to be referred to uniquely\nso that relationships between Elements can be clearly articulated.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:specVersion", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The specVersion provides a reference number that can be used to understand how to parse and interpret an Element.\nIt will enable both future changes to the specification and to support backward compatibility.\nThe major version number shall be incremented when incompatible changes between versions are made\n(one or more sections are created, modified or deleted).\nThe minor version number shall be incremented when backwards compatible changes are made.\n\nHere, parties exchanging information in accordance with the SPDX specification need to provide \n100% transparency as to which SPDX specification version such information is conforming to.", + "rdfs:range": { + "@id": "core:SemVer" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:standard", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Various standards may be relevant to useful to capture for specific artifacts.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:startTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A startTime specifies the time from which element is applicable / valid.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:statement", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A statement is a commentary on an assertion that an annotator has made.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:subject", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A subject is an Element an annotator has made an assertion about.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:summary", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A summary is a short description of an Element. Here, the intent is to allow the Element creator to \nprovide concise information about the function or use of the Element.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:suppliedBy", + "@type": "owl:ObjectProperty", + "rdfs:comment": "Identify the actual distribution source for the Artifact being referenced.\nThis might or might not be different from the originating distribution source for the artifact.", + "rdfs:range": { + "@id": "core:Agent" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:to", + "@type": "owl:ObjectProperty", + "rdfs:comment": "This field references an Element on the right-hand side of a relationship.", + "rdfs:range": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:validUntilTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A validUntilTime specifies until when the artifact can be used before its usage needs to be reassessed.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:value", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A value used in a generic key-value pair.\nA key-value pair can be used to implement a dictionary which associates a key with a value.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:anonymizationMethodUsed", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "AnonymizationMethodUsed describes the methods used to anonymize the dataset (of fields in the dataset).", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:confidentialityLevel", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "ConfidentialityLevel describes the levels of confidentiality of the data points contained in the dataset.", + "rdfs:range": { + "@id": "dataset:ConfidentialityLevelType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:dataCollectionProcess", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DataCollectionProcess describes how a dataset was collected.\nExamples include the sources from which a dataset was scrapped or\nthe interview protocol that was used for data collection.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:dataPreprocessing", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DataPreprocessing describes the various preprocessing steps\nthat were applied to the raw data to create the dataset.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetAvailability", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Some datasets are publicly available and can be downloaded directly. Others are only accessible behind a clickthrough, or after filling a registration form. This field will describe the dataset availability from that perspective.", + "rdfs:range": { + "@id": "dataset:DatasetAvailabilityType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetNoise", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DatasetNoise describes what kinds of noises a dataset might encompass.\nThe field uses free form text to specify the fields or the samples that might be noisy.\nAlternatively, it can also be used to describe various noises that could impact the whole dataset.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetSize", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DatasetSize Captures how large a dataset is.\nThe size is to be measured in bytes.", + "rdfs:range": { + "@id": "xsd:nonNegativeInteger" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Type describes the datatype contained in the dataset. For example a dataset can be a image dataset or a text dataset or sometimes a multimodal dataset that contains multiple types of data", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:datasetUpdateMechanism", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "DatasetUpdateMechanism describes a mechanism to update the dataset.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:intendedUse", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "IntendedUse describes what the given dataset should be used for.\nSome datasets are collected to be used only for particular purposes. \nFor example, medical data collected from a specific demography might only be applicable\nfor training machine learning models to make predictions for that demography.\nIn such a case, the intendedUse field would capture this information.\nSimilarly, if a dataset is collected for building a facial recognition model,\nthe intendedUse field would specify that.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:knownBias", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "KnownBias is a free form text field that describes the different biases that the dataset encompasses.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:sensitivePersonalInformation", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SensitivePersonalInformation indicates the presence of sensitive personal data\nor information that allows drawing conclusions about a person's identity.", + "rdfs:range": { + "@id": "dataset:PresenceType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "dataset:sensor", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Sensor describes a sensor that was used for collecting the data\nand its calibration value as a key-value pair.", + "rdfs:range": { + "@id": "core:DictionaryEntry" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:additionComment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An additionComment for a LicenseAddition describes general factual information\nabout the LicenseAddition. It should not contain information (or links to\ninformation) that includes any kind of interpretation about the meaning or\neffect of the License, even if written by the license addition's author.\n\nExamples of information for an additionComment may include the following:\n\n* If the LicenseAddition's identifier is deprecated, it may briefly explain the\n reason for deprecation.\n* It may include the date of release, if identified, for LicenseAdditions with\n multiple versions.\n* It may include links to other official language translations for the\n LicenseAddition.\n* It may include a reference to the License(s) with which this LicenseAddition\n is typically used.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:additionId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An additionId contains a human-readable, short-form identifier for a\nLicenseAddition. It may only include letters, numbers, period (\".\") and\nhyphen (\"-\") characters.\n\nFor a ListedLicenseException, the licenseId will be as specified on the\n[SPDX Exceptions List](https://spdx.org/licenses/exceptions-index.html) for the\nparticular exception.\n\nFor a CustomLicenseAddition, the short-form identifier must begin with the\nprefix `AdditionRef-` and must be unique within the applicable SPDX namespace.\nThe short-form identifier may be preceded by an SPDX namespace or a\nfully-qualified URI prefix.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:additionName", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An additionName contains the full name of a LicenseAddition, preferably using\nthe title found in the applicable license addition text or file, or as\notherwise specified by the LicenseAddition's author or steward.\n\nWhen no such title is specified, using a name from another well-known source or list\nof licenses additions (such as OSI or Fedora) is suggested.\n\nIf no official or common name is known, any name may be used to aid in\ndistinguishing the LicenseAddition from other LicenseAdditions.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:additionText", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An additionText contains the plain text of the LicenseAddition, without\ntemplating or other similar markup.\n\nUsers of the additionText for a License can apply the SPDX Matching Guidelines\nwhen comparing it to another text for matching purposes.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:isDeprecatedAdditionId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The isDeprecatedAdditionId property specifies whether an identifier for a\nLicenseAddition has been marked as deprecated. If the property is not defined,\nthen it is presumed to be false (i.e., not deprecated).\n\nIf the LicenseAddition is included on the SPDX Exceptions List, then\nthe `deprecatedVersion` property indicates on which version release of the\nExceptions List it was first marked as deprecated.\n\n\"Deprecated\" in this context refers to deprecating the use of the\n_identifier_, not the underlying license addition. In other words, even if a\nLicenseAddition's author or steward has stated that a particular\nLicenseAddition generally should not be used, that would _not_ mean that the\nLicenseAddition's identifier is \"deprecated.\" Rather, a LicenseAddition\noperator is typically marked as \"deprecated\" when it is determined that use of\nanother identifier is preferable.", + "rdfs:range": { + "@id": "xsd:boolean" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:isDeprecatedLicenseId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The isDeprecatedLicenseId property specifies whether an identifier for a\nLicense or LicenseAddition has been marked as deprecated. If the property\nis not defined, then it is presumed to be false (i.e., not deprecated).\n\nIf the License or LicenseAddition is included on the SPDX License List, then\nthe `deprecatedVersion` property indicates on which version release of the\nLicense List it was first marked as deprecated.\n\n\"Deprecated\" in this context refers to deprecating the use of the\n_identifier_, not the underlying license. In other words, even if a License's\nauthor or steward has stated that a particular License generally should not be\nused, that would _not_ mean that the License's identifier is \"deprecated.\"\nRather, a License or LicenseAddition operator is typically marked as\n\"deprecated\" when it is determined that use of another identifier is\npreferable.", + "rdfs:range": { + "@id": "xsd:boolean" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:isFsfLibre", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "isFsfLibre specifies whether the [Free Software Foundation FSF](https://fsf.org)\nhas listed this License as \"free\" in their commentary on licenses, located at\nthe time of this writing at https://www.gnu.org/licenses/license-list.en.html.\n\nA value of \"true\" indicates that the FSF has listed this License as _free_.\n\nA value of \"false\" indicates that the FSF has listed this License as _not free_.\n\nIf the isFsfLibre field is not specified, the SPDX data creator makes no\nassertions about whether the License is listed in the FSF's commentary.", + "rdfs:range": { + "@id": "xsd:boolean" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:isOsiApproved", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "isOsiApproved specifies whether the [Open Source Initiative (OSI)](https://opensource.org)\nhas listed this License as \"approved\" in their list of OSI Approved Licenses,\nlocated at the time of this writing at https://opensource.org/licenses/.\n\nA value of \"true\" indicates that the OSI has listed this License as approved.\n\nA value of \"false\" indicates that the OSI has not listed this License as\napproved.\n\nIf the isOsiApproved field is not specified, the SPDX data creator makes no\nassertions about whether the License is approved by the OSI.", + "rdfs:range": { + "@id": "xsd:boolean" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:licenseComment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A licenseComment describes general factual information about the License. It\nshould not contain information (or links to information) that includes any kind\nof interpretation about the meaning or effect of the License, even if written\nby the license's author.\n\nExamples of information for a licenseComment may include the following:\n\n* If the License's identifier is deprecated, it may briefly explain the reason\n for deprecation.\n* It may include the date of release, if identified, for Licenses with multiple\n versions.\n* It may include links to other official language translations for the License.\n* For LicenseAdditions, it may include a reference to the License(s) with\n which this additional text is typically used.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:licenseId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A licenseId contains a human-readable, short-form license identifier for a\nLicense. It may only include letters, numbers, period (\".\") and hyphen (\"-\")\ncharacters.\n\nFor a ListedLicense, the licenseId will be as specified on the\n[SPDX License List](https://spdx.org/licenses) for the particular license.\n\nFor a CustomLicense, the short-form license identifer must begin with the\nprefix `LicenseRef-` and must be unique within the applicable SPDX namespace.\nThe short-form license ID may be preceded by an SPDX namespace or a\nfully-qualified URI prefix.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:licenseName", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A licenseName contains the full name of a License, preferably using the title found\nin the applicable license text or file, or as otherwise specified by the\nLicense's author or steward.\n\nWhen no such title is specified, using a name from another well-known source or list\nof licenses (such as OSI or Fedora) is suggested.\n\nIf no official or common name is known, any name may be used to aid in\ndistinguishing the License from other Licenses.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:licenseText", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A licenseText contains the plain text of the License, without templating\nor other similar markup.\n\nUsers of the licenseText for a License can apply the SPDX Matching Guidelines\nwhen comparing it to another text for matching purposes.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:standardAdditionTemplate", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A standardAdditionTemplate contains a license addition template which describes\nsections of the LicenseAddition text which can be varied. See the Legacy Text\nTemplate format section of the SPDX specification for format information.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:standardLicenseHeader", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A standardLicenseHeader contains the plain text of the License author's\npreferred wording to be used, typically in a source code file's header\ncomments or similar location, to indicate that the file is subject to\nthe specified License.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:standardLicenseTemplate", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A standardLicenseTemplate contains a license template which describes\nsections of the License text which can be varied. See the Legacy Text Template\nformat section of the SPDX specification for format information.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:subjectAddition", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A subjectAddition is a LicenseAddition which is subject to a 'with additional\ntext' effect (WithAdditionOperator).", + "rdfs:range": { + "@id": "licensing:LicenseAddition" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:actionStatement", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "When an element is referenced with a VexAffectedVulnAssessmentRelationship,\nthe relationship MUST include one actionStatement that SHOULD describe actions\nto remediate or mitigate the vulnerability.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:assessedElement", "@type": "owl:ObjectProperty", - "rdfs:comment": "This field references an Element on the right-hand side of a relationship.", + "rdfs:comment": "Specifies subpackages, files or snippets referenced by a security assessment\nto specify the precise location where a vulnerability was found.", "rdfs:range": { "@id": "core:Element" }, "ns0:term_status": "Stable" }, { - "@id": "core:unknown", - "@type": [ - "owl:NamedIndividual", - "core:RelationshipCompleteness" - ] - }, - { - "@id": "core:urlScheme", - "@type": [ - "owl:NamedIndividual", - "core:ExternalIdentifierType" - ] + "@id": "security:decisionType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A decisionType is a mandatory value and must select one of the four entries in the `SsvcDecisionType.md` vocabulary.", + "rdfs:range": { + "@id": "security:SsvcDecisionType" + }, + "ns0:term_status": "Stable" }, { - "@id": "core:validUntilTime", + "@id": "security:exploited", "@type": "owl:DatatypeProperty", - "rdfs:comment": "A validUntilTime specifies until when the artifact can be used before its usage needs to be reassessed.", + "rdfs:comment": "This field is set when a CVE is listed in an exploit catalog.", "rdfs:range": { - "@id": "xsd:dateTime" + "@id": "xsd:boolean" }, "ns0:term_status": "Stable" }, { - "@id": "core:value", + "@id": "security:impactStatement", "@type": "owl:DatatypeProperty", - "rdfs:comment": "A value used in a generic key-value pair.\nA key-value pair can be used to implement a dictionary which associates a key with a value.", + "rdfs:comment": "When a VEX product element is related with a VexNotAffectedVulnAssessmentRelationship\nand a machine readable justification label is not provided, then an impactStatement\nthat further explains how or why the prouct(s) are not affected by the vulnerability\nmust be provided.", "rdfs:range": { "@id": "xsd:string" }, "ns0:term_status": "Stable" }, { - "@id": "core:variant", - "@type": [ - "owl:NamedIndividual", - "core:RelationshipType" - ] - }, - { - "@id": "core:verifiedUsing", - "@type": "owl:ObjectProperty", - "rdfs:comment": "VerifiedUsing provides an IntegrityMethod with which the integrity of an Element can be asserted.", + "@id": "security:justificationType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "When stating that an element is not affected by a vulnerability, the\nVexNotAffectedVulnAssessmentRelationship must include a justification from the\nmachine-readable labels catalog informing the reason the element is not impacted.\n\nimpactStatement which is a string with English prose can be used instead or as\ncomplementary to the justification label, but one of both MUST be defined.", "rdfs:range": { - "@id": "core:IntegrityMethod" + "@id": "security:VexJustificationType" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:Dataset", - "@type": "owl:Class", - "rdfs:comment": "Metadata information that can be added to a dataset that may be used in a software or to train/test an AI package.", - "rdfs:subClassOf": { - "@id": "https://spdx.org/rdf/Dataset#/Software/Package" + "@id": "security:probability", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The probability score between 0 and 1 (0 and 100%) estimating the likelihood\nthat a vulnerability will be exploited in the next 12 months.", + "rdfs:range": { + "@id": "xsd:decimal" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:anonymizationMethodUsed", + "@id": "software:attributionText", "@type": "owl:DatatypeProperty", - "rdfs:comment": "AnonymizationMethodUsed describes the methods used to anonymize the dataset (of fields in the dataset).", + "rdfs:comment": "An attributionText for a software Package, File or Snippet provides a consumer\nof SPDX data with acknowledgement content, to assist redistributors of the\nPackage, File or Snippet with reproducing those acknowledgements.\n\nFor example, this field may include a statement that is required by a\nparticular license to be reproduced in end-user documentation, advertising\nmaterials, or another form.\n\nThis field may describe where, or in which contexts, the acknowledgements\nneed to be reproduced, but it is not required to do so. The SPDX data creator\nmay also explain elsewhere (such as in a licenseComment field) how they intend\nfor data in this field to be used.\n\nAn attributionText is is not meant to include the software Package, File or\nSnippet’s actual complete license text (see concludedLicense to identify the\ncorresponding license).", "rdfs:range": { "@id": "xsd:string" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:confidentialityLevel", + "@id": "software:byteRange", "@type": "owl:DatatypeProperty", - "rdfs:comment": "ConfidentialityLevel describes the levels of confidentiality of the data points contained in the dataset.", + "rdfs:comment": "This field defines the byte range in the original host file that the snippet information applies to.\nA range of bytes is independent of various formatting concerns, and the most accurate way \nof referring to the differences. The choice was made to start the numbering of \nthe byte range at 1 to be consistent with the W3C pointer method vocabulary.", "rdfs:range": { - "@id": "dataset:ConfidentialityLevelType" + "@id": "core:PositiveIntegerRange" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:dataCollectionProcess", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "DataCollectionProcess describes how a dataset was collected.\nExamples include the sources from which a dataset was scrapped or\nthe interview protocol that was used for data collection.", + "@id": "software:concludedLicense", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A concludedLicense is the license identified by the SPDX data creator,\nbased on analyzing the license information in the software Package, File\nor Snippet and other information to arrive at a reasonably objective\nconclusion as to what license governs it.\n\nIf a concludedLicense has a NONE value (NoneLicense), this indicates that the\nSPDX data creator has looked and did not find any license information for this\nsoftware Package, File or Snippet.\n\nIf a concludedLicense has a NOASSERTION value (NoAssertionLicense), this\nindicates that one of the following applies:\n* the SPDX data creator has attempted to but cannot reach a reasonable\n objective determination;\n* the SPDX data creator has made no attempt to determine this field; or\n* the SPDX data creator has intentionally provided no information (no\n meaning should be implied by doing so).\n\nA written explanation of a NOASSERTION value (NoAssertionLicense) MAY be\nprovided in the licenseComment field.\n\nIf the concludedLicense for a software Package, File or Snippet is not the\nsame as its declaredLicense, a written explanation SHOULD be provided in\nthe licenseComment field.\n\nIf the declaredLicense for a software Package, File or Snippet is a choice\nof more than one license (e.g. a license expression combining two licenses\nthrough use of the `OR` operator), then the concludedLicense may either\nretain the license choice or identify which license was chosen.", "rdfs:range": { - "@id": "xsd:string" + "@id": "software:LicenseField" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:dataPreprocessing", + "@id": "software:conditionality", "@type": "owl:DatatypeProperty", - "rdfs:comment": "DataPreprocessing describes the various preprocessing steps\nthat were applied to the raw data to create the dataset.", + "rdfs:comment": "A conditionality is TODO", "rdfs:range": { - "@id": "xsd:string" + "@id": "software:DependencyConditionalityType" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:datasetAvailability", + "@id": "software:contentIdentifier", "@type": "owl:DatatypeProperty", - "rdfs:comment": "Some datasets are publicly available and can be downloaded directly. Others are only accessible behind a clickthrough, or after filling a registration form. This field will describe the dataset availability from that perspective.", + "rdfs:comment": "A contentIdentifier is TODO", "rdfs:range": { - "@id": "dataset:DatasetAvailabilityType" + "@id": "xsd:anyURI" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:datasetNoise", + "@id": "software:contentType", "@type": "owl:DatatypeProperty", - "rdfs:comment": "DatasetNoise describes what kinds of noises a dataset might encompass.\nThe field uses free form text to specify the fields or the samples that might be noisy.\nAlternatively, it can also be used to describe various noises that could impact the whole dataset.", + "rdfs:comment": "This field is a reasonable estimation of the content type of the Element, from a creator perspective.\nContent type is intrinsic to the Element, independent of how the Element is being used.", + "rdfs:range": { + "@id": "core:MediaType" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:copyrightText", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A copyrightText consists of the text(s) of the copyright notice(s) found\nfor a software Package, File or Snippet, if any.\n\nIf a copyrightText contains text, then it may contain any text related to\none or more copyright notices (even if not complete) for that software\nPackage, File or Snippet.\n\nIf a copyrightText has a \"NONE\" value, this indicates that the software\nPackage, File or Snippet contains no copyright notice whatsoever.\n\nIf a copyrightText has a \"NOASSERTION\" value, this indicates that one of the\nfollowing applies:\n* the SPDX data creator has attempted to but cannot reach a reasonable\n objective determination;\n* the SPDX data creator has made no attempt to determine this field; or\n* the SPDX data creator has intentionally provided no information (no\n meaning should be implied by doing so).", "rdfs:range": { "@id": "xsd:string" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:datasetSize", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "DatasetSize Captures how large a dataset is.\nThe size is to be measured in bytes.", + "@id": "software:declaredLicense", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A declaredLicense is the license identified in text in the software package,\nfile or snippet as the license declared by its authors.\n\nThis field is not intended to capture license information obtained from an\nexternal source, such as a package's website. Such information can be\nincluded, as needed, in a concludedLicense field.\n\nA declaredLicense may be expressed differently in practice for different\ntypes of artifacts. For example:\n\n* for Packages:\n * would include license info describing the license of the Package as a\n whole, when it is found in the Package itself (e.g., LICENSE file,\n README file, metadata in the repository, etc.)\n * would not include any license information that is not in the Package\n itself (e.g., license information from the project’s website or from a\n third party repository or website)\n* for Files:\n * would include license info found in the File itself (e.g., license\n header or notice, comments, SPDX-License-Identifier expression)\n * would not include license info found in a different file (e.g., LICENSE\n file in the top directory of a repository)\n* for Snippets:\n * would include license info found in the Snippet itself (e.g., license\n notice, comments, SPDX-License-Identifier expression)\n * would not include license info found elsewhere in the File or in a\n different File (e.g., comment at top of File if it is not within the\n Snippet, LICENSE file in the top directory of a repository)\n\nIf a declaredLicense has a NONE value (NoneLicense), this indicates that the\ncorresponding Package, File or Snippet contains no license information\nwhatsoever.\n\nIf a declaredLicense has a NOASSERTION value (NoAssertionLicense), this\nindicates that one of the following applies:\n* the SPDX data creator has attempted to but cannot reach a reasonable\n objective determination;\n* the SPDX data creator has made no attempt to determine this field; or\n* the SPDX data creator has intentionally provided no information (no meaning\n should be implied by doing so).", "rdfs:range": { - "@id": "xsd:nonNegativeInteger" + "@id": "software:LicenseField" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:datasetUpdateMechanism", + "@id": "software:downloadLocation", "@type": "owl:DatatypeProperty", - "rdfs:comment": "DatasetUpdateMechanism describes a mechanism to update the dataset.", + "rdfs:comment": "DownloadLocation identifies the download Uniform Resource Identifier \nfor the package at the time that the document was created.\nWhere and how to download the exact package being referenced \nis critical for verification and tracking data.", "rdfs:range": { - "@id": "xsd:string" + "@id": "xsd:anyURI" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:intendedUse", + "@id": "software:homePage", "@type": "owl:DatatypeProperty", - "rdfs:comment": "IntendedUse describes what the given dataset should be used for.\nSome datasets are collected to be used only for particular purposes. \nFor example, medical data collected from a specific demography might only be applicable\nfor training machine learning models to make predictions for that demography.\nIn such a case, the intendedUse field would capture this information.\nSimilarly, if a dataset is collected for building a facial recognition model,\nthe intendedUse field would specify that.", + "rdfs:comment": "HomePage is a place for the SPDX document creator to record a website that serves as the package's home page.\nThis saves the recipient of the SPDX document who is looking for more info from\nhaving to search for and verify a match between the package and the associated project home page.\nThis link can also be used to reference further information about the package\nreferenced by the SPDX document creator.", "rdfs:range": { - "@id": "xsd:string" + "@id": "xsd:anyURI" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:knownBias", + "@id": "software:lineRange", "@type": "owl:DatatypeProperty", - "rdfs:comment": "KnownBias is a free form text field that describes the different biases that the dataset encompasses.", + "rdfs:comment": "This field defines the line range in the original host file that the snippet information applies to.\nIf there is a disagreement between the byte range and line range, the byte range values will take precedence.\nA range of lines is a convenient reference for those files where there is a known line delimiter. \nThe choice was made to start the numbering of the lines at 1 to be consistent with the W3C pointer method vocabulary.", "rdfs:range": { - "@id": "xsd:string" + "@id": "core:PositiveIntegerRange" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:sensitivePersonalInformation", + "@id": "software:packageUrl", "@type": "owl:DatatypeProperty", - "rdfs:comment": "SensitivePersonalInformation indicates the presence of sensitive personal data\nor information that allows drawing conclusions about a person's identity.", + "rdfs:comment": "A packageUrl is TODO", "rdfs:range": { - "@id": "dataset:PresenceType" + "@id": "xsd:anyURI" }, "ns0:term_status": "Stable" }, { - "@id": "dataset:sensor", + "@id": "software:packageVersion", "@type": "owl:DatatypeProperty", - "rdfs:comment": "Sensor describes a sensor that was used for collecting the data\nand its calibration value as a key-value pair.", + "rdfs:comment": "A packageVersion is useful for identification purposes and for indicating later changes of the package version.", "rdfs:range": { - "@id": "https://spdx.org/rdf/Dataset#/Core/DictionaryEntry" + "@id": "xsd:string" }, "ns0:term_status": "Stable" }, { - "@id": "software:File", - "@type": "owl:Class", - "rdfs:comment": "TODO This is about the File class.", - "rdfs:subClassOf": { - "@id": "https://spdx.org/rdf/Software#/Core/Artifact" + "@id": "software:purpose", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "purpose provides information about the primary purpose of the software artifact.", + "rdfs:range": { + "@id": "software:SoftwarePurpose" }, "ns0:term_status": "Stable" }, { - "@id": "software:Package", - "@type": "owl:Class", - "rdfs:comment": "A package refers to any unit of content that can be associated with a distribution of software.\nTypically, a package is composed of one or more files. \nAny of the following non-limiting examples may be (but are not required to be) represented in SPDX as a package:\n\n - a tarball, zip file or other archive\n - a directory or sub-directory\n - a separately distributed piece of software which another Package or File uses or depends upon (e.g., a Python package, a Go module, ...)\n - a container image, and/or each image layer within a container image\n - a collection of one or more sub-packages\n - a Git repository snapshot from a particular point in time\n\nNote that some of these could be represented in SPDX as a file as well.", - "rdfs:subClassOf": { - "@id": "https://spdx.org/rdf/Software#/Core/Artifact" + "@id": "software:sbomType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field is a reasonable estimation of the type of SBOM created from a creator perspective.\nIt is intended to be used to give guidance on the elements that may be contained within it.\nAligning with the guidance produced in [Types of Software Bill of Material (SBOM) Documents](https://www.cisa.gov/sites/default/files/2023-04/sbom-types-document-508c.pdf).", + "rdfs:range": { + "@id": "software:SBOMType" }, "ns0:term_status": "Stable" }, { - "@id": "software:Sbom", - "@type": "owl:Class", - "rdfs:comment": "A Software Bill of Materials (SBOM) is a collection of SPDX Elements describing a single package.\nThis could include details of the content and composition of the product,\nprovenance details of the product and/or\nits composition, licensing information, known quality or security issues, etc.", - "rdfs:subClassOf": { - "@id": "https://spdx.org/rdf/Software#/Core/Bom" + "@id": "software:softwareLinkage", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A softwareLinkage is TODO", + "rdfs:range": { + "@id": "software:SoftwareDependencyLinkType" }, "ns0:term_status": "Stable" }, { - "@id": "software:Snippet", - "@type": "owl:Class", - "rdfs:comment": "A Snippet describes a certain part of a file and can be used when the file is known to have some content\nthat has been included from another original source. Snippets are useful for denoting when part of a file\nmay have been originally created under another license or copied from a place with a known vulnerability.", - "rdfs:subClassOf": { - "@id": "https://spdx.org/rdf/Software#/Core/Artifact" + "@id": "software:sourceInfo", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SourceInfo records any relevant background information or additional comments\nabout the origin of the package. For example, this field might include comments \nindicating whether the package was pulled from a source code management system \nor has been repackaged. The creator can provide additional information to describe\nany anomalies or discoveries in the determination of the origin of the package.", + "rdfs:range": { + "@id": "xsd:string" }, "ns0:term_status": "Stable" }, { - "@id": "software:application", + "@id": "core:Bundle", "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A bundle is a collection of Elements that have a shared context.", + "rdfs:subClassOf": { + "@id": "core:ElementCollection" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "context", + "sh:path": { + "@id": "core:context" + } + } }, { - "@id": "software:archive", + "@id": "core:ExternalIdentifier", "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An ExternalIdentifier is a reference to a resource outside the scope of SPDX-3.0 content\nthat uniquely identifies an Element.", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:name": "identifierLocator", + "sh:path": { + "@id": "core:identifierLocator" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "identifier", + "sh:path": { + "@id": "core:identifier" + } + }, + { + "sh:datatype": { + "@id": "core:ExternalIdentifierType" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "externalIdentifierType", + "sh:path": { + "@id": "core:externalIdentifierType" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "comment", + "sh:path": { + "@id": "core:comment" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "issuingAuthority", + "sh:path": { + "@id": "core:issuingAuthority" + } + } ] }, { - "@id": "software:bom", + "@id": "core:ExternalReference", "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An External Reference points to a resource outside the scope of the SPDX-3.0 content\nthat provides additional characteristics of an Element.", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:name": "locator", + "sh:path": { + "@id": "core:locator" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "comment", + "sh:path": { + "@id": "core:comment" + } + }, + { + "sh:datatype": { + "@id": "core:MediaType" + }, + "sh:maxCount": 1, + "sh:name": "contentType", + "sh:path": { + "@id": "core:contentType" + } + }, + { + "sh:datatype": { + "@id": "core:ExternalReferenceType" + }, + "sh:maxCount": 1, + "sh:name": "externalReferenceType", + "sh:path": { + "@id": "core:externalReferenceType" + } + } ] }, { - "@id": "software:byteRange", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "This field defines the byte range in the original host file that the snippet information applies to.\nA range of bytes is independent of various formatting concerns, and the most accurate way \nof referring to the differences. The choice was made to start the numbering of \nthe byte range at 1 to be consistent with the W3C pointer method vocabulary.", - "rdfs:range": { - "@id": "software:positiveIntegerRange" + "@id": "core:Hash", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A hash is a grouping of characteristics unique to the result\nof applying a mathematical algorithm\nthat maps data of arbitrary size to a bit string (the hash)\nand is a one-way function, that is,\na function which is practically infeasible to invert.\nThis is commonly used for integrity checking of data.", + "rdfs:subClassOf": { + "@id": "core:IntegrityMethod" }, - "ns0:term_status": "Stable" + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "hashValue", + "sh:path": { + "@id": "core:hashValue" + } + }, + { + "sh:datatype": { + "@id": "core:HashAlgorithm" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "algorithm", + "sh:path": { + "@id": "core:algorithm" + } + } + ] }, { - "@id": "software:configuration", + "@id": "core:Payload", "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "TODO", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:NamespaceMap" + }, + "sh:name": "namespaces", + "sh:path": { + "@id": "core:namespaces" + } + }, + { + "sh:datatype": { + "@id": "core:CreationInfo" + }, + "sh:maxCount": 1, + "sh:name": "creationInfo", + "sh:path": { + "@id": "core:creationInfo" + } + }, + { + "sh:datatype": { + "@id": "core:ExternalMap" + }, + "sh:name": "imports", + "sh:path": { + "@id": "core:imports" + } + } ] }, { - "@id": "software:container", + "@id": "core:Relationship", "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Relationship is a grouping of characteristics unique to an assertion\nthat one Element is related to one or more other Elements in some way.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "endTime", + "sh:path": { + "@id": "core:endTime" + } + }, + { + "sh:datatype": { + "@id": "core:RelationshipType" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "relationshipType", + "sh:path": { + "@id": "core:relationshipType" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "startTime", + "sh:path": { + "@id": "core:startTime" + } + }, + { + "sh:datatype": { + "@id": "core:Element" + }, + "sh:name": "to", + "sh:path": { + "@id": "core:to" + } + }, + { + "sh:datatype": { + "@id": "core:RelationshipCompleteness" + }, + "sh:maxCount": 1, + "sh:name": "completeness", + "sh:path": { + "@id": "core:completeness" + } + }, + { + "sh:datatype": { + "@id": "core:Element" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "from", + "sh:path": { + "@id": "core:from" + } + } ] }, { - "@id": "software:contentIdentifier", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "A contentIdentifier is TODO", - "rdfs:range": { - "@id": "xsd:anyURI" + "@id": "core:SemVer", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "The semantic version is a string\nthat is following the specification of [Semantic Versioning 2.0.0](https://semver.org/).\nFormat restriction: pattern: ^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$", + "rdfs:subClassOf": { + "@id": "xsd:string" }, "ns0:term_status": "Stable" }, { - "@id": "software:contentType", + "@id": "core:Tool", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Tool is an element of hardware and/or software utilized to carry out a particular function.", + "rdfs:subClassOf": { + "@id": "core:Entity" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:contentType", "@type": "owl:DatatypeProperty", - "rdfs:comment": "This field is a reasonable estimation of the content type of the Element, from a creator perspective.\nContent type is intrinsic to the Element, independent of how the Element is being used.", + "rdfs:comment": "ContentType specifies the media type of an Element.", "rdfs:range": { - "@id": "software:mediaType" + "@id": "core:MediaType" }, "ns0:term_status": "Stable" }, { - "@id": "software:data", - "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] + "@id": "core:name", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "This field identifies the name of an Element as designated by the creator. \nThe name of an Element is an important convention and easier to refer to than the URI.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" }, { - "@id": "software:device", - "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] + "@id": "core:verifiedUsing", + "@type": "owl:ObjectProperty", + "rdfs:comment": "VerifiedUsing provides an IntegrityMethod with which the integrity of an Element can be asserted.", + "rdfs:range": { + "@id": "core:IntegrityMethod" + }, + "ns0:term_status": "Stable" }, { - "@id": "software:documentation", - "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] + "@id": "licensing:deprecatedVersion", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A deprecatedVersion for a ListedLicense or ListedLicenseException on the SPDX\nLicense List specifies which version release of the License List was the first\none in which it was marked as deprecated.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" }, { - "@id": "software:downloadLocation", + "@id": "licensing:listVersionAdded", "@type": "owl:DatatypeProperty", - "rdfs:comment": "DownloadLocation identifies the download Uniform Resource Identifier \nfor the package at the time that the document was created.\nWhere and how to download the exact package being referenced \nis critical for verification and tracking data.", + "rdfs:comment": "A listVersionAdded for a ListedLicense or ListedLicenseException on the SPDX\nLicense List specifies which version release of the License List was the first\none in which it was included.", "rdfs:range": { - "@id": "xsd:anyURI" + "@id": "xsd:string" }, "ns0:term_status": "Stable" }, { - "@id": "software:executable", - "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] + "@id": "licensing:member", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A member is a license expression participating in a conjuctive (of type\nConjunctiveLicenseSet) or a disjunctive (of type DisjunctiveLicenseSet)\nlicense set.", + "rdfs:range": { + "@id": "licensing:AnyLicenseInfo" + }, + "ns0:term_status": "Stable" }, { - "@id": "software:file", - "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] + "@id": "licensing:obsoletedBy", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "An obsoletedBy value for a deprecated License or LicenseAddition specifies\nthe licenseId of the replacement License or LicenseAddition that is preferred\nto be used in its place. It should use the same format as specified for a\nlicenseId.\n\nThe License's or LicenseAddition's comment value may include more information\nabout the reason why the licenseId specified in the obsoletedBy value is\npreferred.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" }, { - "@id": "software:filePurpose", + "@id": "licensing:seeAlso", "@type": "owl:DatatypeProperty", - "rdfs:comment": "FilePurpose provides information about the primary purpose of the file.", + "rdfs:comment": "A seeAlso defines a cross-reference with a URL where the License or\nLicenseAddition can be found in use by one or a few projects.\n\nIf applicable, it should include a URL where the license text is posted by\nthe license steward, particularly if the license steward has made available a\n\"canonical\" primary URL for the license text.\n\nIf the license is OSI approved, a seeAlso should be included with the URL for\nthe license's listing on the OSI website.\n\nThe seeAlso URL may refer to a previously-available URL for the License or\nLicenseAddition which is no longer active.\n\nWhere applicable, the seeAlso URL should include the license text in its\nnative language. seeAlso URLs to English or other translations may be included\nwhere multiple, equivalent official translations exist.", "rdfs:range": { - "@id": "software:SoftwarePurpose" + "@id": "xsd:anyURI" }, "ns0:term_status": "Stable" }, { - "@id": "software:firmware", - "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] - }, - { - "@id": "software:framework", - "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] + "@id": "licensing:subjectLicense", + "@type": "owl:ObjectProperty", + "rdfs:comment": "A subjectLicense is a License which is subject to either an 'or later' effect\n(OrLaterOperator) or a 'with additional text' effect (WithAdditionOperator).", + "rdfs:range": { + "@id": "licensing:License" + }, + "ns0:term_status": "Stable" }, { - "@id": "software:homePage", + "@id": "security:modifiedTime", "@type": "owl:DatatypeProperty", - "rdfs:comment": "HomePage is a place for the SPDX document creator to record a website that serves as the package's home page.\nThis saves the recipient of the SPDX document who is looking for more info from\nhaving to search for and verify a match between the package and the associated project home page.\nThis link can also be used to reference further information about the package\nreferenced by the SPDX document creator.", + "rdfs:comment": "Specifies a time when a vulnerability assessment was last modified.", "rdfs:range": { - "@id": "xsd:anyURI" + "@id": "core:DateTime" }, "ns0:term_status": "Stable" }, { - "@id": "software:install", - "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] - }, - { - "@id": "software:library", - "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] - }, - { - "@id": "software:lineRange", + "@id": "security:publishedTime", "@type": "owl:DatatypeProperty", - "rdfs:comment": "This field defines the line range in the original host file that the snippet information applies to.\nIf there is a disagreement between the byte range and line range, the byte range values will take precedence.\nA range of lines is a convenient reference for those files where there is a known line delimiter. \nThe choice was made to start the numbering of the lines at 1 to be consistent with the W3C pointer method vocabulary.", + "rdfs:comment": "Specifies the time when a vulnerability was first published.", "rdfs:range": { - "@id": "software:positiveIntegerRange" + "@id": "core:DateTime" }, "ns0:term_status": "Stable" }, { - "@id": "software:module", - "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] + "@id": "security:score", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "The score provides information on the severity of a vulnerability per the\nCommon Vulnerability Scoring System as defined on [https://www.first.org/cvss](https://www.first.org/cvss/).", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" }, { - "@id": "software:operatingSystem", - "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] + "@id": "security:vector", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Sepcifies the vector string of a vulnerability, a string combining metrics\nfrom an assessment of its severity.", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" }, { - "@id": "software:other", + "@id": "software:Package", "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A package refers to any unit of content that can be associated with a distribution of software.\nTypically, a package is composed of one or more files. \nAny of the following non-limiting examples may be (but are not required to be) represented in SPDX as a package:\n\n - a tarball, zip file or other archive\n - a directory or sub-directory\n - a separately distributed piece of software which another Package or File uses or depends upon (e.g., a Python package, a Go module, ...)\n - a container image, and/or each image layer within a container image\n - a collection of one or more sub-packages\n - a Git repository snapshot from a particular point in time\n\nNote that some of these could be represented in SPDX as a file as well.\nExternal property restriction on /Core/Element/name: minCount: 1", + "rdfs:subClassOf": { + "@id": "software:SoftwareArtifact" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "sourceInfo", + "sh:path": { + "@id": "software:sourceInfo" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "packageUrl", + "sh:path": { + "@id": "software:packageUrl" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "downloadLocation", + "sh:path": { + "@id": "software:downloadLocation" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "packageVersion", + "sh:path": { + "@id": "software:packageVersion" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "homePage", + "sh:path": { + "@id": "software:homePage" + } + } ] }, { - "@id": "software:packagePurpose", + "@id": "core:creationInfo", "@type": "owl:DatatypeProperty", - "rdfs:comment": "PackagePurpose provides information about the primary purpose of the package.", + "rdfs:comment": "CreationInfo provides information about the creation of the Element.", "rdfs:range": { - "@id": "software:SoftwarePurpose" + "@id": "core:CreationInfo" }, "ns0:term_status": "Stable" }, { - "@id": "software:packageUrl", + "@id": "core:imports", "@type": "owl:DatatypeProperty", - "rdfs:comment": "A packageUrl is TODO", + "rdfs:comment": "Imports provides an ExternalMap of Element identifiers that are used within a document\nbut defined external to that document.", "rdfs:range": { - "@id": "xsd:anyURI" + "@id": "core:ExternalMap" }, "ns0:term_status": "Stable" }, { - "@id": "software:packageVersion", + "@id": "core:namespaces", "@type": "owl:DatatypeProperty", - "rdfs:comment": "A packageVersion is useful for identification purposes and for indicating later changes of the package version.", + "rdfs:comment": "This field provides a NamespaceMap applicable to an ElementCollection.", "rdfs:range": { - "@id": "xsd:string" + "@id": "core:NamespaceMap" }, "ns0:term_status": "Stable" }, { - "@id": "software:patch", - "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" - ] + "@id": "security:ExploitCatalogType", + "@type": "owl:Class", + "rdfs:comment": "ExploitCatalogType specifies the type of exploit catalog that a vulnerability is listed in.", + "ns0:term_status": "Stable" }, { - "@id": "software:snippetPurpose", + "@id": "security:severity", "@type": "owl:DatatypeProperty", - "rdfs:comment": "SnippetPurpose provides information about the primary purpose of the snippet.", + "rdfs:comment": "The severity field provides a human readable string, a label that can be used\nas an English adjective that qualifies its numerical score.", "rdfs:range": { - "@id": "software:SoftwarePurpose" + "@id": "xsd:string" }, "ns0:term_status": "Stable" }, { - "@id": "software:source", + "@id": "software:SoftwareArtifact", "@type": [ - "owl:NamedIndividual", - "software:SoftwarePurpose" + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A software artifact is a distinct article or unit related to software\nsuch as a package, a file, or a snippet.", + "rdfs:subClassOf": { + "@id": "core:Artifact" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "software:SoftwarePurpose" + }, + "sh:name": "purpose", + "sh:path": { + "@id": "software:purpose" + } + }, + { + "sh:datatype": { + "@id": "licensing:LicenseField" + }, + "sh:maxCount": 1, + "sh:name": "concludedLicense", + "sh:path": { + "@id": "software:concludedLicense" + } + }, + { + "sh:datatype": { + "@id": "licensing:LicenseField" + }, + "sh:maxCount": 1, + "sh:name": "declaredLicense", + "sh:path": { + "@id": "software:declaredLicense" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "contentIdentifier", + "sh:path": { + "@id": "software:contentIdentifier" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "copyrightText", + "sh:path": { + "@id": "software:copyrightText" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "attributionText", + "sh:path": { + "@id": "software:attributionText" + } + } ] }, { - "@id": "software:sourceInfo", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "SourceInfo records any relevant background information or additional comments\nabout the origin of the package. For example, this field might include comments \nindicating whether the package was pulled from a source code management system \nor has been repackaged. The creator can provide additional information to describe\nany anomalies or discoveries in the determination of the origin of the package.", - "rdfs:range": { - "@id": "xsd:string" - }, + "@id": "core:AnnotationType", + "@type": "owl:Class", + "rdfs:comment": "AnnotationType specifies the type of an annotation.", "ns0:term_status": "Stable" }, { "@id": "core:CreationInfo", - "@type": "owl:Class", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], "rdfs:comment": "The CreationInfo provides information about who created the Element, and when and how it was created. \n\nThe dateTime created is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.", - "ns0:term_status": "Stable" + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "comment", + "sh:path": { + "@id": "core:comment" + } + }, + { + "sh:datatype": { + "@id": "core:SemVer" + }, + "sh:name": "specVersion", + "sh:path": { + "@id": "core:specVersion" + } + }, + { + "sh:datatype": { + "@id": "core:Entity" + }, + "sh:minCount": 1, + "sh:name": "createdBy", + "sh:path": { + "@id": "core:createdBy" + } + }, + { + "sh:datatype": { + "@id": "core:ProfileIdentifierType" + }, + "sh:minCount": 1, + "sh:name": "profile", + "sh:path": { + "@id": "core:profile" + } + }, + { + "sh:datatype": { + "@id": "core:Tool" + }, + "sh:name": "createdUsing", + "sh:path": { + "@id": "core:createdUsing" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:name": "created", + "sh:path": { + "@id": "core:created" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:name": "dataLicense", + "sh:path": { + "@id": "core:dataLicense" + } + } + ] }, { - "@id": "core:ElementCollection", - "@type": "owl:Class", - "rdfs:comment": "An SpdxCollection is a collection of Elements, not necessarily with unifying context.", + "@id": "core:Entity", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "TODO", "rdfs:subClassOf": { "@id": "core:Element" }, "ns0:term_status": "Stable" }, - { - "@id": "core:ExternalIdentifier", - "@type": "owl:Class", - "rdfs:comment": "An ExternalIdentifier is a reference to a resource outside the scope of SPDX-3.0 content\nthat uniquely identifies an Element.", - "ns0:term_status": "Stable" - }, { "@id": "core:ExternalMap", - "@type": "owl:Class", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], "rdfs:comment": "An External Map is a map of Element identifiers that are used within a Document\nbut defined external to that Document.\nThe external map provides details about the externally-defined Element\nsuch as its provenance, where to retrieve it, and how to verify its integrity.", - "rdfs:subClassOf": { - "@id": "core:none" - }, - "ns0:term_status": "Stable" + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "externalId", + "sh:path": { + "@id": "core:externalId" + } + }, + { + "sh:datatype": { + "@id": "core:IntegrityMethod" + }, + "sh:name": "verifiedUsing", + "sh:path": { + "@id": "core:verifiedUsing" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "locationHint", + "sh:path": { + "@id": "core:locationHint" + } + } + ] }, { - "@id": "core:ExternalReference", - "@type": "owl:Class", - "rdfs:comment": "An External Reference points to a resource outside the scope of the SPDX-3.0 content\nthat provides additional characteristics of an Element.", + "@id": "core:IntegrityMethod", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An IntegrityMethod provides an independently reproducible mechanism that permits verification\nof a specific Element that correlates to the data in this SPDX document. This identifier enables\na recipient to determine if anything in the original Element has been changed and eliminates\nconfusion over which version or modification of a specific Element is referenced.", + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "comment", + "sh:path": { + "@id": "core:comment" + } + } + }, + { + "@id": "core:NamespaceMap", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A namespace map allows the creator of a collection of Elements to use\nshorter identifiers (\"prefixes\") instead of URIs to provide a more\nhuman-readable and smaller serialized representation of the Elements.", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "prefix", + "sh:path": { + "@id": "core:prefix" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:name": "namespace", + "sh:path": { + "@id": "core:namespace" + } + } + ] + }, + { + "@id": "core:PositiveIntegerRange", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "PositiveIntegerRange is a tuple of two positive integers that define a range.\n\"begin\" must be less than or equal to \"end\".", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:positiveInteger" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "end", + "sh:path": { + "@id": "core:end" + } + }, + { + "sh:datatype": { + "@id": "xsd:positiveInteger" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "begin", + "sh:path": { + "@id": "core:begin" + } + } + ] + }, + { + "@id": "licensing:LicenseAddition", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A LicenseAddition represents text which is intended to be added to a License\nas additional text, but which is not itself intended to be a standalone\nLicense.\n\nIt may be an exception which is listed on the SPDX Exceptions List\n(ListedLicenseException), or may be any other additional text (as an exception\nor otherwise) which is defined by an SPDX data creator (CustomLicenseAddition).", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "additionId", + "sh:path": { + "@id": "licensing:additionId" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "additionName", + "sh:path": { + "@id": "licensing:additionName" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "standardAdditionTemplate", + "sh:path": { + "@id": "licensing:standardAdditionTemplate" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "additionComment", + "sh:path": { + "@id": "licensing:additionComment" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:name": "seeAlso", + "sh:path": { + "@id": "licensing:seeAlso" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "additionText", + "sh:path": { + "@id": "licensing:additionText" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "obsoletedBy", + "sh:path": { + "@id": "licensing:obsoletedBy" + } + }, + { + "sh:datatype": { + "@id": "xsd:boolean" + }, + "sh:maxCount": 1, + "sh:name": "isDeprecatedAdditionId", + "sh:path": { + "@id": "licensing:isDeprecatedAdditionId" + } + } + ] + }, + { + "@id": "security:VexVulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "VexVulnAssessmentRelationship is an abstract subclass that defined the common\nproperties shared by all the SPDX-VEX status relationships. \n\n**Constraints**\n\nWhen linking elements using a VexVulnAssessmentRelationship, the following\nrequirements must be observed:\n\n- The from: end must be a /Security/Vulnerability classed element\n- The to: end must point to elements representing the VEX _products_. To\nspecify a different element where the vulnerability was detected, the VEX\nrelationship can optionally specify _subcomponents_ using the assessedElement\nproperty.\n\nVEX inherits information from the document level down to its statements. When a\nstatement is missing information it can be completed by reading the equivalent \nfield from the containing document. For example, if a VEX relationship is\nmissing data in its createdBy property, tools must consider the entity\nlisted in the CreationInfo section of the document as the VEX author.\nIn the same way, when a VEX relationship does not have a created property,\nthe document's date must be considered as authoritative.", "rdfs:subClassOf": { - "@id": "core:none" + "@id": "security:VulnAssessmentRelationship" }, - "ns0:term_status": "Stable" + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "statusNotes", + "sh:path": { + "@id": "security:statusNotes" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "vexVersion", + "sh:path": { + "@id": "security:vexVersion" + } + } + ] }, { "@id": "core:MediaType", - "@type": "owl:Class", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], "rdfs:comment": "The MediaType is a String constrained to the RFC 2046 specification. It provides a standardized\nway of indicating the type of content of an Element.\nA list of all possible media types is available at https://www.iana.org/assignments/media-types/media-types.xhtml.", "rdfs:subClassOf": { "@id": "xsd:string" @@ -1821,129 +4818,474 @@ "ns0:term_status": "Stable" }, { - "@id": "core:NamespaceMap", + "@id": "core:RelationshipCompleteness", "@type": "owl:Class", - "rdfs:comment": "A namespace map allows the creator of a collection of Elements to use\nshorter identifiers (\"prefixes\") instead of URIs to provide a more\nhuman-readable and smaller serialized representation of the Elements.", + "rdfs:comment": "RelationshipCompleteness indicates whether a relationship is complete or \nknown to be incomplete or if there is made no assertion either way.", "ns0:term_status": "Stable" }, { - "@id": "core:ProfileIdentifier", - "@type": "owl:Class", - "rdfs:comment": "A profile identifier provides the profile that the Element is specified in.", - "rdfs:subClassOf": { + "@id": "core:comment", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A comment is an optional field for creators of the Element to provide comments\nto the readers/reviewers of the document.", + "rdfs:range": { "@id": "xsd:string" }, "ns0:term_status": "Stable" }, { - "@id": "core:SemVer", - "@type": "owl:Class", - "rdfs:comment": "The semantic version is a String constrained to the SemVer 2.0.0 specification.", + "@id": "licensing:License", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A License represents a license text, whether listed on the SPDX License List\n(ListedLicense) or defined by an SPDX data creator (CustomLicense).", "rdfs:subClassOf": { - "@id": "xsd:string" + "@id": "licensing:AnyLicenseInfo" }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "standardLicenseTemplate", + "sh:path": { + "@id": "licensing:standardLicenseTemplate" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "licenseName", + "sh:path": { + "@id": "licensing:licenseName" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "obsoletedBy", + "sh:path": { + "@id": "licensing:obsoletedBy" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "licenseText", + "sh:path": { + "@id": "licensing:licenseText" + } + }, + { + "sh:datatype": { + "@id": "xsd:boolean" + }, + "sh:maxCount": 1, + "sh:name": "isDeprecatedLicenseId", + "sh:path": { + "@id": "licensing:isDeprecatedLicenseId" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:name": "seeAlso", + "sh:path": { + "@id": "licensing:seeAlso" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "licenseComment", + "sh:path": { + "@id": "licensing:licenseComment" + } + }, + { + "sh:datatype": { + "@id": "xsd:boolean" + }, + "sh:maxCount": 1, + "sh:name": "isOsiApproved", + "sh:path": { + "@id": "licensing:isOsiApproved" + } + }, + { + "sh:datatype": { + "@id": "xsd:boolean" + }, + "sh:maxCount": 1, + "sh:name": "isFsfLibre", + "sh:path": { + "@id": "licensing:isFsfLibre" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "licenseId", + "sh:path": { + "@id": "licensing:licenseId" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "standardLicenseHeader", + "sh:path": { + "@id": "licensing:standardLicenseHeader" + } + } + ] + }, + { + "@id": "licensing:LicenseField", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A LicenseField is the primary value that is used by a licensing field for a\nsoftware Package, File or Snippet. It represents either a license expression,\nor the values NOASSERTION or NONE. The specific meanings of NOASSERTION or\nNONE for the particular licensing field are defined in the corresponding\nproperty description.", "ns0:term_status": "Stable" }, { - "@id": "core:Tool", + "@id": "ai:SafetyRiskAssessmentType", "@type": "owl:Class", - "rdfs:comment": "A Tool is an element of hardware and/or software utilized to carry out a particular function.", + "rdfs:comment": "Lists the different safety risk type values that can be used to describe the safety risk of AI software\naccording to [Article 20 of Regulation 765/2008/EC](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).", + "ns0:term_status": "Stable" + }, + { + "@id": "core:Identity", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An Identity is a grouping of identifying characteristics unique to an individual or organization.", "rdfs:subClassOf": { "@id": "core:Entity" }, "ns0:term_status": "Stable" }, { - "@id": "core:Bundle", + "@id": "dataset:ConfidentialityLevelType", "@type": "owl:Class", - "rdfs:comment": "A bundle is a collection of Elements that have a shared context.", + "rdfs:comment": "Describes the different confidentiality levels as given by the [Traffic Light Protocol](https://en.wikipedia.org/wiki/Traffic_Light_Protocol).", + "ns0:term_status": "Stable" + }, + { + "@id": "security:SsvcDecisionType", + "@type": "owl:Class", + "rdfs:comment": "SsvcDecisionType specifies the type of decision that's been made according to the Stakeholder-Specific Vulnerability Categorization (SSVC) system [https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc](https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc)", + "ns0:term_status": "Stable" + }, + { + "@id": "security:VulnAssessmentRelationship", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "VulnAssessmentRelationship is the ancestor class common to all vulnerability\nassessment relationships. It factors out the common properties shared by them.", "rdfs:subClassOf": { - "@id": "core:ElementCollection" + "@id": "core:Relationship" }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "publishedTime", + "sh:path": { + "@id": "security:publishedTime" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "withdrawnTime", + "sh:path": { + "@id": "security:withdrawnTime" + } + }, + { + "sh:datatype": { + "@id": "core:Identity" + }, + "sh:maxCount": 1, + "sh:name": "suppliedBy", + "sh:path": { + "@id": "security:suppliedBy" + } + }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "modifiedTime", + "sh:path": { + "@id": "security:modifiedTime" + } + }, + { + "sh:datatype": { + "@id": "core:Element" + }, + "sh:maxCount": 1, + "sh:name": "assessedElement", + "sh:path": { + "@id": "security:assessedElement" + } + } + ] + }, + { + "@id": "software:SoftwareDependencyLinkType", + "@type": "owl:Class", + "rdfs:comment": "TODO", "ns0:term_status": "Stable" }, { - "@id": "core:IntegrityMethod", + "@id": "ai:PresenceType", "@type": "owl:Class", - "rdfs:comment": "An IntegrityMethod provides an independently reproducible mechanism that permits verification\nof a specific Element that correlates to the data in this SPDX document. This identifier enables\na recipient to determine if anything in the original Element has been changed and eliminates\nconfusion over which version or modification of a specific Element is referenced.", + "rdfs:comment": "This type is used to indicate if a given field is present or absent or unknown.", "ns0:term_status": "Stable" }, { - "@id": "core:Payload", + "@id": "dataset:DatasetAvailabilityType", "@type": "owl:Class", - "rdfs:comment": "TODO", - "rdfs:subClassOf": { - "@id": "core:none" - }, + "rdfs:comment": "Describes the possible types of availability of a dataset, indicating whether the dataset can be directly downloaded, can be assembled using a script for scraping the data, is only available after a clickthrough or a registration form.", "ns0:term_status": "Stable" }, { - "@id": "core:AnnotationType", + "@id": "security:VexJustificationType", "@type": "owl:Class", - "rdfs:comment": "AnnotationType specifies the type of an annotation.", + "rdfs:comment": "VexJustificationType specifies the type of Vulnerability Exploitability eXchange (VEX) justification.", "ns0:term_status": "Stable" }, { - "@id": "core:Entity", + "@id": "software:DependencyConditionalityType", "@type": "owl:Class", "rdfs:comment": "TODO", - "rdfs:subClassOf": { - "@id": "core:Element" - }, "ns0:term_status": "Stable" }, { - "@id": "core:Identity", + "@id": "core:LifecycleScopeType", "@type": "owl:Class", - "rdfs:comment": "An Identity is a grouping of identifying characteristics unique to an individual or organization.", + "rdfs:comment": "TODO", + "ns0:term_status": "Stable" + }, + { + "@id": "licensing:AnyLicenseInfo", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An AnyLicenseInfo is used by a licensing field for a software package,\nfile or snippet when its value is not NOASSERTION or NONE. It can be a\nsingle license (either on the SPDX License List or a custom-defined license);\na single license with an \"or later\" operator applied; the foregoing with\nadditional text applied; or a set of licenses combined by applying \"AND\" and\n\"OR\" operators recursively.", "rdfs:subClassOf": { - "@id": "core:Entity" + "@id": "licensing:LicenseField" }, "ns0:term_status": "Stable" }, { - "@id": "core:RelationshipCompleteness", + "@id": "software:SBOMType", "@type": "owl:Class", - "rdfs:comment": "RelationshipCompleteness indicates whether a relationship is complete or \nknown to be incomplete or if there is made no assertion either way.", + "rdfs:comment": "The set of SBOM types with definitions as defined in [Types of Software Bill of Material (SBOM) Documents](https://www.cisa.gov/sites/default/files/2023-04/sbom-types-document-508c.pdf), published on April 21, 2023. \nAn SBOM type describes the most likely type of an SBOM from the producer perspective, so that consumers can draw conclusions about the data inside an SBOM. A single SBOM can have multiple SBOM document types associated with it.", "ns0:term_status": "Stable" }, { - "@id": "ai:PresenceType", + "@id": "core:ExternalIdentifierType", "@type": "owl:Class", - "rdfs:comment": "This type is used to indicate if a given field is present or absent or unknown.", + "rdfs:comment": "ExteralIdentifierType specifies the type of an external identifier.", "ns0:term_status": "Stable" }, { - "@id": "ai:SafetyRiskAssessmentType", + "@id": "core:ProfileIdentifierType", "@type": "owl:Class", - "rdfs:comment": "Lists the different safety risk type values that can be used to describe the safety risk of AI software\naccording to [Article 20 of Regulation 765/2008/EC](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).", + "rdfs:comment": "There are a set of profiles that have been defined to be valid for a specific release This file enumerates the values that have been agreed on, and may be applied to the creation information for an an element.", "ns0:term_status": "Stable" }, { - "@id": "core:ExternalReferenceType", - "@type": "owl:Class", - "rdfs:comment": "ExteralReferenceType specifies the type of an external reference.", - "ns0:term_status": "Stable" + "@id": "core:DictionaryEntry", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "The class used for implementing a generic string mapping (also known as associative array, dictionary, or hash map) in SPDX. Each DictionaryEntry contains a key-value pair which maps the key to its associated value. To implement a dictionary, this class is to be used in a collection with unique keys.", + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "key", + "sh:path": { + "@id": "core:key" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "value", + "sh:path": { + "@id": "core:value" + } + } + ] }, { "@id": "core:Element", - "@type": "owl:Class", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], "rdfs:comment": "An Element is a representation of a fundamental concept either directly inherent\nto the Bill of Materials (BOM) domain or indirectly related to the BOM domain\nand necessary for contextually characterizing BOM concepts and relationships.\nWithin SPDX-3.0 structure this is the base class acting as a consistent,\nunifying, and interoperable foundation for all explicit\nand inter-relatable content objects.", "rdfs:subClassOf": { "@id": "core:Payload" }, - "ns0:term_status": "Stable" + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "spdxId", + "sh:path": { + "@id": "core:spdxId" + } + }, + { + "sh:datatype": { + "@id": "core:ExternalIdentifier" + }, + "sh:name": "externalIdentifier", + "sh:path": { + "@id": "core:externalIdentifier" + } + }, + { + "sh:datatype": { + "@id": "core:IntegrityMethod" + }, + "sh:name": "verifiedUsing", + "sh:path": { + "@id": "core:verifiedUsing" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "name", + "sh:path": { + "@id": "core:name" + } + }, + { + "sh:datatype": { + "@id": "core:Extension" + }, + "sh:name": "extension", + "sh:path": { + "@id": "core:extension" + } + }, + { + "sh:datatype": { + "@id": "core:ExternalReference" + }, + "sh:name": "externalReference", + "sh:path": { + "@id": "core:externalReference" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "summary", + "sh:path": { + "@id": "core:summary" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "description", + "sh:path": { + "@id": "core:description" + } + }, + { + "sh:datatype": { + "@id": "core:CreationInfo" + }, + "sh:maxCount": 1, + "sh:name": "creationInfo", + "sh:path": { + "@id": "core:creationInfo" + } + }, + { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "comment", + "sh:path": { + "@id": "core:comment" + } + } + ] }, { - "@id": "core:ExternalIdentifierType", + "@id": "core:ExternalReferenceType", "@type": "owl:Class", - "rdfs:comment": "ExteralIdentifierType specifies the type of an external identifier.", + "rdfs:comment": "ExteralReferenceType specifies the type of an external reference.", "ns0:term_status": "Stable" }, { - "@id": "core:HashAlgorithm", - "@type": "owl:Class", - "rdfs:comment": "A HashAlgorithm is a mathematical algorithm that maps data of arbitrary size to a bit string (the hash)\nand is a one-way function, that is, a function which is practically infeasible to invert.", + "@id": "core:DateTime", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Datetime is a string representation of a specific date and time.\nIt has resolution of seconds and is always expressed in UTC timezone.\nThe specific format is one of the most commonly used ISO-8601 formats.\nFormat restriction: pattern: ^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\dZ$", + "rdfs:subClassOf": { + "@id": "xsd:string" + }, "ns0:term_status": "Stable" }, { @@ -1952,6 +5294,12 @@ "rdfs:comment": "This field provides information about the primary purpose of an Element.\nSoftware Purpose is intrinsic to how the Element is being used rather than the content of the Element.\nThis field is a reasonable estimate of the most likely usage of the Element\nfrom the producer and consumer perspective from which both parties can draw conclusions\nabout the context in which the Element exists.", "ns0:term_status": "Stable" }, + { + "@id": "core:HashAlgorithm", + "@type": "owl:Class", + "rdfs:comment": "A HashAlgorithm is a mathematical algorithm that maps data of arbitrary size to a bit string (the hash)\nand is a one-way function, that is, a function which is practically infeasible to invert.", + "ns0:term_status": "Stable" + }, { "@id": "core:RelationshipType", "@type": "owl:Class", diff --git a/src/spdx_tools/spdx3/writer/json_ld/context.json b/src/spdx_tools/spdx3/writer/json_ld/context.json index 80dd583b4..064de1672 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/context.json +++ b/src/spdx_tools/spdx3/writer/json_ld/context.json @@ -2,40 +2,175 @@ "core": "https://spdx.org/rdf/Core/", "software": "https://spdx.org/rdf/Software/", "xsd": "http://www.w3.org/2001/XMLSchema/", + "AIPackage": "ai:AIPackage", + "Build": "build:Build", "Annotation": "core:Annotation", "AnonymousPayload": "core:AnonymousPayload", - "Hash": "core:Hash", "Organization": "core:Organization", "Person": "core:Person", - "Relationship": "core:Relationship", "SpdxDocument": "core:SpdxDocument", - "Tool": "core:Tool", + "Dataset": "dataset:Dataset", + "ConjunctiveLicenseSet": "licensing:ConjunctiveLicenseSet", + "CustomLicense": "licensing:CustomLicense", + "CustomLicenseAddition": "licensing:CustomLicenseAddition", + "DisjunctiveLicenseSet": "licensing:DisjunctiveLicenseSet", + "ListedLicense": "licensing:ListedLicense", + "ListedLicenseException": "licensing:ListedLicenseException", + "NoAssertionLicense": "licensing:NoAssertionLicense", + "NoneLicense": "licensing:NoneLicense", + "OrLaterOperator": "licensing:OrLaterOperator", + "WithAdditionOperator": "licensing:WithAdditionOperator", + "CvssV2VulnAssessmentRelationship": "security:CvssV2VulnAssessmentRelationship", + "CvssV3VulnAssessmentRelationship": "security:CvssV3VulnAssessmentRelationship", + "EpssVulnAssessmentRelationship": "security:EpssVulnAssessmentRelationship", + "ExploitCatalogVulnAssessmentRelationship": "security:ExploitCatalogVulnAssessmentRelationship", + "SsvcVulnAssessmentRelationship": "security:SsvcVulnAssessmentRelationship", + "VexAffectedVulnAssessmentRelationship": "security:VexAffectedVulnAssessmentRelationship", + "VexFixedVulnAssessmentRelationship": "security:VexFixedVulnAssessmentRelationship", + "VexNotAffectedVulnAssessmentRelationship": "security:VexNotAffectedVulnAssessmentRelationship", + "VexUnderInvestigationVulnAssessmentRelationship": "security:VexUnderInvestigationVulnAssessmentRelationship", + "Vulnerability": "security:Vulnerability", + "withdrawn": { + "@id": "security:withdrawn", + "@type": "core:DateTime" + }, "File": "software:File", - "Package": "software:Package", "Sbom": "software:Sbom", "Snippet": "software:Snippet", + "SoftwareDependencyRelationship": "software:SoftwareDependencyRelationship", + "autonomyType": { + "@id": "ai:autonomyType", + "@type": "ai:PresenceType" + }, + "domain": { + "@id": "ai:domain", + "@type": "xsd:string" + }, + "energyConsumption": { + "@id": "ai:energyConsumption", + "@type": "xsd:string" + }, + "hyperparameter": { + "@id": "ai:hyperparameter", + "@type": "core:DictionaryEntry" + }, + "informationAboutApplication": { + "@id": "ai:informationAboutApplication", + "@type": "xsd:string" + }, + "informationAboutTraining": { + "@id": "ai:informationAboutTraining", + "@type": "xsd:string" + }, + "limitation": { + "@id": "ai:limitation", + "@type": "xsd:string" + }, + "metric": { + "@id": "ai:metric", + "@type": "core:DictionaryEntry" + }, + "metricDecisionThreshold": { + "@id": "ai:metricDecisionThreshold", + "@type": "core:DictionaryEntry" + }, + "modelDataPreprocessing": { + "@id": "ai:modelDataPreprocessing", + "@type": "xsd:string" + }, + "modelExplainability": { + "@id": "ai:modelExplainability", + "@type": "xsd:string" + }, + "safetyRiskAssessment": { + "@id": "ai:safetyRiskAssessment", + "@type": "@vocab", + "@context": { + "@vocab": "ai:SafetyRiskAssessmentType/" + } + }, + "sensitivePersonalInformation": { + "@id": "dataset:sensitivePersonalInformation", + "@type": "@vocab", + "@context": { + "@vocab": "dataset:PresenceType/" + } + }, + "standardCompliance": { + "@id": "ai:standardCompliance", + "@type": "xsd:string" + }, + "typeOfModel": { + "@id": "ai:typeOfModel", + "@type": "xsd:string" + }, + "buildEndTime": { + "@id": "build:buildEndTime", + "@type": "core:DateTime" + }, + "buildId": { + "@id": "build:buildId", + "@type": "xsd:string" + }, + "buildStartTime": { + "@id": "build:buildStartTime", + "@type": "core:DateTime" + }, + "buildType": { + "@id": "build:buildType", + "@type": "xsd:anyURI" + }, + "configSourceDigest": { + "@id": "build:configSourceDigest", + "@type": "core:Hash" + }, + "configSourceEntrypoint": { + "@id": "build:configSourceEntrypoint", + "@type": "xsd:string" + }, + "configSourceUri": { + "@id": "build:configSourceUri", + "@type": "xsd:anyURI" + }, + "environment": { + "@id": "build:environment", + "@type": "core:DictionaryEntry" + }, + "parameters": { + "@id": "build:parameters", + "@type": "core:DictionaryEntry" + }, + "Artifact": "core:Artifact", "Bom": "core:Bom", "ElementCollection": "core:ElementCollection", - "ExternalIdentifier": "core:ExternalIdentifier", + "LifecycleScopedRelationship": "core:LifecycleScopedRelationship", "algorithm": { "@id": "core:algorithm", "@type": "@vocab", "@context": { - "@vocab": "core:HashAlgorithm#" + "@vocab": "core:HashAlgorithm/" } }, "annotationType": { "@id": "core:annotationType", "@type": "@vocab", "@context": { - "@vocab": "core:AnnotationType#" + "@vocab": "core:AnnotationType/" } }, + "begin": { + "@id": "core:begin", + "@type": "xsd:positiveInteger" + }, + "builtTime": { + "@id": "core:builtTime", + "@type": "core:DateTime" + }, "completeness": { "@id": "core:completeness", "@type": "@vocab", "@context": { - "@vocab": "core:RelationshipCompleteness#" + "@vocab": "core:RelationshipCompleteness/" } }, "context": { @@ -44,12 +179,16 @@ }, "created": { "@id": "core:created", - "@type": "xsd:dateTime" + "@type": "core:DateTime" }, "createdBy": { "@id": "core:createdBy", "@type": "core:Entity" }, + "createdUsing": { + "@id": "core:createdUsing", + "@type": "core:Tool" + }, "dataLicense": { "@id": "core:dataLicense", "@type": "xsd:string" @@ -62,25 +201,40 @@ "@id": "core:element", "@type": "core:Element" }, + "end": { + "@id": "core:end", + "@type": "xsd:positiveInteger" + }, + "endTime": { + "@id": "core:endTime", + "@type": "core:DateTime" + }, "externalId": { "@id": "core:externalId", "@type": "xsd:anyURI" }, "externalIdentifier": { "@id": "core:externalIdentifier", - "@type": "core:ExternaIdentifier" + "@type": "core:ExternalIdentifier" }, - "externalReferenceType": { - "@id": "core:externalReferenceType", + "externalIdentifierType": { + "@id": "core:externalIdentifierType", "@type": "@vocab", "@context": { - "@vocab": "core:ExternalReferenceType#" + "@vocab": "core:ExternalIdentifierType/" } }, "externalReference": { "@id": "core:externalReference", "@type": "core:ExternalReference" }, + "externalReferenceType": { + "@id": "core:externalReferenceType", + "@type": "@vocab", + "@context": { + "@vocab": "core:ExternalReferenceType/" + } + }, "from": { "@id": "core:from", "@type": "core:Element" @@ -89,6 +243,22 @@ "@id": "core:hashValue", "@type": "xsd:string" }, + "identifier": { + "@id": "core:identifier", + "@type": "xsd:string" + }, + "identifierLocator": { + "@id": "core:identifierLocator", + "@type": "xsd:anyURI" + }, + "issuingAuthority": { + "@id": "core:issuingAuthority", + "@type": "xsd:anyURI" + }, + "key": { + "@id": "core:key", + "@type": "xsd:string" + }, "locationHint": { "@id": "core:locationHint", "@type": "xsd:anyURI" @@ -111,19 +281,33 @@ }, "profile": { "@id": "core:profile", - "@type": "core:ProfileIdentifier" + "@type": "@vocab", + "@context": { + "@vocab": "core:ProfileIdentifierType/" + } }, "relationshipType": { "@id": "core:relationshipType", "@type": "@vocab", "@context": { - "@vocab": "core:RelationshipType#" + "@vocab": "core:RelationshipType/" } }, + "releaseTime": { + "@id": "core:releaseTime", + "@type": "core:DateTime" + }, "rootElement": { "@id": "core:rootElement", "@type": "core:Element" }, + "scope": { + "@id": "core:scope", + "@type": "@vocab", + "@context": { + "@vocab": "core:LifecycleScopeType/" + } + }, "spdxId": { "@id": "core:spdxId", "@type": "xsd:anyURI" @@ -132,6 +316,14 @@ "@id": "core:specVersion", "@type": "core:SemVer" }, + "standard": { + "@id": "core:standard", + "@type": "xsd:string" + }, + "startTime": { + "@id": "core:startTime", + "@type": "core:DateTime" + }, "statement": { "@id": "core:statement", "@type": "xsd:string" @@ -144,60 +336,262 @@ "@id": "core:summary", "@type": "xsd:string" }, + "suppliedBy": { + "@id": "core:suppliedBy", + "@type": "core:Agent" + }, "to": { "@id": "core:to", "@type": "core:Element" }, + "validUntilTime": { + "@id": "core:validUntilTime", + "@type": "core:DateTime" + }, + "value": { + "@id": "core:value", + "@type": "xsd:string" + }, + "anonymizationMethodUsed": { + "@id": "dataset:anonymizationMethodUsed", + "@type": "xsd:string" + }, + "confidentialityLevel": { + "@id": "dataset:confidentialityLevel", + "@type": "@vocab", + "@context": { + "@vocab": "dataset:ConfidentialityLevelType/" + } + }, + "dataCollectionProcess": { + "@id": "dataset:dataCollectionProcess", + "@type": "xsd:string" + }, + "dataPreprocessing": { + "@id": "dataset:dataPreprocessing", + "@type": "xsd:string" + }, + "datasetAvailability": { + "@id": "dataset:datasetAvailability", + "@type": "@vocab", + "@context": { + "@vocab": "dataset:DatasetAvailabilityType/" + } + }, + "datasetNoise": { + "@id": "dataset:datasetNoise", + "@type": "xsd:string" + }, + "datasetSize": { + "@id": "dataset:datasetSize", + "@type": "xsd:nonNegativeInteger" + }, + "datasetType": { + "@id": "dataset:datasetType", + "@type": "xsd:string" + }, + "datasetUpdateMechanism": { + "@id": "dataset:datasetUpdateMechanism", + "@type": "xsd:string" + }, + "intendedUse": { + "@id": "dataset:intendedUse", + "@type": "xsd:string" + }, + "knownBias": { + "@id": "dataset:knownBias", + "@type": "xsd:string" + }, + "sensor": { + "@id": "dataset:sensor", + "@type": "core:DictionaryEntry" + }, + "additionComment": { + "@id": "licensing:additionComment", + "@type": "xsd:string" + }, + "additionId": { + "@id": "licensing:additionId", + "@type": "xsd:string" + }, + "additionName": { + "@id": "licensing:additionName", + "@type": "xsd:string" + }, + "additionText": { + "@id": "licensing:additionText", + "@type": "xsd:string" + }, + "isDeprecatedAdditionId": { + "@id": "licensing:isDeprecatedAdditionId", + "@type": "xsd:boolean" + }, + "isDeprecatedLicenseId": { + "@id": "licensing:isDeprecatedLicenseId", + "@type": "xsd:boolean" + }, + "isFsfLibre": { + "@id": "licensing:isFsfLibre", + "@type": "xsd:boolean" + }, + "isOsiApproved": { + "@id": "licensing:isOsiApproved", + "@type": "xsd:boolean" + }, + "licenseComment": { + "@id": "licensing:licenseComment", + "@type": "xsd:string" + }, + "licenseId": { + "@id": "licensing:licenseId", + "@type": "xsd:string" + }, + "licenseName": { + "@id": "licensing:licenseName", + "@type": "xsd:string" + }, + "licenseText": { + "@id": "licensing:licenseText", + "@type": "xsd:string" + }, + "standardAdditionTemplate": { + "@id": "licensing:standardAdditionTemplate", + "@type": "xsd:string" + }, + "standardLicenseHeader": { + "@id": "licensing:standardLicenseHeader", + "@type": "xsd:string" + }, + "standardLicenseTemplate": { + "@id": "licensing:standardLicenseTemplate", + "@type": "xsd:string" + }, + "subjectAddition": { + "@id": "licensing:subjectAddition", + "@type": "licensing:LicenseAddition" + }, + "actionStatement": { + "@id": "security:actionStatement", + "@type": "xsd:string" + }, + "assessedElement": { + "@id": "security:assessedElement", + "@type": "core:Element" + }, + "decisionType": { + "@id": "security:decisionType", + "@type": "@vocab", + "@context": { + "@vocab": "security:SsvcDecisionType/" + } + }, + "exploited": { + "@id": "security:exploited", + "@type": "xsd:boolean" + }, + "impactStatement": { + "@id": "security:impactStatement", + "@type": "xsd:string" + }, + "justificationType": { + "@id": "security:justificationType", + "@type": "@vocab", + "@context": { + "@vocab": "security:VexJustificationType/" + } + }, + "probability": { + "@id": "security:probability", + "@type": "xsd:decimal" + }, + "attributionText": { + "@id": "software:attributionText", + "@type": "xsd:string" + }, "byteRange": { "@id": "software:byteRange", - "@type": "software:positiveIntegerRange" + "@type": "core:PositiveIntegerRange" + }, + "concludedLicense": { + "@id": "software:concludedLicense", + "@type": "software:LicenseField" + }, + "conditionality": { + "@id": "software:conditionality", + "@type": "@vocab", + "@context": { + "@vocab": "software:DependencyConditionalityType/" + } + }, + "contentIdentifier": { + "@id": "software:contentIdentifier", + "@type": "xsd:anyURI" }, "contentType": { "@id": "core:contentType", "@type": "core:MediaType" }, + "copyrightText": { + "@id": "software:copyrightText", + "@type": "xsd:string" + }, + "declaredLicense": { + "@id": "software:declaredLicense", + "@type": "software:LicenseField" + }, "downloadLocation": { "@id": "software:downloadLocation", "@type": "xsd:anyURI" }, - "filePurpose": { - "@id": "software:filePurpose", - "@type": "@vocab", - "@context": { - "@vocab": "software:SoftwarePurpose#" - } - }, "homePage": { "@id": "software:homePage", "@type": "xsd:anyURI" }, "lineRange": { "@id": "software:lineRange", - "@type": "software:positiveIntegerRange" + "@type": "core:PositiveIntegerRange" + }, + "packageUrl": { + "@id": "software:packageUrl", + "@type": "xsd:anyURI" }, - "packagePurpose": { - "@id": "software:packagePurpose", + "packageVersion": { + "@id": "software:packageVersion", + "@type": "xsd:string" + }, + "purpose": { + "@id": "software:purpose", "@type": "@vocab", "@context": { - "@vocab": "software:SoftwarePurpose#" + "@vocab": "software:SoftwarePurpose/" } }, - "packageUrl": { - "@id": "software:packageUrl", - "@type": "xsd:anyURI" + "sbomType": { + "@id": "software:sbomType", + "@type": "@vocab", + "@context": { + "@vocab": "software:SBOMType/" + } }, - "snippetPurpose": { - "@id": "software:snippetPurpose", + "softwareLinkage": { + "@id": "software:softwareLinkage", "@type": "@vocab", "@context": { - "@vocab": "software:SoftwarePurpose#" + "@vocab": "software:SoftwareDependencyLinkType/" } }, + "sourceInfo": { + "@id": "software:sourceInfo", + "@type": "xsd:string" + }, "Bundle": "core:Bundle", + "ExternalIdentifier": "core:ExternalIdentifier", "ExternalReference": "core:ExternalReference", + "Hash": "core:Hash", "Payload": "core:Payload", - "ProfileIdentifier": "core:ProfileIdentifier", + "Relationship": "core:Relationship", "SemVer": "core:SemVer", + "Tool": "core:Tool", "name": { "@id": "core:name", "@type": "xsd:string" @@ -206,11 +600,50 @@ "@id": "core:verifiedUsing", "@type": "core:IntegrityMethod" }, - "Artifact": "core:Artifact", - "MediaType": "core:MediaType", + "deprecatedVersion": { + "@id": "licensing:deprecatedVersion", + "@type": "xsd:string" + }, + "listVersionAdded": { + "@id": "licensing:listVersionAdded", + "@type": "xsd:string" + }, + "member": { + "@id": "licensing:member", + "@type": "licensing:AnyLicenseInfo" + }, + "obsoletedBy": { + "@id": "licensing:obsoletedBy", + "@type": "xsd:string" + }, + "seeAlso": { + "@id": "licensing:seeAlso", + "@type": "xsd:anyURI" + }, + "subjectLicense": { + "@id": "licensing:subjectLicense", + "@type": "licensing:License" + }, + "modifiedTime": { + "@id": "security:modifiedTime", + "@type": "core:DateTime" + }, + "publishedTime": { + "@id": "security:publishedTime", + "@type": "core:DateTime" + }, + "score": { + "@id": "security:score", + "@type": "xsd:string" + }, + "vector": { + "@id": "security:vector", + "@type": "xsd:string" + }, + "Package": "software:Package", "creationInfo": { "@id": "core:creationInfo", - "@type": "core:CreationInformation" + "@type": "core:CreationInfo" }, "imports": { "@id": "core:imports", @@ -220,19 +653,49 @@ "@id": "core:namespaces", "@type": "core:NamespaceMap" }, - "contentIdentifier": { - "@id": "software:contentIdentifier", - "@type": "xsd:anyURI" + "ExploitCatalogType": "security:ExploitCatalogType", + "severity": { + "@id": "security:severity", + "@type": "xsd:string" }, - "CreationInformation": "core:CreationInformation", + "SoftwareArtifact": "software:SoftwareArtifact", + "AnnotationType": "core:AnnotationType", + "CreationInfo": "core:CreationInfo", "Entity": "core:Entity", "ExternalMap": "core:ExternalMap", - "Identity": "core:Identity", "IntegrityMethod": "core:IntegrityMethod", "NamespaceMap": "core:NamespaceMap", + "PositiveIntegerRange": "core:PositiveIntegerRange", + "LicenseAddition": "licensing:LicenseAddition", + "VexVulnAssessmentRelationship": "security:VexVulnAssessmentRelationship", + "MediaType": "core:MediaType", + "RelationshipCompleteness": "core:RelationshipCompleteness", "comment": { "@id": "core:comment", "@type": "xsd:string" }, - "Element": "core:Element" + "License": "licensing:License", + "LicenseField": "licensing:LicenseField", + "SafetyRiskAssessmentType": "ai:SafetyRiskAssessmentType", + "Identity": "core:Identity", + "ConfidentialityLevelType": "dataset:ConfidentialityLevelType", + "SsvcDecisionType": "security:SsvcDecisionType", + "VulnAssessmentRelationship": "security:VulnAssessmentRelationship", + "SoftwareDependencyLinkType": "software:SoftwareDependencyLinkType", + "PresenceType": "ai:PresenceType", + "DatasetAvailabilityType": "dataset:DatasetAvailabilityType", + "VexJustificationType": "security:VexJustificationType", + "DependencyConditionalityType": "software:DependencyConditionalityType", + "LifecycleScopeType": "core:LifecycleScopeType", + "AnyLicenseInfo": "licensing:AnyLicenseInfo", + "SBOMType": "software:SBOMType", + "ExternalIdentifierType": "core:ExternalIdentifierType", + "ProfileIdentifierType": "core:ProfileIdentifierType", + "DictionaryEntry": "core:DictionaryEntry", + "Element": "core:Element", + "ExternalReferenceType": "core:ExternalReferenceType", + "DateTime": "core:DateTime", + "SoftwarePurpose": "software:SoftwarePurpose", + "HashAlgorithm": "core:HashAlgorithm", + "RelationshipType": "core:RelationshipType" } diff --git a/src/spdx_tools/spdx3/writer/json_ld/model.ttl b/src/spdx_tools/spdx3/writer/json_ld/model.ttl index 03358cabb..b703f22f5 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/model.ttl +++ b/src/spdx_tools/spdx3/writer/json_ld/model.ttl @@ -1,34 +1,56 @@ -@prefix ai: . -@prefix build: . -@prefix core: . -@prefix dataset: . +@prefix ai: . +@prefix build: . +@prefix core: . +@prefix dataset: . +@prefix licensing: . @prefix ns0: . @prefix owl: . @prefix rdfs: . +@prefix security: . @prefix sh: . -@prefix software: . +@prefix software: . @prefix xsd: . ai:AIPackage a owl:Class, sh:NodeShape ; - rdfs:comment "Metadata information that can be added to a package to describe an AI application or trained AI model." ; - rdfs:subClassOf ; + rdfs:comment """Metadata information that can be added to a package to describe an AI application or trained AI model. +External property restriction on /Core/Artifact/suppliedBy: minCount: 1 +External property restriction on /Software/Package/downloadLocation: minCount: 1 +External property restriction on /Software/Package/packageVersion: minCount: 1 +External property restriction on /Software/SoftwareArtifact/purpose: minCount: 1 +External property restriction on /Core/Relationship/relationshipType: minCount: 1 +External property restriction on /Core/Artifact/releaseTime: minCount: 1""" ; + rdfs:subClassOf software:Package ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; - sh:name "standardsCompliance" ; - sh:path ai:standardsCompliance ], - [ sh:datatype xsd:string ; + sh:property [ sh:datatype ai:PresenceType ; sh:maxCount 1 ; - sh:name "dataPreprocessingSteps" ; - sh:path ai:dataPreprocessingSteps ], + sh:name "sensitivePersonalInformation" ; + sh:path ai:sensitivePersonalInformation ], + [ sh:datatype core:DictionaryEntry ; + sh:name "metricDecisionThreshold" ; + sh:path ai:metricDecisionThreshold ], [ sh:datatype xsd:string ; + sh:name "modelExplainability" ; + sh:path ai:modelExplainability ], + [ sh:datatype core:DictionaryEntry ; + sh:name "metric" ; + sh:path ai:metric ], + [ sh:datatype xsd:string ; + sh:name "standardCompliance" ; + sh:path ai:standardCompliance ], + [ sh:datatype xsd:string ; + sh:name "domain" ; + sh:path ai:domain ], + [ sh:datatype ai:SafetyRiskAssessmentType ; sh:maxCount 1 ; - sh:name "limitations" ; - sh:path ai:limitations ], - [ sh:datatype ai:PresenceType ; - sh:maxCount 1 ; - sh:name "autonomyType" ; - sh:path ai:autonomyType ], + sh:name "safetyRiskAssessment" ; + sh:path ai:safetyRiskAssessment ], + [ sh:datatype core:DictionaryEntry ; + sh:name "hyperparameter" ; + sh:path ai:hyperparameter ], + [ sh:datatype xsd:string ; + sh:name "typeOfModel" ; + sh:path ai:typeOfModel ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "energyConsumption" ; @@ -37,37 +59,21 @@ ai:AIPackage a owl:Class, sh:maxCount 1 ; sh:name "informationAboutApplication" ; sh:path ai:informationAboutApplication ], - [ sh:datatype ; - sh:name "metrics" ; - sh:path ai:metrics ], + [ sh:datatype xsd:string ; + sh:name "modelDataPreprocessing" ; + sh:path ai:modelDataPreprocessing ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "modelExplainabilityMechanisms" ; - sh:path ai:modelExplainabilityMechanisms ], + sh:name "informationAboutTraining" ; + sh:path ai:informationAboutTraining ], [ sh:datatype ai:PresenceType ; sh:maxCount 1 ; - sh:name "sensitivePersonalInformation" ; - sh:path ai:sensitivePersonalInformation ], - [ sh:datatype xsd:string ; - sh:name "typeOfModel" ; - sh:path ai:typeOfModel ], - [ sh:datatype ; - sh:name "metricsDecisionThresholds" ; - sh:path ai:metricsDecisionThresholds ], - [ sh:datatype xsd:string ; - sh:name "domain" ; - sh:path ai:domain ], - [ sh:datatype ; - sh:name "hyperparameters" ; - sh:path ai:hyperparameters ], - [ sh:datatype ai:SafetyRiskAssessmentType ; - sh:maxCount 1 ; - sh:name "safetyRiskAssessment" ; - sh:path ai:safetyRiskAssessment ], + sh:name "autonomyType" ; + sh:path ai:autonomyType ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "informationAboutTraining" ; - sh:path ai:informationAboutTraining ] . + sh:name "limitation" ; + sh:path ai:limitation ] . ai:high a owl:NamedIndividual, ai:SafetyRiskAssessmentType . @@ -78,16 +84,10 @@ ai:low a owl:NamedIndividual, ai:medium a owl:NamedIndividual, ai:SafetyRiskAssessmentType . -ai:modelDataPreprocessingSteps a owl:DatatypeProperty ; - rdfs:comment """ModelDataPreprocessingSteps is a free form text that describes the preprocessing steps -applied to the training data before training of the model(s) contained in the AI software.""" ; - rdfs:range xsd:string ; - ns0:term_status "Stable" . - ai:no a owl:NamedIndividual, ai:PresenceType . -ai:noassertion a owl:NamedIndividual, +ai:noAssertion a owl:NamedIndividual, ai:PresenceType . ai:serious a owl:NamedIndividual, @@ -107,55 +107,47 @@ those defined in [SLSA provenance](https://slsa.dev/provenance/v0.2). ExternalIdentifier of type "urlScheme" may be used to identify build logs. In this case, the comment of the ExternalIdentifier should be "LogReference". Note that buildStart and buildEnd are optional, and may be omitted to simplify creating reproducible builds.""" ; - rdfs:subClassOf ; + rdfs:subClassOf core:Element ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; + sh:property [ sh:datatype core:DateTime ; sh:maxCount 1 ; - sh:name "buildId" ; - sh:path build:buildId ], - [ sh:datatype xsd:dateTime ; + sh:name "buildStartTime" ; + sh:path build:buildStartTime ], + [ sh:datatype core:DateTime ; sh:maxCount 1 ; - sh:name "buildEnd" ; - sh:path build:buildEnd ], - [ sh:datatype ; + sh:name "buildEndTime" ; + sh:path build:buildEndTime ], + [ sh:datatype core:DictionaryEntry ; sh:name "parameters" ; sh:path build:parameters ], [ sh:datatype xsd:anyURI ; sh:name "configSourceUri" ; sh:path build:configSourceUri ], - [ sh:datatype xsd:string ; - sh:name "configSourceEntrypoint" ; - sh:path build:configSourceEntrypoint ], - [ sh:datatype ; - sh:name "environment" ; - sh:path build:environment ], - [ sh:datatype ; - sh:name "configSourceDigest" ; - sh:path build:configSourceDigest ], [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "buildType" ; sh:path build:buildType ], - [ sh:datatype xsd:dateTime ; + [ sh:datatype core:DictionaryEntry ; + sh:name "environment" ; + sh:path build:environment ], + [ sh:datatype xsd:string ; + sh:name "configSourceEntrypoint" ; + sh:path build:configSourceEntrypoint ], + [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "buildStart" ; - sh:path build:buildStart ] . + sh:name "buildId" ; + sh:path build:buildId ], + [ sh:datatype core:Hash ; + sh:name "configSourceDigest" ; + sh:path build:configSourceDigest ] . core:Annotation a owl:Class, sh:NodeShape ; rdfs:comment "An Annotation is an assertion made in relation to one or more elements." ; rdfs:subClassOf core:Element ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:MediaType ; - sh:name "contentType" ; - sh:path core:contentType ], - [ sh:datatype core:AnnotationType ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "annotationType" ; - sh:path core:annotationType ], - [ sh:datatype core:Element ; + sh:property [ sh:datatype core:Element ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "subject" ; @@ -163,7 +155,15 @@ core:Annotation a owl:Class, [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "statement" ; - sh:path core:statement ] . + sh:path core:statement ], + [ sh:datatype core:MediaType ; + sh:name "contentType" ; + sh:path core:contentType ], + [ sh:datatype core:AnnotationType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "annotationType" ; + sh:path core:annotationType ] . core:AnonymousPayload a owl:Class, sh:NodeShape ; @@ -181,73 +181,6 @@ core:AnonymousPayload a owl:Class, sh:name "namespaces" ; sh:path core:namespaces ] . -core:Artifact a owl:Class, - sh:NodeShape ; - rdfs:comment """An artifact is a distinct article or unit within the digital domain, -such as an electronic file, a software package, a device or an element of data.""" ; - rdfs:subClassOf core:Element ; - ns0:term_status "Stable" ; - sh:property [ sh:datatype core:Identity ; - sh:name "originatedBy" ; - sh:path core:originatedBy ], - [ sh:datatype xsd:dateTime ; - sh:maxCount 1 ; - sh:name "builtTime" ; - sh:path core:builtTime ], - [ sh:datatype xsd:dateTime ; - sh:maxCount 1 ; - sh:name "validUntilTime" ; - sh:path core:validUntilTime ], - [ sh:datatype xsd:dateTime ; - sh:maxCount 1 ; - sh:name "releaseTime" ; - sh:path core:releaseTime ] . - -core:Bom a owl:Class, - sh:NodeShape ; - rdfs:comment """A Bill Of Materials (BOM) is a container for a grouping of SPDX-3.0 content -characterizing details about a product. -This could include details of the content and composition of the product, -provenence details of the product and/or -its composition, licensing information, known quality or security issues, etc.""" ; - rdfs:subClassOf core:Bundle ; - ns0:term_status "Stable" . - -core:DictionaryEntry a owl:Class, - sh:NodeShape ; - rdfs:comment "The class used for implementing a generic string mapping (also known as associative array, dictionary, or hash map) in SPDX. Each DictionaryEntry contains a key-value pair which maps the key to its associated value. To implement a dictionary, this class is to be used in a collection with unique keys." ; - ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "key" ; - sh:path core:key ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "value" ; - sh:path core:value ] . - -core:Hash a owl:Class, - sh:NodeShape ; - rdfs:comment """A hash is a grouping of characteristics unique to the result -of applying a mathematical algorithm -that maps data of arbitrary size to a bit string (the hash) -and is a one-way function, that is, -a function which is practically infeasible to invert. -This is commonly used for integrity checking of data.""" ; - rdfs:subClassOf core:IntegrityMethod ; - ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "hashValue" ; - sh:path core:hashValue ], - [ sh:datatype core:HashAlgorithm ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "algorithm" ; - sh:path core:algorithm ] . - core:Organization a owl:Class, sh:NodeShape ; rdfs:comment "An Organization is a group of people who work together in an organized way for a shared purpose." ; @@ -260,51 +193,11 @@ core:Person a owl:Class, rdfs:subClassOf core:Identity ; ns0:term_status "Stable" . -core:PositiveIntegerRange a owl:Class, - sh:NodeShape ; - rdfs:comment """PositiveIntegerRange is a tuple of two positive integers that define a range. -"begin" must be less than or equal to "end".""" ; - rdfs:subClassOf core:none ; - ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:positiveInteger ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "begin" ; - sh:path core:begin ], - [ sh:datatype xsd:positiveInteger ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "end" ; - sh:path core:end ] . - -core:Relationship a owl:Class, - sh:NodeShape ; - rdfs:comment """A Relationship is a grouping of characteristics unique to an assertion -that one Element is related to one or more other Elements in some way.""" ; - rdfs:subClassOf core:Element ; - ns0:term_status "Stable" ; - sh:property [ sh:datatype core:Element ; - sh:minCount 1 ; - sh:name "to" ; - sh:path core:to ], - [ sh:datatype core:Element ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "from" ; - sh:path core:from ], - [ sh:datatype core:RelationshipCompleteness ; - sh:maxCount 1 ; - sh:name "completeness" ; - sh:path core:completeness ], - [ sh:datatype core:RelationshipType ; - sh:maxCount 1 ; - sh:name "relationshipType" ; - sh:path core:relationshipType ] . - core:SpdxDocument a owl:Class, sh:NodeShape ; rdfs:comment """An SpdxDocument assembles a collection of Elements under a common string, the name of the document. -Commonly used when representing a unit of transfer of SPDX Elements.""" ; +Commonly used when representing a unit of transfer of SPDX Elements. +External property restriction on /Core/Element/name: minCount: 1""" ; rdfs:subClassOf core:Bundle ; ns0:term_status "Stable" ; sh:property [ sh:datatype xsd:string ; @@ -313,6 +206,12 @@ Commonly used when representing a unit of transfer of SPDX Elements.""" ; sh:name "name" ; sh:path core:name ] . +core:affects a owl:NamedIndividual, + core:RelationshipType . + +core:ai a owl:NamedIndividual, + core:ProfileIdentifierType . + core:altDownloadLocation a owl:NamedIndividual, core:ExternalReferenceType . @@ -325,6 +224,12 @@ core:amends a owl:NamedIndividual, core:ancestor a owl:NamedIndividual, core:RelationshipType . +core:availableFrom a owl:NamedIndividual, + core:RelationshipType . + +core:binaryArtifact a owl:NamedIndividual, + core:ExternalReferenceType . + core:blake2b256 a owl:NamedIndividual, core:HashAlgorithm . @@ -337,6 +242,10 @@ core:blake2b512 a owl:NamedIndividual, core:blake3 a owl:NamedIndividual, core:HashAlgorithm . +core:build a owl:NamedIndividual, + core:LifecycleScopeType, + core:ProfileIdentifierType . + core:buildConfigOf a owl:NamedIndividual, core:RelationshipType . @@ -352,33 +261,57 @@ core:buildInputOf a owl:NamedIndividual, core:buildInvokedBy a owl:NamedIndividual, core:RelationshipType . +core:buildMeta a owl:NamedIndividual, + core:ExternalReferenceType . + core:buildOnBehalfOf a owl:NamedIndividual, core:RelationshipType . core:buildOutputOf a owl:NamedIndividual, core:RelationshipType . +core:buildSystem a owl:NamedIndividual, + core:ExternalReferenceType . + core:buildTool a owl:NamedIndividual, core:RelationshipType . +core:chat a owl:NamedIndividual, + core:ExternalReferenceType . + core:complete a owl:NamedIndividual, core:RelationshipCompleteness . core:contains a owl:NamedIndividual, core:RelationshipType . +core:coordinatedBy a owl:NamedIndividual, + core:RelationshipType . + core:copy a owl:NamedIndividual, core:RelationshipType . +core:core a owl:NamedIndividual, + core:ProfileIdentifierType . + core:cpe22 a owl:NamedIndividual, core:ExternalIdentifierType . core:cpe23 a owl:NamedIndividual, core:ExternalIdentifierType . +core:crystalsDilithium a owl:NamedIndividual, + core:HashAlgorithm . + +core:crystalsKyber a owl:NamedIndividual, + core:HashAlgorithm . + core:dataFile a owl:NamedIndividual, core:RelationshipType . +core:dataset a owl:NamedIndividual, + core:ProfileIdentifierType . + core:dependencyManifest a owl:NamedIndividual, core:RelationshipType . @@ -391,16 +324,26 @@ core:descendant a owl:NamedIndividual, core:describes a owl:NamedIndividual, core:RelationshipType . +core:design a owl:NamedIndividual, + core:LifecycleScopeType . + core:devDependency a owl:NamedIndividual, core:RelationshipType . core:devTool a owl:NamedIndividual, core:RelationshipType . +core:development a owl:NamedIndividual, + core:LifecycleScopeType . + core:distributionArtifact a owl:NamedIndividual, core:RelationshipType . core:documentation a owl:NamedIndividual, + core:ExternalReferenceType, + core:RelationshipType . + +core:doesNotAffect a owl:NamedIndividual, core:RelationshipType . core:dynamicLink a owl:NamedIndividual, @@ -415,6 +358,12 @@ core:example a owl:NamedIndividual, core:expandedFromArchive a owl:NamedIndividual, core:RelationshipType . +core:exploitCreatedBy a owl:NamedIndividual, + core:RelationshipType . + +core:falcon a owl:NamedIndividual, + core:HashAlgorithm . + core:fileAdded a owl:NamedIndividual, core:RelationshipType . @@ -424,15 +373,57 @@ core:fileDeleted a owl:NamedIndividual, core:fileModified a owl:NamedIndividual, core:RelationshipType . +core:fixedBy a owl:NamedIndividual, + core:RelationshipType . + +core:fixedIn a owl:NamedIndividual, + core:RelationshipType . + +core:foundBy a owl:NamedIndividual, + core:RelationshipType . + +core:funding a owl:NamedIndividual, + core:ExternalReferenceType . + core:generates a owl:NamedIndividual, core:RelationshipType . core:gitoid a owl:NamedIndividual, core:ExternalIdentifierType . +core:hasAssociatedVulnerability a owl:NamedIndividual, + core:RelationshipType . + +core:hasCvssV2AssessmentFor a owl:NamedIndividual, + core:RelationshipType . + +core:hasCvssV3AssessmentFor a owl:NamedIndividual, + core:RelationshipType . + +core:hasEpssAssessmentFor a owl:NamedIndividual, + core:RelationshipType . + +core:hasExploitCatalogAssessmentFor a owl:NamedIndividual, + core:RelationshipType . + +core:hasSsvcAssessmentFor a owl:NamedIndividual, + core:RelationshipType . + core:incomplete a owl:NamedIndividual, core:RelationshipCompleteness . +core:issueTracker a owl:NamedIndividual, + core:ExternalReferenceType . + +core:license a owl:NamedIndividual, + core:ExternalReferenceType . + +core:licensing a owl:NamedIndividual, + core:ProfileIdentifierType . + +core:mailingList a owl:NamedIndividual, + core:ExternalReferenceType . + core:md2 a owl:NamedIndividual, core:HashAlgorithm . @@ -448,6 +439,12 @@ core:md6 a owl:NamedIndividual, core:metafile a owl:NamedIndividual, core:RelationshipType . +core:metrics a owl:NamedIndividual, + core:ExternalReferenceType . + +core:noAssertion a owl:NamedIndividual, + core:RelationshipCompleteness . + core:optionalComponent a owl:NamedIndividual, core:RelationshipType . @@ -459,6 +456,7 @@ core:other a owl:NamedIndividual, core:ExternalIdentifierType, core:ExternalReferenceType, core:HashAlgorithm, + core:LifecycleScopeType, core:RelationshipType . core:packages a owl:NamedIndividual, @@ -476,15 +474,36 @@ core:prerequisite a owl:NamedIndividual, core:providedDependency a owl:NamedIndividual, core:RelationshipType . +core:publishedBy a owl:NamedIndividual, + core:RelationshipType . + +core:releaseHistory a owl:NamedIndividual, + core:ExternalReferenceType . + +core:releaseNotes a owl:NamedIndividual, + core:ExternalReferenceType . + +core:reportedBy a owl:NamedIndividual, + core:RelationshipType . + +core:republishedBy a owl:NamedIndividual, + core:RelationshipType . + core:requirementFor a owl:NamedIndividual, core:RelationshipType . core:review a owl:NamedIndividual, core:AnnotationType . +core:runtime a owl:NamedIndividual, + core:LifecycleScopeType . + core:runtimeDependency a owl:NamedIndividual, core:RelationshipType . +core:security a owl:NamedIndividual, + core:ProfileIdentifierType . + core:securityAdvisory a owl:NamedIndividual, core:ExternalReferenceType . @@ -521,6 +540,15 @@ core:sha3_512 a owl:NamedIndividual, core:sha512 a owl:NamedIndividual, core:HashAlgorithm . +core:socialMedia a owl:NamedIndividual, + core:ExternalReferenceType . + +core:software a owl:NamedIndividual, + core:ProfileIdentifierType . + +core:sourceArtifact a owl:NamedIndividual, + core:ExternalReferenceType . + core:spdxPvcSha1 a owl:NamedIndividual, core:HashAlgorithm . @@ -530,11 +558,14 @@ core:spdxPvcSha256 a owl:NamedIndividual, core:specificationFor a owl:NamedIndividual, core:RelationshipType . +core:sphincsPlus a owl:NamedIndividual, + core:HashAlgorithm . + core:staticLink a owl:NamedIndividual, core:RelationshipType . -core:suppliedBy a owl:NamedIndividual, - core:RelationshipType . +core:support a owl:NamedIndividual, + core:ExternalReferenceType . core:swhid a owl:NamedIndividual, core:ExternalIdentifierType . @@ -543,6 +574,7 @@ core:swid a owl:NamedIndividual, core:ExternalIdentifierType . core:test a owl:NamedIndividual, + core:LifecycleScopeType, core:RelationshipType . core:testCase a owl:NamedIndividual, @@ -554,136 +586,800 @@ core:testDependency a owl:NamedIndividual, core:testTool a owl:NamedIndividual, core:RelationshipType . -core:unknown a owl:NamedIndividual, - core:RelationshipCompleteness . +core:underInvestigationFor a owl:NamedIndividual, + core:RelationshipType . core:urlScheme a owl:NamedIndividual, core:ExternalIdentifierType . +core:usage a owl:NamedIndividual, + core:ProfileIdentifierType . + core:variant a owl:NamedIndividual, core:RelationshipType . +core:vcs a owl:NamedIndividual, + core:ExternalReferenceType . + +dataset:Amber a owl:NamedIndividual, + dataset:ConfidentialityLevelType . + +dataset:Clear a owl:NamedIndividual, + dataset:ConfidentialityLevelType . + +dataset:Clickthrough a owl:NamedIndividual, + dataset:DatasetAvailabilityType . + dataset:Dataset a owl:Class, sh:NodeShape ; - rdfs:comment "Metadata information that can be added to a dataset that may be used in a software or to train/test an AI package." ; - rdfs:subClassOf ; + rdfs:comment """Metadata information that can be added to a dataset that may be used in a software or to train/test an AI package. +External property restriction on /Core/Artifact/originatedBy: minCount: 1 +External property restriction on /Software/Package/downloadLocation: minCount: 1 +External property restriction on /Software/SoftwareArtifact/purpose: minCount: 1 +External property restriction on /Core/Artifact/releaseTime: minCount: 1 +External property restriction on /Core/Artifact/builtTime: minCount: 1""" ; + rdfs:subClassOf software:Package ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:nonNegativeInteger ; + sh:property [ sh:datatype xsd:string ; + sh:name "dataPreprocessing" ; + sh:path dataset:dataPreprocessing ], + [ sh:datatype xsd:nonNegativeInteger ; sh:maxCount 1 ; sh:name "datasetSize" ; sh:path dataset:datasetSize ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "datasetUpdateMechanism" ; - sh:path dataset:datasetUpdateMechanism ], - [ sh:datatype ; + sh:name "dataCollectionProcess" ; + sh:path dataset:dataCollectionProcess ], + [ sh:datatype core:DictionaryEntry ; sh:name "sensor" ; sh:path dataset:sensor ], [ sh:datatype xsd:string ; + sh:name "knownBias" ; + sh:path dataset:knownBias ], + [ sh:datatype dataset:PresenceType ; sh:maxCount 1 ; - sh:name "dataPreprocessing" ; - sh:path dataset:dataPreprocessing ], + sh:name "sensitivePersonalInformation" ; + sh:path dataset:sensitivePersonalInformation ], [ sh:datatype dataset:ConfidentialityLevelType ; - sh:name "confidentialityLevelType" ; - sh:path dataset:confidentialityLevelType ], - [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "dataCollectionProcess" ; - sh:path dataset:dataCollectionProcess ], + sh:name "confidentialityLevel" ; + sh:path dataset:confidentialityLevel ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "knownBias" ; - sh:path dataset:knownBias ], + sh:name "intendedUse" ; + sh:path dataset:intendedUse ], [ sh:datatype xsd:string ; - sh:name "anonymizationMethodUsed" ; - sh:path dataset:anonymizationMethodUsed ], + sh:maxCount 1 ; + sh:name "datasetUpdateMechanism" ; + sh:path dataset:datasetUpdateMechanism ], [ sh:datatype dataset:DatasetAvailabilityType ; sh:maxCount 1 ; sh:name "datasetAvailability" ; sh:path dataset:datasetAvailability ], - [ sh:datatype dataset:PresenceType ; - sh:name "sensitivePersonalInformationType" ; - sh:path dataset:sensitivePersonalInformationType ], + [ sh:datatype xsd:string ; + sh:name "anonymizationMethodUsed" ; + sh:path dataset:anonymizationMethodUsed ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "datasetType" ; + sh:path dataset:datasetType ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "datasetNoise" ; - sh:path dataset:datasetNoise ], + sh:path dataset:datasetNoise ] . + +dataset:Direct-Download a owl:NamedIndividual, + dataset:DatasetAvailabilityType . + +dataset:Green a owl:NamedIndividual, + dataset:ConfidentialityLevelType . + +dataset:Query a owl:NamedIndividual, + dataset:DatasetAvailabilityType . + +dataset:Red a owl:NamedIndividual, + dataset:ConfidentialityLevelType . + +dataset:Registration a owl:NamedIndividual, + dataset:DatasetAvailabilityType . + +dataset:Scraping-Script a owl:NamedIndividual, + dataset:DatasetAvailabilityType . + +licensing:ConjunctiveLicenseSet a owl:Class, + sh:NodeShape ; + rdfs:comment """A ConjunctiveLicenseSet indicates that _each_ of its subsidiary +AnyLicenseInfos apply. In other words, a ConjunctiveLicenseSet of two or +more licenses represents a licensing situation where _all_ of the specified +licenses are to be complied with. It is represented in the SPDX License +Expression Syntax by the `AND` operator. + +It is syntactically correct to specify a ConjunctiveLicenseSet where the +subsidiary AnyLicenseInfos may be "incompatible" according to a particular +interpretation of the corresponding Licenses. The SPDX License Expression +Syntax does not take into account interpretation of license texts, which is +left to the consumer of SPDX data to determine for themselves.""" ; + rdfs:subClassOf licensing:AnyLicenseInfo ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype licensing:AnyLicenseInfo ; + sh:minCount 2 ; + sh:name "member" ; + sh:path licensing:member ] . + +licensing:CustomLicense a owl:Class, + sh:NodeShape ; + rdfs:comment """A CustomLicense represents a License that is not listed on the SPDX License +List at https://spdx.org/licenses, and is therefore defined by an SPDX data +creator.""" ; + rdfs:subClassOf licensing:License ; + ns0:term_status "Stable" . + +licensing:CustomLicenseAddition a owl:Class, + sh:NodeShape ; + rdfs:comment """A CustomLicenseAddition represents an addition to a License that is not listed +on the SPDX Exceptions List at https://spdx.org/licenses/exceptions-index.html, +and is therefore defined by an SPDX data creator. + +It is intended to represent additional language which is meant to be added to +a License, but which is not itself a standalone License.""" ; + rdfs:subClassOf licensing:LicenseAddition ; + ns0:term_status "Stable" . + +licensing:DisjunctiveLicenseSet a owl:Class, + sh:NodeShape ; + rdfs:comment """A DisjunctiveLicenseSet indicates that _only one_ of its subsidiary +AnyLicenseInfos is required to apply. In other words, a +DisjunctiveLicenseSet of two or more licenses represents a licensing +situation where _only one_ of the specified licenses are to be complied with. +A consumer of SPDX data would typically understand this to permit the recipient +of the licensed content to choose which of the corresponding license they +would prefer to use. It is represented in the SPDX License Expression Syntax +by the `OR` operator.""" ; + rdfs:subClassOf licensing:AnyLicenseInfo ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype licensing:AnyLicenseInfo ; + sh:minCount 2 ; + sh:name "member" ; + sh:path licensing:member ] . + +licensing:ListedLicense a owl:Class, + sh:NodeShape ; + rdfs:comment """A ListedLicense represents a License that is listed on the SPDX License List +at https://spdx.org/licenses.""" ; + rdfs:subClassOf licensing:License ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "deprecatedVersion" ; + sh:path licensing:deprecatedVersion ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "intendedUse" ; - sh:path dataset:intendedUse ] . + sh:name "listVersionAdded" ; + sh:path licensing:listVersionAdded ] . -dataset:confidentialityLevel a owl:DatatypeProperty ; - rdfs:comment "ConfidentialityLevel describes the levels of confidentiality of the data points contained in the dataset." ; - rdfs:range dataset:ConfidentialityLevelType ; +licensing:ListedLicenseException a owl:Class, + sh:NodeShape ; + rdfs:comment """A ListedLicenseException represents an exception to a License (in other words, +an exception to a license condition or an additional permission beyond those +granted in a License) which is listed on the SPDX Exceptions List at +https://spdx.org/licenses/exceptions-index.html.""" ; + rdfs:subClassOf licensing:LicenseAddition ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "listVersionAdded" ; + sh:path licensing:listVersionAdded ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "deprecatedVersion" ; + sh:path licensing:deprecatedVersion ] . + +licensing:NoAssertionLicense a owl:Class, + sh:NodeShape ; + rdfs:comment """A NoAssertionLicense is the primary value that is used by a concludedLicense +or declaredLicense field that indicates that the SPDX data creator is making +no assertion about the license information for the corresponding software +Package, File or Snippet. + +The specific meaning of NoAssertionLicense in the context of a +concludedLicense or declaredLicense field is more fully set forth in the +Property definitions for those fields.""" ; + rdfs:subClassOf licensing:LicenseField ; ns0:term_status "Stable" . -dataset:sensitivePersonalInformation a owl:DatatypeProperty ; - rdfs:comment """SensitivePersonalInformation indicates the presence of sensitive personal data -or information that allows drawing conclusions about a person's identity.""" ; - rdfs:range dataset:PresenceType ; +licensing:NoneLicense a owl:Class, + sh:NodeShape ; + rdfs:comment """A NoneLicense is the primary value that is used by a concludedLicense or +declaredLicense field that indicates the absence of license information from +the corresponding software Package, File or Snippet. + +The specific meaning of NoneLicense in the context of a concludedLicense or +declaredLicense field is more fully set forth in the Property definitions for +those fields.""" ; + rdfs:subClassOf licensing:LicenseField ; ns0:term_status "Stable" . -software:File a owl:Class, +licensing:OrLaterOperator a owl:Class, sh:NodeShape ; - rdfs:comment "TODO This is about the File class." ; - rdfs:subClassOf ; + rdfs:comment """An OrLaterOperator indicates that this portion of the AnyLicenseInfo +represents either (1) the specified version of the corresponding License, or +(2) any later version of that License. It is represented in the SPDX License +Expression Syntax by the `+` operator. + +It is context-dependent, and unspecified by SPDX, as to what constitutes a +"later version" of any particular License. Some Licenses may not be versioned, +or may not have clearly-defined ordering for versions. The consumer of SPDX +data will need to determine for themselves what meaning to attribute to a +"later version" operator for a particular License.""" ; + rdfs:subClassOf licensing:AnyLicenseInfo ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:anyURI ; + sh:property [ sh:datatype licensing:License ; sh:maxCount 1 ; - sh:name "contentIdentifier" ; - sh:path software:contentIdentifier ], - [ sh:datatype software:SoftwarePurpose ; - sh:name "filePurpose" ; - sh:path software:filePurpose ], - [ sh:datatype software:MediaType ; + sh:minCount 1 ; + sh:name "subjectLicense" ; + sh:path licensing:subjectLicense ] . + +licensing:WithAdditionOperator a owl:Class, + sh:NodeShape ; + rdfs:comment """A WithAdditionOperator indicates that the designated License is subject to the +designated LicenseAddition, which might be a license exception on the SPDX +Exceptions List (ListedLicenseException) or may be other additional text +(CustomLicenseAddition). It is represented in the SPDX License Expression +Syntax by the `WITH` operator.""" ; + rdfs:subClassOf licensing:AnyLicenseInfo ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype licensing:License ; sh:maxCount 1 ; - sh:name "contentType" ; - sh:path software:contentType ] . + sh:minCount 1 ; + sh:name "subjectLicense" ; + sh:path licensing:subjectLicense ], + [ sh:datatype licensing:LicenseAddition ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "subjectAddition" ; + sh:path licensing:subjectAddition ] . -software:Package a owl:Class, +security:CvssV2VulnAssessmentRelationship a owl:Class, sh:NodeShape ; - rdfs:comment """A package refers to any unit of content that can be associated with a distribution of software. -Typically, a package is composed of one or more files. -Any of the following non-limiting examples may be (but are not required to be) represented in SPDX as a package: + rdfs:comment """A CvssV2VulnAssessmentRelationship relationship describes the determined score and vector of a vulnerability using version 2.0 of the Common Vulnerability Scoring System +(CVSS) as defined on [https://www.first.org/cvss/v2/guide](https://www.first.org/cvss/v2/guide). It is intented to communicate the results of using a CVSS calculator. + +**Constraints** + +The value of severity must be one of 'low', 'medium' or 'high' + +**Syntax** + +```json +{ + "@type": "CvssV2VulnAssessmentRelationship", + "@id": "urn:spdx.dev:cvssv2-cve-2020-28498", + "relationshipType": "hasCvssV2AssessmentFor", + "score": 4.3, + "vector": "(AV:N/AC:M/Au:N/C:P/I:N/A:N)", + "severity": "low", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.2", + "externalReferences": [ + { + "@type": "ExternalReference", + "externalReferenceType": "securityAdvisory", + "locator": "https://nvd.nist.gov/vuln/detail/CVE-2020-28498" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityAdvisory", + "locator": "https://snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityFix", + "locator": "https://github.com/indutny/elliptic/commit/441b742" + } + ], + "suppliedBy": ["urn:spdx.dev:agent-my-security-vendor"], + "publishedTime": "2023-05-06T10:06:13Z" +}, +{ + "@type": "Relationship", + "@id": "urn:spdx.dev:vulnAgentRel-1", + "relationshipType": "publishedBy", + "from": "urn:spdx.dev:cvssv2-cve-2020-28498", + "to": ["urn:spdx.dev:agent-snyk"], + "startTime": "2021-03-08T16:06:50Z" +} +```""" ; + rdfs:subClassOf security:VulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "vector" ; + sh:path security:vector ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "severity" ; + sh:path security:severity ], + [ sh:datatype xsd:decimal ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "score" ; + sh:path security:score ] . - - a tarball, zip file or other archive - - a directory or sub-directory - - a separately distributed piece of software which another Package or File uses or depends upon (e.g., a Python package, a Go module, ...) - - a container image, and/or each image layer within a container image - - a collection of one or more sub-packages - - a Git repository snapshot from a particular point in time +security:CvssV3VulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """A CvssV3VulnAssessmentRelationship relationship describes the determined score, +severity, and vector of a vulnerability using version 3.1 of the Common +Vulnerability Scoring System (CVSS) as defined on +[https://www.first.org/cvss/v3.1/specification-document](https://www.first.org/cvss/v3.1/specification-document). It is intented to communicate the results of using a CVSS calculator. + +**Constraints** + +The value of severity must be one of 'none', 'low', 'medium', 'high' or 'critical'. +Absence of the property shall be interpreted as 'none'. + +**Syntax** + +```json +{ + "@type": "CvssV3VulnAssessmentRelationship", + "@id": "urn:spdx.dev:cvssv3-cve-2020-28498", + "relationshipType": "hasCvssV3AssessmentFor", + "severity": "medium", + "score": 6.8, + "vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.2", + "externalReferences": [ + { + "@type": "ExternalReference", + "externalReferenceType": "securityAdvisory", + "locator": "https://nvd.nist.gov/vuln/detail/CVE-2020-28498" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityAdvisory", + "locator": "https://snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityFix", + "locator": "https://github.com/indutny/elliptic/commit/441b742" + } + ], + "suppliedBy": ["urn:spdx.dev:agent-my-security-vendor"], + "publishedTime": "2023-05-06T10:06:13Z" +}, +{ + "@type": "Relationship", + "@id": "urn:spdx.dev:vulnAgentRel-1", + "relationshipType": "publishedBy", + "from": "urn:spdx.dev:cvssv3-cve-2020-28498", + "to": "urn:spdx.dev:agent-snyk", + "startTime": "2021-03-08T16:06:50Z" +} +```""" ; + rdfs:subClassOf security:VulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:decimal ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "score" ; + sh:path security:score ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "vector" ; + sh:path security:vector ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "severity" ; + sh:path security:severity ] . -Note that some of these could be represented in SPDX as a file as well.""" ; - rdfs:subClassOf ; +security:EpssVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """An EpssVulnAssessmentRelationship relationship describes the likelihood or +probability that a vulnerability will be exploited in the wild using the Exploit +Prediction Scoring System (EPSS) as defined on +[https://www.first.org/epss/model](https://www.first.org/epss/model). + +**Syntax** + +```json +{ + "@type": "EpssVulnAssessmentRelationship", + "@id": "urn:spdx.dev:epss-1", + "relationshipType": "hasEpssAssessmentFor", + "probability": 80, + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VulnAssessmentRelationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:anyURI ; + sh:property [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "downloadLocation" ; - sh:path software:downloadLocation ], - [ sh:datatype xsd:anyURI ; + sh:name "severity" ; + sh:path security:severity ], + [ sh:datatype xsd:nonNegativeInteger ; sh:maxCount 1 ; - sh:name "packageUrl" ; - sh:path software:packageUrl ], - [ sh:datatype software:SoftwarePurpose ; - sh:name "packagePurpose" ; - sh:path software:packagePurpose ], - [ sh:datatype xsd:anyURI ; + sh:minCount 1 ; + sh:name "probability" ; + sh:path security:probability ] . + +security:ExploitCatalogVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """An ExploitCatalogVulnAssessmentRelationship describes if a vulnerability is +listed in any exploit catalog such as the CISA Known Exploited Vulnerabilities +Catalog (KEV) +[https://www.cisa.gov/known-exploited-vulnerabilities-catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog). + +**Syntax** + +```json +{ + "@type": "ExploitCatalogVulnAssessmentRelationship", + "@id": "urn:spdx.dev:exploit-catalog-1", + "relationshipType": "hasExploitCatalogAssessmentFor", + "catalogType": "kev", + "locator": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog", + "exploited": "true", + "from": "urn:spdx.dev:vuln-cve-2023-2136", + "to": ["urn:product-google-chrome-112.0.5615.136"], + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype security:ExploitCatalogType ; sh:maxCount 1 ; - sh:name "contentIdentifier" ; - sh:path software:contentIdentifier ], + sh:minCount 1 ; + sh:name "catalogType" ; + sh:path security:catalogType ], [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; - sh:name "homePage" ; - sh:path software:homePage ], + sh:minCount 1 ; + sh:name "locator" ; + sh:path security:locator ], + [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "exploited" ; + sh:path security:exploited ] . + +security:SsvcVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """An SsvcVulnAssessmentRelationship describes the decision made using the +Stakeholder-Specific Vulnerability Categorization (SSVC) decision tree as +defined on [https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc](https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc). +It is intended to communicate the results of using the CISA SSVC Calculator. + +**Syntax** + +```json +{ + "@type": "SsvcVulnAssessmentRelationship", + "@id": "urn:spdx.dev:ssvc-1", + "relationshipType": "hasSsvcAssessmentFor", + "decisionType": "act", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.2", + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype security:SsvcDecisionType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "decisionType" ; + sh:path security:decisionType ] . + +security:VexAffectedVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """VexAffectedVulnAssessmentRelationship connects a vulnerability and a number +of elements. The relationship marks these elements as products affected by the +vulnerability. This relationship corresponds to the VEX affected status. + +**Constraints** + +When linking elements using a VexAffectedVulnAssessmentRelationship, the +following requirements must be observed: + +- Elements linked with a VulnVexAffectedAssessmentRelationship are constrained +to the affects relationship type. + +**Syntax** + +```json +{ + "@type": "VexAffectedVulnAssessmentRelationship", + "@id": "urn:spdx.dev:vex-affected-1", + "relationshipType": "affects", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.2", + "actionStatement": "Upgrade to version 1.4 of ACME application.", + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VexVulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:dateTime ; + sh:name "actionStatementTime" ; + sh:path security:actionStatementTime ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "packageVersion" ; - sh:path software:packageVersion ], + sh:name "actionStatement" ; + sh:path security:actionStatement ] . + +security:VexFixedVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """VexFixedVulnAssessmentRelationship links a vulnerability to a number of elements +representing VEX products where a vulnerability has been fixed and are no longer +affected. It represents the VEX fixed status. + +**Constraints** + +When linking elements using a VexFixedVulnAssessmentRelationship, the following +requirements must be observed: + +- Elements linked with a VulnVexFixedAssessmentRelationship are constrained to +using the fixedIn relationship type. +- The from: end of the relationship must ve a /Security/Vulnerability classed +element. + +**Syntax** + +```json +{ + "@type": "VexFixedVulnAssessmentRelationship", + "@id": "urn:spdx.dev:vex-fixed-in-1", + "relationshipType": "fixedIn", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.4", + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VexVulnAssessmentRelationship ; + ns0:term_status "Stable" . + +security:VexNotAffectedVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """VexNotAffectedVulnAssessmentRelationship connects a vulnerability and a number +of elements designating them as products not affected by the vulnerability. +This relationship corresponds to the VEX not_affected status. + +**Constraints** + +When linking elements using a VexNotVulnAffectedAssessmentRelationship, the +following requirements must be observed: + +* Relating elements with a VexNotAffectedVulnAssessmentRelationship is restricted +to the doesNotAffect relationship type. +* The from: end of the relationship must be a /Security/Vulnerability classed +element. +* Both impactStatement and justificationType properties have a cardinality of +0..1 making them optional. Nevertheless, to produce a valid VEX not_affected +statement, one of them MUST be defined. This is specified in the Minimum Elements +for VEX. + +**Syntax** + +```json +{ + "@type": "VexNotAffectedVulnAssessmentRelationship", + "@id": "urn:spdx.dev:vex-not-affected-1", + "relationshipType": "doesNotAffect", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.2", + "justificationType": "componentNotPresent", + "impactStatement": "Not using this vulnerable part of this library.", + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VexVulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:dateTime ; + sh:maxCount 1 ; + sh:name "impactStatementTime" ; + sh:path security:impactStatementTime ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "sourceInfo" ; - sh:path software:sourceInfo ] . + sh:name "impactStatement" ; + sh:path security:impactStatement ], + [ sh:datatype security:VexJustificationType ; + sh:maxCount 1 ; + sh:name "justificationType" ; + sh:path security:justificationType ] . + +security:VexUnderInvestigationVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """VexUnderInvestigationVulnAssessmentRelationship links a vulnerability to a +number of products stating the vulnerability's impact on them is being +investigated. It represents the VEX under_investigation status. + +**Constraints** + +When linking elements using a VexUnderInvestigationVulnAssessmentRelationship +the following requirements must be observed: + +- Elements linked with a VexUnderInvestigationVulnAssessmentRelationship are +constrained to using the underInvestigationFor relationship type. +- The from: end of the relationship must ve a /Security/Vulnerability classed +element. + +**Syntax** + +```json +{ + "@type": "VexUnderInvestigationVulnAssessmentRelationship", + "@id": "urn:spdx.dev:vex-underInvestigation-1", + "relationshipType": "underInvestigationFor", + "from": "urn:spdx.dev:vuln-cve-2020-28498", + "to": ["urn:product-acme-application-1.3"], + "assessedElement": "urn:npm-elliptic-6.5.2", + "suppliedBy": ["urn:spdx.dev:agent-jane-doe"], + "publishedTime": "2021-03-09T11:04:53Z" +} +```""" ; + rdfs:subClassOf security:VexVulnAssessmentRelationship ; + ns0:term_status "Stable" . + +security:Vulnerability a owl:Class, + sh:NodeShape ; + rdfs:comment """Specifies a vulnerability and its associated information. + +**Syntax** + +```json +{ + "@type": "Vulnerability", + "@id": "urn:spdx.dev:vuln-1", + "summary": "Use of a Broken or Risky Cryptographic Algorithm", + "description": "The npm package `elliptic` before version 6.5.4 are vulnerable to Cryptographic Issues via the secp256k1 implementation in elliptic/ec/key.js. There is no check to confirm that the public key point passed into the derive function actually exists on the secp256k1 curve. This results in the potential for the private key used in this implementation to be revealed after a number of ECDH operations are performed.", + "modified": "2021-03-08T16:02:43Z", + "published": "2021-03-08T16:06:50Z", + "externalIdentifiers": [ + { + "@type": "ExternalIdentifier", + "externalIdentifierType": "cve", + "identifier": "CVE-2020-2849", + "identifierLocator": [ + "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-28498", + "https://www.cve.org/CVERecord?id=CVE-2020-28498" + ], + "issuingAuthority": "urn:spdx.dev:agent-cve.org" + }, + { + "type": "ExternalIdentifier", + "externalIdentifierType": "securityOther", + "identifier": "GHSA-r9p9-mrjm-926w", + "identifierLocator": "https://github.com/advisories/GHSA-r9p9-mrjm-926w" + }, + { + "type": "ExternalIdentifier", + "externalIdentifierType": "securityOther", + "identifier": "SNYK-JS-ELLIPTIC-1064899", + "identifierLocator": "https://security.snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899" + } + ], + "externalReferences": [ + { + "@type": "ExternalReference", + "externalReferenceType": "securityAdvisory", + "locator": "https://nvd.nist.gov/vuln/detail/CVE-2020-28498" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityAdvisory", + "locator": "https://ubuntu.com/security/CVE-2020-28498" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityOther", + "locator": "https://github.com/indutny/elliptic/pull/244/commits" + }, + { + "@type": "ExternalReference", + "externalReferenceType": "securityOther", + "locator": "https://github.com/christianlundkvist/blog/blob/master/2020_05_26_secp256k1_twist_attacks/secp256k1_twist_attacks.md" + } + ] +}, +{ + "@type": "Relationship", + "@id": "urn:spdx.dev:vulnRelationship-1", + "relationshipType": "hasAssociatedVulnerability", + "from": "urn:npm-elliptic-6.5.2", + "to": ["urn:spdx.dev:vuln-1"], + "startTime": "2021-03-08T16:06:50Z" +}, +{ + "@type": "Relationship", + "@id": "urn:spdx.dev:vulnAgentRel-1", + "relationshipType": "publishedBy", + "from": "urn:spdx.dev:vuln-1", + "to": ["urn:spdx.dev:agent-snyk"], + "startTime": "2021-03-08T16:06:50Z" +} +```""" ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "publishedTime" ; + sh:path security:publishedTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "withdrawnTime" ; + sh:path security:withdrawnTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "modifiedTime" ; + sh:path security:modifiedTime ] . + +security:act a owl:NamedIndividual, + security:SsvcDecisionType . + +security:attend a owl:NamedIndividual, + security:SsvcDecisionType . + +security:componentNotPresent a owl:NamedIndividual, + security:VexJustificationType . + +security:inlineMitigationsAlreadyExist a owl:NamedIndividual, + security:VexJustificationType . + +security:kev a owl:NamedIndividual, + security:ExploitCatalogType . + +security:other a owl:NamedIndividual, + security:ExploitCatalogType . + +security:track a owl:NamedIndividual, + security:SsvcDecisionType . + +security:trackStar a owl:NamedIndividual, + security:SsvcDecisionType . + +security:vulnerableCodeCannotBeControlledByAdversary a owl:NamedIndividual, + security:VexJustificationType . + +security:vulnerableCodeNotInExecutePath a owl:NamedIndividual, + security:VexJustificationType . + +security:vulnerableCodeNotPresent a owl:NamedIndividual, + security:VexJustificationType . + +security:withdrawn a owl:DatatypeProperty ; + rdfs:comment "Specified the time and date when a vulnerability was withdrawn." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +software:File a owl:Class, + sh:NodeShape ; + rdfs:comment """Refers to any object that stores content on a computer. +The type of content can optionally be provided in the contentType property. +External property restriction on /Core/Element/name: minCount: 1""" ; + rdfs:subClassOf software:SoftwareArtifact ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:MediaType ; + sh:maxCount 1 ; + sh:name "contentType" ; + sh:path software:contentType ] . software:Sbom a owl:Class, sh:NodeShape ; @@ -691,31 +1387,44 @@ software:Sbom a owl:Class, This could include details of the content and composition of the product, provenance details of the product and/or its composition, licensing information, known quality or security issues, etc.""" ; - rdfs:subClassOf ; - ns0:term_status "Stable" . + rdfs:subClassOf core:Bom ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype software:SBOMType ; + sh:name "sbomType" ; + sh:path software:sbomType ] . software:Snippet a owl:Class, sh:NodeShape ; rdfs:comment """A Snippet describes a certain part of a file and can be used when the file is known to have some content that has been included from another original source. Snippets are useful for denoting when part of a file may have been originally created under another license or copied from a place with a known vulnerability.""" ; - rdfs:subClassOf ; + rdfs:subClassOf software:SoftwareArtifact ; ns0:term_status "Stable" ; - sh:property [ sh:datatype ; + sh:property [ sh:datatype core:PositiveIntegerRange ; sh:maxCount 1 ; sh:name "lineRange" ; sh:path software:lineRange ], - [ sh:datatype xsd:anyURI ; - sh:maxCount 1 ; - sh:name "contentIdentifier" ; - sh:path software:contentIdentifier ], - [ sh:datatype ; + [ sh:datatype core:PositiveIntegerRange ; sh:maxCount 1 ; sh:name "byteRange" ; - sh:path software:byteRange ], - [ sh:datatype software:SoftwarePurpose ; - sh:name "snippetPurpose" ; - sh:path software:snippetPurpose ] . + sh:path software:byteRange ] . + +software:SoftwareDependencyRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment "TODO" ; + rdfs:subClassOf core:LifecycleScopedRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype software:DependencyConditionalityType ; + sh:maxCount 1 ; + sh:name "conditionality" ; + sh:path software:conditionality ], + [ sh:datatype software:SoftwareDependencyLinkType ; + sh:maxCount 1 ; + sh:name "softwareLinkage" ; + sh:path software:softwareLinkage ] . + +software:analyzed a owl:NamedIndividual, + software:SBOMType . software:application a owl:NamedIndividual, software:SoftwarePurpose . @@ -726,6 +1435,9 @@ software:archive a owl:NamedIndividual, software:bom a owl:NamedIndividual, software:SoftwarePurpose . +software:build a owl:NamedIndividual, + software:SBOMType . + software:configuration a owl:NamedIndividual, software:SoftwarePurpose . @@ -735,12 +1447,24 @@ software:container a owl:NamedIndividual, software:data a owl:NamedIndividual, software:SoftwarePurpose . +software:deployed a owl:NamedIndividual, + software:SBOMType . + +software:design a owl:NamedIndividual, + software:SBOMType . + software:device a owl:NamedIndividual, software:SoftwarePurpose . software:documentation a owl:NamedIndividual, software:SoftwarePurpose . +software:dynamic a owl:NamedIndividual, + software:SoftwareDependencyLinkType . + +software:evidence a owl:NamedIndividual, + software:SoftwarePurpose . + software:executable a owl:NamedIndividual, software:SoftwarePurpose . @@ -759,21 +1483,54 @@ software:install a owl:NamedIndividual, software:library a owl:NamedIndividual, software:SoftwarePurpose . +software:manifest a owl:NamedIndividual, + software:SoftwarePurpose . + software:module a owl:NamedIndividual, software:SoftwarePurpose . software:operatingSystem a owl:NamedIndividual, software:SoftwarePurpose . +software:optional a owl:NamedIndividual, + software:DependencyConditionalityType . + software:other a owl:NamedIndividual, + software:DependencyConditionalityType, + software:SoftwareDependencyLinkType, software:SoftwarePurpose . software:patch a owl:NamedIndividual, software:SoftwarePurpose . +software:prerequisite a owl:NamedIndividual, + software:DependencyConditionalityType . + +software:provided a owl:NamedIndividual, + software:DependencyConditionalityType . + +software:required a owl:NamedIndividual, + software:DependencyConditionalityType . + +software:requirement a owl:NamedIndividual, + software:SoftwarePurpose . + +software:runtime a owl:NamedIndividual, + software:SBOMType . + software:source a owl:NamedIndividual, + software:SBOMType, + software:SoftwarePurpose . + +software:specification a owl:NamedIndividual, software:SoftwarePurpose . +software:static a owl:NamedIndividual, + software:SoftwareDependencyLinkType . + +software:tool a owl:NamedIndividual, + software:SoftwareDependencyLinkType . + ai:autonomyType a owl:DatatypeProperty ; rdfs:comment """AutonomyType indicates if a human is involved in any of the decisions of the AI software or if that software is fully automatic.""" ; @@ -787,55 +1544,61 @@ can be expected to operate successfully. Examples include computer vision, natur ns0:term_status "Stable" . ai:energyConsumption a owl:DatatypeProperty ; - rdfs:comment """EnergyConsumption captures the amount of energy needed to train and operate the AI model. + rdfs:comment """EnergyConsumption captures the amount of energy needed to train and operate the AI model. This value is also known as training energy consumption or inference energy consumption.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . -ai:hyperparameters a owl:DatatypeProperty ; - rdfs:comment """This field records important hyperparameter values. -These are parameters of the machine learning model that are used to control the learning process, +ai:hyperparameter a owl:DatatypeProperty ; + rdfs:comment """This field records a hyperparameter value. +Hyperparameters are parameters of the machine learning model that are used to control the learning process, for example the optimization and learning rate used during the training of the model.""" ; - rdfs:range ; + rdfs:range core:DictionaryEntry ; ns0:term_status "Stable" . ai:informationAboutApplication a owl:DatatypeProperty ; - rdfs:comment """InformationAboutApplication describes any relevant information in free form text about + rdfs:comment """InformationAboutApplication describes any relevant information in free form text about how the AI model is used inside the software, as well as any relevant pre-processing steps, third party APIs etc.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . ai:informationAboutTraining a owl:DatatypeProperty ; rdfs:comment """InformationAboutTraining describes the specific steps involved in the training of the AI model. -For example, it can be specified whether supervised fine-tuning +For example, it can be specified whether supervised fine-tuning or active learning is used as part of training the model.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . -ai:limitations a owl:DatatypeProperty ; - rdfs:comment """Limitations captures limitations of the AI Package (or of the AI models present in the AI package), +ai:limitation a owl:DatatypeProperty ; + rdfs:comment """Limitation captures a limitation of the AI Package (or of the AI models present in the AI package), expressed as free form text. Note that this is not guaranteed to be exhaustive. For instance, a limitation might be that the AI package cannot be used on datasets from a certain demography.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . -ai:metrics a owl:DatatypeProperty ; - rdfs:comment """Metrics records the measurements with which the AI model was evaluated. +ai:metric a owl:DatatypeProperty ; + rdfs:comment """Metric records the measurement with which the AI model was evaluated. This makes statements about the prediction quality including uncertainty, accuracy, characteristics of the tested population, quality, fairness, explainability, robustness etc.""" ; - rdfs:range ; + rdfs:range core:DictionaryEntry ; ns0:term_status "Stable" . -ai:metricsDecisionThresholds a owl:DatatypeProperty ; - rdfs:comment """Each metric might be computed based on a decision threshold. +ai:metricDecisionThreshold a owl:DatatypeProperty ; + rdfs:comment """Each metric might be computed based on a decision threshold. For instance, precision or recall is typically computed by checking if the probability of the outcome is larger than 0.5. -Each decision threshold should match with the metrics field defined in the AI Package.""" ; - rdfs:range ; +Each decision threshold should match with a metric field defined in the AI Package.""" ; + rdfs:range core:DictionaryEntry ; + ns0:term_status "Stable" . + +ai:modelDataPreprocessing a owl:DatatypeProperty ; + rdfs:comment """ModelDataPreprocessing is a free form text that describes the preprocessing steps +applied to the training data before training of the model(s) contained in the AI software.""" ; + rdfs:range xsd:string ; ns0:term_status "Stable" . -ai:modelExplainabilityMechanisms a owl:DatatypeProperty ; - rdfs:comment """ModelExplainabilityMechanisms is a free form text that lists the different explainability mechanisms +ai:modelExplainability a owl:DatatypeProperty ; + rdfs:comment """ModelExplainability is a free form text that lists the different explainability mechanisms (such as SHAP, or other model specific explainability mechanisms) that can be used to explain the model.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . @@ -853,22 +1616,22 @@ This might include biometric data, addresses or other data that can be used to i rdfs:range ai:PresenceType ; ns0:term_status "Stable" . -ai:standardsCompliance a owl:DatatypeProperty ; - rdfs:comment """StandardsCompliance captures standards that the AI software complies with. -This could include both published and unpublished standards including ISO, IEEE, ETSI etc. -These standards could (but not necessarily have to) be used to satisfy a legal or regulatory requirement.""" ; +ai:standardCompliance a owl:DatatypeProperty ; + rdfs:comment """StandardCompliance captures a standard that the AI software complies with. +This includes both published and unpublished standards, for example ISO, IEEE, ETSI etc. +The standard could (but not necessarily have to) be used to satisfy a legal or regulatory requirement.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . ai:typeOfModel a owl:DatatypeProperty ; - rdfs:comment """TypeOfModel records the type of the AI model(s) used in the software. + rdfs:comment """TypeOfModel records the type of the AI model(s) used in the software. For instance, if it is a supervised model, unsupervised model, reinforcement learning model or a combination of those.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . -build:buildEnd a owl:DatatypeProperty ; - rdfs:comment "buildEnd describes the time at which a build stops or finishes. This value is typically recorded by the builder." ; - rdfs:range xsd:dateTime ; +build:buildEndTime a owl:DatatypeProperty ; + rdfs:comment "buildEndTime describes the time at which a build stops or finishes. This value is typically recorded by the builder." ; + rdfs:range core:DateTime ; ns0:term_status "Stable" . build:buildId a owl:DatatypeProperty ; @@ -876,9 +1639,9 @@ build:buildId a owl:DatatypeProperty ; rdfs:range xsd:string ; ns0:term_status "Stable" . -build:buildStart a owl:DatatypeProperty ; - rdfs:comment "buildStart is the time at which a build is triggered. The builder typically records this value." ; - rdfs:range xsd:dateTime ; +build:buildStartTime a owl:DatatypeProperty ; + rdfs:comment "buildStartTime is the time at which a build is triggered. The builder typically records this value." ; + rdfs:range core:DateTime ; ns0:term_status "Stable" . build:buildType a owl:DatatypeProperty ; @@ -888,7 +1651,7 @@ build:buildType a owl:DatatypeProperty ; build:configSourceDigest a owl:DatatypeProperty ; rdfs:comment "configSourceDigest is the checksum of the build configuration file used by a builder to execute a build. This Property uses the Core model's [Hash](../../Core/Classes/Hash.md) class." ; - rdfs:range ; + rdfs:range core:Hash ; ns0:term_status "Stable" . build:configSourceEntrypoint a owl:DatatypeProperty ; @@ -913,42 +1676,90 @@ steps: ns0:term_status "Stable" . build:configSourceUri a owl:DatatypeProperty ; - rdfs:comment """If a build configuration exists for the toolchain or platform performing the build, the configSourceUri of a build is the URI of that build configuration. For example, a build triggered by a GitHub action is defined by a build configuration YAML file. In this case, the configSourceUri is the URL of that YAML file. + rdfs:comment """If a build configuration exists for the toolchain or platform performing the build, the configSourceUri of a build is the URI of that build configuration. For example, a build triggered by a GitHub action is defined by a build configuration YAML file. In this case, the configSourceUri is the URL of that YAML file. m""" ; rdfs:range xsd:anyURI ; ns0:term_status "Stable" . build:environment a owl:DatatypeProperty ; rdfs:comment "environment is a map of environment variables and values that are set during a build session. This is different from the [parameters](parameters.md) property in that it describes the environment variables set before a build is invoked rather than the variables provided to the builder." ; - rdfs:range ; + rdfs:range core:DictionaryEntry ; ns0:term_status "Stable" . build:parameters a owl:DatatypeProperty ; rdfs:comment "parameters is a key-value map of all build parameters and their values that were provided to the builder for a build instance. This is different from the [environment](environment.md) property in that the keys and values are provided as command line arguments or a configuration file to the builder." ; - rdfs:range ; + rdfs:range core:DictionaryEntry ; ns0:term_status "Stable" . -core:ElementCollection a owl:Class, +core:Artifact a owl:Class, sh:NodeShape ; - rdfs:comment "An SpdxCollection is a collection of Elements, not necessarily with unifying context." ; + rdfs:comment """An artifact is a distinct article or unit within the digital domain, +such as an electronic file, a software package, a device or an element of data.""" ; rdfs:subClassOf core:Element ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:Element ; - sh:minCount 1 ; - sh:name "element" ; - sh:path core:element ], - [ sh:datatype core:Element ; - sh:minCount 1 ; - sh:name "rootElement" ; - sh:path core:rootElement ], - [ sh:datatype core:NamespaceMap ; - sh:name "namespaces" ; - sh:path core:namespaces ], - [ sh:datatype core:ExternalMap ; - sh:name "imports" ; - sh:path core:imports ] . - -core:algorithm a owl:DatatypeProperty ; + sh:property [ sh:datatype core:Identity ; + sh:name "suppliedBy" ; + sh:path core:suppliedBy ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "validUntilTime" ; + sh:path core:validUntilTime ], + [ sh:datatype xsd:string ; + sh:name "standard" ; + sh:path core:standard ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "releaseTime" ; + sh:path core:releaseTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "builtTime" ; + sh:path core:builtTime ], + [ sh:datatype core:Identity ; + sh:name "originatedBy" ; + sh:path core:originatedBy ] . + +core:Bom a owl:Class, + sh:NodeShape ; + rdfs:comment """A Bill Of Materials (BOM) is a container for a grouping of SPDX-3.0 content +characterizing details about a product. +This could include details of the content and composition of the product, +provenence details of the product and/or +its composition, licensing information, known quality or security issues, etc.""" ; + rdfs:subClassOf core:Bundle ; + ns0:term_status "Stable" . + +core:ElementCollection a owl:Class, + sh:NodeShape ; + rdfs:comment "An SpdxCollection is a collection of Elements, not necessarily with unifying context." ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:Element ; + sh:minCount 1 ; + sh:name "rootElement" ; + sh:path core:rootElement ], + [ sh:datatype core:ExternalMap ; + sh:name "imports" ; + sh:path core:imports ], + [ sh:datatype core:Element ; + sh:minCount 1 ; + sh:name "element" ; + sh:path core:element ], + [ sh:datatype core:NamespaceMap ; + sh:name "namespaces" ; + sh:path core:namespaces ] . + +core:LifecycleScopedRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment "TODO" ; + rdfs:subClassOf core:Relationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:LifecycleScopeType ; + sh:maxCount 1 ; + sh:name "scope" ; + sh:path core:scope ] . + +core:algorithm a owl:DatatypeProperty ; rdfs:comment "An algorithm specifies the algorithm that was used for calculating the hash value." ; rdfs:range core:HashAlgorithm ; ns0:term_status "Stable" . @@ -965,7 +1776,7 @@ core:begin a owl:DatatypeProperty ; core:builtTime a owl:DatatypeProperty ; rdfs:comment "A builtTime specifies the time an artifact was built." ; - rdfs:range xsd:dateTime ; + rdfs:range core:DateTime ; ns0:term_status "Stable" . core:completeness a owl:DatatypeProperty ; @@ -983,7 +1794,7 @@ that Elements of the bundle have been assembled under.""" ; core:created a owl:DatatypeProperty ; rdfs:comment """Created is a date that identifies when the Element was originally created. The time stamp can serve as an indication as to whether the analysis needs to be updated. This is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.""" ; - rdfs:range xsd:dateTime ; + rdfs:range core:DateTime ; ns0:term_status "Stable" . core:createdBy a owl:ObjectProperty ; @@ -1010,7 +1821,7 @@ however individuals can still contract with each other to restrict release of specific collections of SPDX files (which map to software bill of materials) and the identification of the supplier of SPDX files. Compliance with this document includes populating the SPDX fields therein -with data related to such fields ("SPDX-Metadata"). +with data related to such fields ("SPDX-Metadata"). This document contains numerous fields where an SPDX file creator may provide relevant explanatory text in SPDX-Metadata. Without opining on the lawfulness of "database rights" (in jurisdictions where applicable), @@ -1018,8 +1829,8 @@ such explanatory text is copyrightable subject matter in most Berne Convention c By using the SPDX specification, or any portion hereof, you hereby agree that any copyright rights (as determined by your jurisdiction) in any SPDX-Metadata, including without limitation explanatory text, -shall be subject to the terms of the Creative Commons CC0 1.0 Universal license. -For SPDX-Metadata not containing any copyright rights, +shall be subject to the terms of the Creative Commons CC0 1.0 Universal license. +For SPDX-Metadata not containing any copyright rights, you hereby agree and acknowledge that the SPDX-Metadata is provided to you “as-is” and without any representations or warranties of any kind concerning the SPDX-Metadata, express, implied, statutory or otherwise, including without limitation warranties @@ -1047,7 +1858,14 @@ core:end a owl:DatatypeProperty ; rdfs:range xsd:positiveInteger ; ns0:term_status "Stable" . -core:extension rdfs:comment "TODO" ; +core:endTime a owl:DatatypeProperty ; + rdfs:comment "A endTime specifies the time from which element is no applicable / valid." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +core:extension a owl:NamedIndividual, + core:ProfileIdentifierType ; + rdfs:comment "TODO" ; ns0:term_status "Stable" . core:externalId a owl:DatatypeProperty ; @@ -1087,6 +1905,21 @@ core:hashValue a owl:DatatypeProperty ; rdfs:range xsd:string ; ns0:term_status "Stable" . +core:identifier a owl:DatatypeProperty ; + rdfs:comment "An identifier uniquely identifies an external element." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:identifierLocator a owl:DatatypeProperty ; + rdfs:comment "A identifierLocator is TODO" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +core:issuingAuthority a owl:DatatypeProperty ; + rdfs:comment "A issuingAuthority is TODO" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + core:key a owl:DatatypeProperty ; rdfs:comment """A key used in generic a key-value pair. A key-value pair can be used to implement a dictionary which associates a key with a value.""" ; @@ -1120,7 +1953,7 @@ core:prefix a owl:DatatypeProperty ; core:profile a owl:DatatypeProperty ; rdfs:comment "This field provides information about which profiles the Element belongs to." ; - rdfs:range core:ProfileIdentifier ; + rdfs:range core:ProfileIdentifierType ; ns0:term_status "Stable" . core:relationshipType a owl:DatatypeProperty ; @@ -1132,7 +1965,7 @@ between a Package and a File, between two Packages, or between one SPDXDocument core:releaseTime a owl:DatatypeProperty ; rdfs:comment "A releaseTime specifies the time an artifact was released." ; - rdfs:range xsd:dateTime ; + rdfs:range core:DateTime ; ns0:term_status "Stable" . core:rootElement a owl:ObjectProperty ; @@ -1140,6 +1973,11 @@ core:rootElement a owl:ObjectProperty ; rdfs:range core:Element ; ns0:term_status "Stable" . +core:scope a owl:DatatypeProperty ; + rdfs:comment "A scope is TODO" ; + rdfs:range core:LifecycleScopeType ; + ns0:term_status "Stable" . + core:spdxId a owl:DatatypeProperty ; rdfs:comment """SpdxId uniquely identifies an Element which may thereby be referenced by other Elements. These references may be internal or external. @@ -1155,11 +1993,21 @@ The major version number shall be incremented when incompatible changes between (one or more sections are created, modified or deleted). The minor version number shall be incremented when backwards compatible changes are made. -Here, parties exchanging information in accordance with the SPDX specification need to provide +Here, parties exchanging information in accordance with the SPDX specification need to provide 100% transparency as to which SPDX specification version such information is conforming to.""" ; rdfs:range core:SemVer ; ns0:term_status "Stable" . +core:standard a owl:DatatypeProperty ; + rdfs:comment "Various standards may be relevant to useful to capture for specific artifacts." ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +core:startTime a owl:DatatypeProperty ; + rdfs:comment "A startTime specifies the time from which element is applicable / valid." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + core:statement a owl:DatatypeProperty ; rdfs:comment "A statement is a commentary on an assertion that an annotator has made." ; rdfs:range xsd:string ; @@ -1171,11 +2019,17 @@ core:subject a owl:ObjectProperty ; ns0:term_status "Stable" . core:summary a owl:DatatypeProperty ; - rdfs:comment """A summary is a short description of an Element. Here, the intent is to allow the Element creator to + rdfs:comment """A summary is a short description of an Element. Here, the intent is to allow the Element creator to provide concise information about the function or use of the Element.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . +core:suppliedBy a owl:ObjectProperty ; + rdfs:comment """Identify the actual distribution source for the Artifact being referenced. +This might or might not be different from the originating distribution source for the artifact.""" ; + rdfs:range core:Agent ; + ns0:term_status "Stable" . + core:to a owl:ObjectProperty ; rdfs:comment "This field references an Element on the right-hand side of a relationship." ; rdfs:range core:Element ; @@ -1183,7 +2037,7 @@ core:to a owl:ObjectProperty ; core:validUntilTime a owl:DatatypeProperty ; rdfs:comment "A validUntilTime specifies until when the artifact can be used before its usage needs to be reassessed." ; - rdfs:range xsd:dateTime ; + rdfs:range core:DateTime ; ns0:term_status "Stable" . core:value a owl:DatatypeProperty ; @@ -1197,6 +2051,11 @@ dataset:anonymizationMethodUsed a owl:DatatypeProperty ; rdfs:range xsd:string ; ns0:term_status "Stable" . +dataset:confidentialityLevel a owl:DatatypeProperty ; + rdfs:comment "ConfidentialityLevel describes the levels of confidentiality of the data points contained in the dataset." ; + rdfs:range dataset:ConfidentialityLevelType ; + ns0:term_status "Stable" . + dataset:dataCollectionProcess a owl:DatatypeProperty ; rdfs:comment """DataCollectionProcess describes how a dataset was collected. Examples include the sources from which a dataset was scrapped or @@ -1228,6 +2087,11 @@ The size is to be measured in bytes.""" ; rdfs:range xsd:nonNegativeInteger ; ns0:term_status "Stable" . +dataset:datasetType a owl:DatatypeProperty ; + rdfs:comment "Type describes the datatype contained in the dataset. For example a dataset can be a image dataset or a text dataset or sometimes a multimodal dataset that contains multiple types of data" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + dataset:datasetUpdateMechanism a owl:DatatypeProperty ; rdfs:comment "DatasetUpdateMechanism describes a mechanism to update the dataset." ; rdfs:range xsd:string ; @@ -1235,7 +2099,7 @@ dataset:datasetUpdateMechanism a owl:DatatypeProperty ; dataset:intendedUse a owl:DatatypeProperty ; rdfs:comment """IntendedUse describes what the given dataset should be used for. -Some datasets are collected to be used only for particular purposes. +Some datasets are collected to be used only for particular purposes. For example, medical data collected from a specific demography might only be applicable for training machine learning models to make predictions for that demography. In such a case, the intendedUse field would capture this information. @@ -1249,39 +2113,421 @@ dataset:knownBias a owl:DatatypeProperty ; rdfs:range xsd:string ; ns0:term_status "Stable" . +dataset:sensitivePersonalInformation a owl:DatatypeProperty ; + rdfs:comment """SensitivePersonalInformation indicates the presence of sensitive personal data +or information that allows drawing conclusions about a person's identity.""" ; + rdfs:range dataset:PresenceType ; + ns0:term_status "Stable" . + dataset:sensor a owl:DatatypeProperty ; rdfs:comment """Sensor describes a sensor that was used for collecting the data and its calibration value as a key-value pair.""" ; - rdfs:range ; + rdfs:range core:DictionaryEntry ; + ns0:term_status "Stable" . + +licensing:additionComment a owl:DatatypeProperty ; + rdfs:comment """An additionComment for a LicenseAddition describes general factual information +about the LicenseAddition. It should not contain information (or links to +information) that includes any kind of interpretation about the meaning or +effect of the License, even if written by the license addition's author. + +Examples of information for an additionComment may include the following: + +* If the LicenseAddition's identifier is deprecated, it may briefly explain the + reason for deprecation. +* It may include the date of release, if identified, for LicenseAdditions with + multiple versions. +* It may include links to other official language translations for the + LicenseAddition. +* It may include a reference to the License(s) with which this LicenseAddition + is typically used.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:additionId a owl:DatatypeProperty ; + rdfs:comment """An additionId contains a human-readable, short-form identifier for a +LicenseAddition. It may only include letters, numbers, period (".") and +hyphen ("-") characters. + +For a ListedLicenseException, the licenseId will be as specified on the +[SPDX Exceptions List](https://spdx.org/licenses/exceptions-index.html) for the +particular exception. + +For a CustomLicenseAddition, the short-form identifier must begin with the +prefix `AdditionRef-` and must be unique within the applicable SPDX namespace. +The short-form identifier may be preceded by an SPDX namespace or a +fully-qualified URI prefix.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:additionName a owl:DatatypeProperty ; + rdfs:comment """An additionName contains the full name of a LicenseAddition, preferably using +the title found in the applicable license addition text or file, or as +otherwise specified by the LicenseAddition's author or steward. + +When no such title is specified, using a name from another well-known source or list +of licenses additions (such as OSI or Fedora) is suggested. + +If no official or common name is known, any name may be used to aid in +distinguishing the LicenseAddition from other LicenseAdditions.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:additionText a owl:DatatypeProperty ; + rdfs:comment """An additionText contains the plain text of the LicenseAddition, without +templating or other similar markup. + +Users of the additionText for a License can apply the SPDX Matching Guidelines +when comparing it to another text for matching purposes.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:isDeprecatedAdditionId a owl:DatatypeProperty ; + rdfs:comment """The isDeprecatedAdditionId property specifies whether an identifier for a +LicenseAddition has been marked as deprecated. If the property is not defined, +then it is presumed to be false (i.e., not deprecated). + +If the LicenseAddition is included on the SPDX Exceptions List, then +the `deprecatedVersion` property indicates on which version release of the +Exceptions List it was first marked as deprecated. + +"Deprecated" in this context refers to deprecating the use of the +_identifier_, not the underlying license addition. In other words, even if a +LicenseAddition's author or steward has stated that a particular +LicenseAddition generally should not be used, that would _not_ mean that the +LicenseAddition's identifier is "deprecated." Rather, a LicenseAddition +operator is typically marked as "deprecated" when it is determined that use of +another identifier is preferable.""" ; + rdfs:range xsd:boolean ; + ns0:term_status "Stable" . + +licensing:isDeprecatedLicenseId a owl:DatatypeProperty ; + rdfs:comment """The isDeprecatedLicenseId property specifies whether an identifier for a +License or LicenseAddition has been marked as deprecated. If the property +is not defined, then it is presumed to be false (i.e., not deprecated). + +If the License or LicenseAddition is included on the SPDX License List, then +the `deprecatedVersion` property indicates on which version release of the +License List it was first marked as deprecated. + +"Deprecated" in this context refers to deprecating the use of the +_identifier_, not the underlying license. In other words, even if a License's +author or steward has stated that a particular License generally should not be +used, that would _not_ mean that the License's identifier is "deprecated." +Rather, a License or LicenseAddition operator is typically marked as +"deprecated" when it is determined that use of another identifier is +preferable.""" ; + rdfs:range xsd:boolean ; + ns0:term_status "Stable" . + +licensing:isFsfLibre a owl:DatatypeProperty ; + rdfs:comment """isFsfLibre specifies whether the [Free Software Foundation FSF](https://fsf.org) +has listed this License as "free" in their commentary on licenses, located at +the time of this writing at https://www.gnu.org/licenses/license-list.en.html. + +A value of "true" indicates that the FSF has listed this License as _free_. + +A value of "false" indicates that the FSF has listed this License as _not free_. + +If the isFsfLibre field is not specified, the SPDX data creator makes no +assertions about whether the License is listed in the FSF's commentary.""" ; + rdfs:range xsd:boolean ; + ns0:term_status "Stable" . + +licensing:isOsiApproved a owl:DatatypeProperty ; + rdfs:comment """isOsiApproved specifies whether the [Open Source Initiative (OSI)](https://opensource.org) +has listed this License as "approved" in their list of OSI Approved Licenses, +located at the time of this writing at https://opensource.org/licenses/. + +A value of "true" indicates that the OSI has listed this License as approved. + +A value of "false" indicates that the OSI has not listed this License as +approved. + +If the isOsiApproved field is not specified, the SPDX data creator makes no +assertions about whether the License is approved by the OSI.""" ; + rdfs:range xsd:boolean ; + ns0:term_status "Stable" . + +licensing:licenseComment a owl:DatatypeProperty ; + rdfs:comment """A licenseComment describes general factual information about the License. It +should not contain information (or links to information) that includes any kind +of interpretation about the meaning or effect of the License, even if written +by the license's author. + +Examples of information for a licenseComment may include the following: + +* If the License's identifier is deprecated, it may briefly explain the reason + for deprecation. +* It may include the date of release, if identified, for Licenses with multiple + versions. +* It may include links to other official language translations for the License. +* For LicenseAdditions, it may include a reference to the License(s) with + which this additional text is typically used.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:licenseId a owl:DatatypeProperty ; + rdfs:comment """A licenseId contains a human-readable, short-form license identifier for a +License. It may only include letters, numbers, period (".") and hyphen ("-") +characters. + +For a ListedLicense, the licenseId will be as specified on the +[SPDX License List](https://spdx.org/licenses) for the particular license. + +For a CustomLicense, the short-form license identifer must begin with the +prefix `LicenseRef-` and must be unique within the applicable SPDX namespace. +The short-form license ID may be preceded by an SPDX namespace or a +fully-qualified URI prefix.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:licenseName a owl:DatatypeProperty ; + rdfs:comment """A licenseName contains the full name of a License, preferably using the title found +in the applicable license text or file, or as otherwise specified by the +License's author or steward. + +When no such title is specified, using a name from another well-known source or list +of licenses (such as OSI or Fedora) is suggested. + +If no official or common name is known, any name may be used to aid in +distinguishing the License from other Licenses.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:licenseText a owl:DatatypeProperty ; + rdfs:comment """A licenseText contains the plain text of the License, without templating +or other similar markup. + +Users of the licenseText for a License can apply the SPDX Matching Guidelines +when comparing it to another text for matching purposes.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:standardAdditionTemplate a owl:DatatypeProperty ; + rdfs:comment """A standardAdditionTemplate contains a license addition template which describes +sections of the LicenseAddition text which can be varied. See the Legacy Text +Template format section of the SPDX specification for format information.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:standardLicenseHeader a owl:DatatypeProperty ; + rdfs:comment """A standardLicenseHeader contains the plain text of the License author's +preferred wording to be used, typically in a source code file's header +comments or similar location, to indicate that the file is subject to +the specified License.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:standardLicenseTemplate a owl:DatatypeProperty ; + rdfs:comment """A standardLicenseTemplate contains a license template which describes +sections of the License text which can be varied. See the Legacy Text Template +format section of the SPDX specification for format information.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:subjectAddition a owl:ObjectProperty ; + rdfs:comment """A subjectAddition is a LicenseAddition which is subject to a 'with additional +text' effect (WithAdditionOperator).""" ; + rdfs:range licensing:LicenseAddition ; + ns0:term_status "Stable" . + +security:actionStatement a owl:DatatypeProperty ; + rdfs:comment """When an element is referenced with a VexAffectedVulnAssessmentRelationship, +the relationship MUST include one actionStatement that SHOULD describe actions +to remediate or mitigate the vulnerability.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +security:assessedElement a owl:ObjectProperty ; + rdfs:comment """Specifies subpackages, files or snippets referenced by a security assessment +to specify the precise location where a vulnerability was found.""" ; + rdfs:range core:Element ; + ns0:term_status "Stable" . + +security:decisionType a owl:DatatypeProperty ; + rdfs:comment "A decisionType is a mandatory value and must select one of the four entries in the `SsvcDecisionType.md` vocabulary." ; + rdfs:range security:SsvcDecisionType ; + ns0:term_status "Stable" . + +security:exploited a owl:DatatypeProperty ; + rdfs:comment "This field is set when a CVE is listed in an exploit catalog." ; + rdfs:range xsd:boolean ; + ns0:term_status "Stable" . + +security:impactStatement a owl:DatatypeProperty ; + rdfs:comment """When a VEX product element is related with a VexNotAffectedVulnAssessmentRelationship +and a machine readable justification label is not provided, then an impactStatement +that further explains how or why the prouct(s) are not affected by the vulnerability +must be provided.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +security:justificationType a owl:DatatypeProperty ; + rdfs:comment """When stating that an element is not affected by a vulnerability, the +VexNotAffectedVulnAssessmentRelationship must include a justification from the +machine-readable labels catalog informing the reason the element is not impacted. + +impactStatement which is a string with English prose can be used instead or as +complementary to the justification label, but one of both MUST be defined.""" ; + rdfs:range security:VexJustificationType ; + ns0:term_status "Stable" . + +security:probability a owl:DatatypeProperty ; + rdfs:comment """The probability score between 0 and 1 (0 and 100%) estimating the likelihood +that a vulnerability will be exploited in the next 12 months.""" ; + rdfs:range xsd:decimal ; + ns0:term_status "Stable" . + +software:attributionText a owl:DatatypeProperty ; + rdfs:comment """An attributionText for a software Package, File or Snippet provides a consumer +of SPDX data with acknowledgement content, to assist redistributors of the +Package, File or Snippet with reproducing those acknowledgements. + +For example, this field may include a statement that is required by a +particular license to be reproduced in end-user documentation, advertising +materials, or another form. + +This field may describe where, or in which contexts, the acknowledgements +need to be reproduced, but it is not required to do so. The SPDX data creator +may also explain elsewhere (such as in a licenseComment field) how they intend +for data in this field to be used. + +An attributionText is is not meant to include the software Package, File or +Snippet’s actual complete license text (see concludedLicense to identify the +corresponding license).""" ; + rdfs:range xsd:string ; ns0:term_status "Stable" . software:byteRange a owl:DatatypeProperty ; rdfs:comment """This field defines the byte range in the original host file that the snippet information applies to. -A range of bytes is independent of various formatting concerns, and the most accurate way -of referring to the differences. The choice was made to start the numbering of +A range of bytes is independent of various formatting concerns, and the most accurate way +of referring to the differences. The choice was made to start the numbering of the byte range at 1 to be consistent with the W3C pointer method vocabulary.""" ; - rdfs:range software:positiveIntegerRange ; + rdfs:range core:PositiveIntegerRange ; + ns0:term_status "Stable" . + +software:concludedLicense a owl:ObjectProperty ; + rdfs:comment """A concludedLicense is the license identified by the SPDX data creator, +based on analyzing the license information in the software Package, File +or Snippet and other information to arrive at a reasonably objective +conclusion as to what license governs it. + +If a concludedLicense has a NONE value (NoneLicense), this indicates that the +SPDX data creator has looked and did not find any license information for this +software Package, File or Snippet. + +If a concludedLicense has a NOASSERTION value (NoAssertionLicense), this +indicates that one of the following applies: +* the SPDX data creator has attempted to but cannot reach a reasonable + objective determination; +* the SPDX data creator has made no attempt to determine this field; or +* the SPDX data creator has intentionally provided no information (no + meaning should be implied by doing so). + +A written explanation of a NOASSERTION value (NoAssertionLicense) MAY be +provided in the licenseComment field. + +If the concludedLicense for a software Package, File or Snippet is not the +same as its declaredLicense, a written explanation SHOULD be provided in +the licenseComment field. + +If the declaredLicense for a software Package, File or Snippet is a choice +of more than one license (e.g. a license expression combining two licenses +through use of the `OR` operator), then the concludedLicense may either +retain the license choice or identify which license was chosen.""" ; + rdfs:range software:LicenseField ; + ns0:term_status "Stable" . + +software:conditionality a owl:DatatypeProperty ; + rdfs:comment "A conditionality is TODO" ; + rdfs:range software:DependencyConditionalityType ; + ns0:term_status "Stable" . + +software:contentIdentifier a owl:DatatypeProperty ; + rdfs:comment "A contentIdentifier is TODO" ; + rdfs:range xsd:anyURI ; ns0:term_status "Stable" . software:contentType a owl:DatatypeProperty ; rdfs:comment """This field is a reasonable estimation of the content type of the Element, from a creator perspective. Content type is intrinsic to the Element, independent of how the Element is being used.""" ; - rdfs:range software:mediaType ; + rdfs:range core:MediaType ; + ns0:term_status "Stable" . + +software:copyrightText a owl:ObjectProperty ; + rdfs:comment """A copyrightText consists of the text(s) of the copyright notice(s) found +for a software Package, File or Snippet, if any. + +If a copyrightText contains text, then it may contain any text related to +one or more copyright notices (even if not complete) for that software +Package, File or Snippet. + +If a copyrightText has a "NONE" value, this indicates that the software +Package, File or Snippet contains no copyright notice whatsoever. + +If a copyrightText has a "NOASSERTION" value, this indicates that one of the +following applies: +* the SPDX data creator has attempted to but cannot reach a reasonable + objective determination; +* the SPDX data creator has made no attempt to determine this field; or +* the SPDX data creator has intentionally provided no information (no + meaning should be implied by doing so).""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +software:declaredLicense a owl:ObjectProperty ; + rdfs:comment """A declaredLicense is the license identified in text in the software package, +file or snippet as the license declared by its authors. + +This field is not intended to capture license information obtained from an +external source, such as a package's website. Such information can be +included, as needed, in a concludedLicense field. + +A declaredLicense may be expressed differently in practice for different +types of artifacts. For example: + +* for Packages: + * would include license info describing the license of the Package as a + whole, when it is found in the Package itself (e.g., LICENSE file, + README file, metadata in the repository, etc.) + * would not include any license information that is not in the Package + itself (e.g., license information from the project’s website or from a + third party repository or website) +* for Files: + * would include license info found in the File itself (e.g., license + header or notice, comments, SPDX-License-Identifier expression) + * would not include license info found in a different file (e.g., LICENSE + file in the top directory of a repository) +* for Snippets: + * would include license info found in the Snippet itself (e.g., license + notice, comments, SPDX-License-Identifier expression) + * would not include license info found elsewhere in the File or in a + different File (e.g., comment at top of File if it is not within the + Snippet, LICENSE file in the top directory of a repository) + +If a declaredLicense has a NONE value (NoneLicense), this indicates that the +corresponding Package, File or Snippet contains no license information +whatsoever. + +If a declaredLicense has a NOASSERTION value (NoAssertionLicense), this +indicates that one of the following applies: +* the SPDX data creator has attempted to but cannot reach a reasonable + objective determination; +* the SPDX data creator has made no attempt to determine this field; or +* the SPDX data creator has intentionally provided no information (no meaning + should be implied by doing so).""" ; + rdfs:range software:LicenseField ; ns0:term_status "Stable" . software:downloadLocation a owl:DatatypeProperty ; - rdfs:comment """DownloadLocation identifies the download Uniform Resource Identifier + rdfs:comment """DownloadLocation identifies the download Uniform Resource Identifier for the package at the time that the document was created. -Where and how to download the exact package being referenced +Where and how to download the exact package being referenced is critical for verification and tracking data.""" ; rdfs:range xsd:anyURI ; ns0:term_status "Stable" . -software:filePurpose a owl:DatatypeProperty ; - rdfs:comment "FilePurpose provides information about the primary purpose of the file." ; - rdfs:range software:SoftwarePurpose ; - ns0:term_status "Stable" . - software:homePage a owl:DatatypeProperty ; rdfs:comment """HomePage is a place for the SPDX document creator to record a website that serves as the package's home page. This saves the recipient of the SPDX document who is looking for more info from @@ -1294,14 +2540,9 @@ referenced by the SPDX document creator.""" ; software:lineRange a owl:DatatypeProperty ; rdfs:comment """This field defines the line range in the original host file that the snippet information applies to. If there is a disagreement between the byte range and line range, the byte range values will take precedence. -A range of lines is a convenient reference for those files where there is a known line delimiter. +A range of lines is a convenient reference for those files where there is a known line delimiter. The choice was made to start the numbering of the lines at 1 to be consistent with the W3C pointer method vocabulary.""" ; - rdfs:range software:positiveIntegerRange ; - ns0:term_status "Stable" . - -software:packagePurpose a owl:DatatypeProperty ; - rdfs:comment "PackagePurpose provides information about the primary purpose of the package." ; - rdfs:range software:SoftwarePurpose ; + rdfs:range core:PositiveIntegerRange ; ns0:term_status "Stable" . software:packageUrl a owl:DatatypeProperty ; @@ -1314,15 +2555,27 @@ software:packageVersion a owl:DatatypeProperty ; rdfs:range xsd:string ; ns0:term_status "Stable" . -software:snippetPurpose a owl:DatatypeProperty ; - rdfs:comment "SnippetPurpose provides information about the primary purpose of the snippet." ; +software:purpose a owl:DatatypeProperty ; + rdfs:comment "purpose provides information about the primary purpose of the software artifact." ; rdfs:range software:SoftwarePurpose ; ns0:term_status "Stable" . +software:sbomType a owl:DatatypeProperty ; + rdfs:comment """This field is a reasonable estimation of the type of SBOM created from a creator perspective. +It is intended to be used to give guidance on the elements that may be contained within it. +Aligning with the guidance produced in [Types of Software Bill of Material (SBOM) Documents](https://www.cisa.gov/sites/default/files/2023-04/sbom-types-document-508c.pdf).""" ; + rdfs:range software:SBOMType ; + ns0:term_status "Stable" . + +software:softwareLinkage a owl:DatatypeProperty ; + rdfs:comment "A softwareLinkage is TODO" ; + rdfs:range software:SoftwareDependencyLinkType ; + ns0:term_status "Stable" . + software:sourceInfo a owl:DatatypeProperty ; rdfs:comment """SourceInfo records any relevant background information or additional comments -about the origin of the package. For example, this field might include comments -indicating whether the package was pulled from a source code management system +about the origin of the package. For example, this field might include comments +indicating whether the package was pulled from a source code management system or has been repackaged. The creator can provide additional information to describe any anomalies or discoveries in the determination of the origin of the package.""" ; rdfs:range xsd:string ; @@ -1343,7 +2596,15 @@ core:ExternalIdentifier a owl:Class, rdfs:comment """An ExternalIdentifier is a reference to a resource outside the scope of SPDX-3.0 content that uniquely identifies an Element.""" ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:ExternalIdentifierType ; + sh:property [ sh:datatype xsd:anyURI ; + sh:name "identifierLocator" ; + sh:path core:identifierLocator ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "identifier" ; + sh:path core:identifier ], + [ sh:datatype core:ExternalIdentifierType ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "externalIdentifierType" ; @@ -1352,21 +2613,23 @@ that uniquely identifies an Element.""" ; sh:maxCount 1 ; sh:name "comment" ; sh:path core:comment ], - [ sh:datatype xsd:string ; + [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "identifier" ; - sh:path core:identifier ] . + sh:name "issuingAuthority" ; + sh:path core:issuingAuthority ] . core:ExternalReference a owl:Class, sh:NodeShape ; rdfs:comment """An External Reference points to a resource outside the scope of the SPDX-3.0 content that provides additional characteristics of an Element.""" ; - rdfs:subClassOf core:none ; ns0:term_status "Stable" ; sh:property [ sh:datatype xsd:anyURI ; sh:name "locator" ; sh:path core:locator ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ], [ sh:datatype core:MediaType ; sh:maxCount 1 ; sh:name "contentType" ; @@ -1374,37 +2637,81 @@ that provides additional characteristics of an Element.""" ; [ sh:datatype core:ExternalReferenceType ; sh:maxCount 1 ; sh:name "externalReferenceType" ; - sh:path core:externalReferenceType ], - [ sh:datatype xsd:string ; + sh:path core:externalReferenceType ] . + +core:Hash a owl:Class, + sh:NodeShape ; + rdfs:comment """A hash is a grouping of characteristics unique to the result +of applying a mathematical algorithm +that maps data of arbitrary size to a bit string (the hash) +and is a one-way function, that is, +a function which is practically infeasible to invert. +This is commonly used for integrity checking of data.""" ; + rdfs:subClassOf core:IntegrityMethod ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "comment" ; - sh:path core:comment ] . + sh:minCount 1 ; + sh:name "hashValue" ; + sh:path core:hashValue ], + [ sh:datatype core:HashAlgorithm ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "algorithm" ; + sh:path core:algorithm ] . core:Payload a owl:Class, sh:NodeShape ; rdfs:comment "TODO" ; - rdfs:subClassOf core:none ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:CreationInfo ; + sh:property [ sh:datatype core:NamespaceMap ; + sh:name "namespaces" ; + sh:path core:namespaces ], + [ sh:datatype core:CreationInfo ; sh:maxCount 1 ; sh:name "creationInfo" ; sh:path core:creationInfo ], [ sh:datatype core:ExternalMap ; sh:name "imports" ; - sh:path core:imports ], - [ sh:datatype core:NamespaceMap ; - sh:name "namespaces" ; - sh:path core:namespaces ] . + sh:path core:imports ] . -core:ProfileIdentifier a owl:Class, +core:Relationship a owl:Class, sh:NodeShape ; - rdfs:comment "A profile identifier provides the profile that the Element is specified in." ; - rdfs:subClassOf xsd:string ; - ns0:term_status "Stable" . - -core:SemVer a owl:Class, + rdfs:comment """A Relationship is a grouping of characteristics unique to an assertion +that one Element is related to one or more other Elements in some way.""" ; + rdfs:subClassOf core:Element ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "endTime" ; + sh:path core:endTime ], + [ sh:datatype core:RelationshipType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "relationshipType" ; + sh:path core:relationshipType ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "startTime" ; + sh:path core:startTime ], + [ sh:datatype core:Element ; + sh:name "to" ; + sh:path core:to ], + [ sh:datatype core:RelationshipCompleteness ; + sh:maxCount 1 ; + sh:name "completeness" ; + sh:path core:completeness ], + [ sh:datatype core:Element ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "from" ; + sh:path core:from ] . + +core:SemVer a owl:Class, sh:NodeShape ; - rdfs:comment "The semantic version is a String constrained to the SemVer 2.0.0 specification." ; + rdfs:comment """The semantic version is a string +that is following the specification of [Semantic Versioning 2.0.0](https://semver.org/). +Format restriction: pattern: ^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$""" ; rdfs:subClassOf xsd:string ; ns0:term_status "Stable" . @@ -1420,7 +2727,7 @@ core:contentType a owl:DatatypeProperty ; ns0:term_status "Stable" . core:name a owl:DatatypeProperty ; - rdfs:comment """This field identifies the name of an Element as designated by the creator. + rdfs:comment """This field identifies the name of an Element as designated by the creator. The name of an Element is an important convention and easier to refer to than the URI.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . @@ -1430,14 +2737,125 @@ core:verifiedUsing a owl:ObjectProperty ; rdfs:range core:IntegrityMethod ; ns0:term_status "Stable" . -core:MediaType a owl:Class, - sh:NodeShape ; - rdfs:comment """The MediaType is a String constrained to the RFC 2046 specification. It provides a standardized -way of indicating the type of content of an Element. -A list of all possible media types is available at https://www.iana.org/assignments/media-types/media-types.xhtml.""" ; - rdfs:subClassOf xsd:string ; +licensing:deprecatedVersion a owl:DatatypeProperty ; + rdfs:comment """A deprecatedVersion for a ListedLicense or ListedLicenseException on the SPDX +License List specifies which version release of the License List was the first +one in which it was marked as deprecated.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:listVersionAdded a owl:DatatypeProperty ; + rdfs:comment """A listVersionAdded for a ListedLicense or ListedLicenseException on the SPDX +License List specifies which version release of the License List was the first +one in which it was included.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +licensing:member a owl:ObjectProperty ; + rdfs:comment """A member is a license expression participating in a conjuctive (of type +ConjunctiveLicenseSet) or a disjunctive (of type DisjunctiveLicenseSet) +license set.""" ; + rdfs:range licensing:AnyLicenseInfo ; + ns0:term_status "Stable" . + +licensing:obsoletedBy a owl:DatatypeProperty ; + rdfs:comment """An obsoletedBy value for a deprecated License or LicenseAddition specifies +the licenseId of the replacement License or LicenseAddition that is preferred +to be used in its place. It should use the same format as specified for a +licenseId. + +The License's or LicenseAddition's comment value may include more information +about the reason why the licenseId specified in the obsoletedBy value is +preferred.""" ; + rdfs:range xsd:string ; ns0:term_status "Stable" . +licensing:seeAlso a owl:DatatypeProperty ; + rdfs:comment """A seeAlso defines a cross-reference with a URL where the License or +LicenseAddition can be found in use by one or a few projects. + +If applicable, it should include a URL where the license text is posted by +the license steward, particularly if the license steward has made available a +"canonical" primary URL for the license text. + +If the license is OSI approved, a seeAlso should be included with the URL for +the license's listing on the OSI website. + +The seeAlso URL may refer to a previously-available URL for the License or +LicenseAddition which is no longer active. + +Where applicable, the seeAlso URL should include the license text in its +native language. seeAlso URLs to English or other translations may be included +where multiple, equivalent official translations exist.""" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + +licensing:subjectLicense a owl:ObjectProperty ; + rdfs:comment """A subjectLicense is a License which is subject to either an 'or later' effect +(OrLaterOperator) or a 'with additional text' effect (WithAdditionOperator).""" ; + rdfs:range licensing:License ; + ns0:term_status "Stable" . + +security:modifiedTime a owl:DatatypeProperty ; + rdfs:comment "Specifies a time when a vulnerability assessment was last modified." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +security:publishedTime a owl:DatatypeProperty ; + rdfs:comment "Specifies the time when a vulnerability was first published." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + +security:score a owl:DatatypeProperty ; + rdfs:comment """The score provides information on the severity of a vulnerability per the +Common Vulnerability Scoring System as defined on [https://www.first.org/cvss](https://www.first.org/cvss/).""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +security:vector a owl:DatatypeProperty ; + rdfs:comment """Sepcifies the vector string of a vulnerability, a string combining metrics +from an assessment of its severity.""" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +software:Package a owl:Class, + sh:NodeShape ; + rdfs:comment """A package refers to any unit of content that can be associated with a distribution of software. +Typically, a package is composed of one or more files. +Any of the following non-limiting examples may be (but are not required to be) represented in SPDX as a package: + + - a tarball, zip file or other archive + - a directory or sub-directory + - a separately distributed piece of software which another Package or File uses or depends upon (e.g., a Python package, a Go module, ...) + - a container image, and/or each image layer within a container image + - a collection of one or more sub-packages + - a Git repository snapshot from a particular point in time + +Note that some of these could be represented in SPDX as a file as well. +External property restriction on /Core/Element/name: minCount: 1""" ; + rdfs:subClassOf software:SoftwareArtifact ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "sourceInfo" ; + sh:path software:sourceInfo ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "packageUrl" ; + sh:path software:packageUrl ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "downloadLocation" ; + sh:path software:downloadLocation ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "packageVersion" ; + sh:path software:packageVersion ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "homePage" ; + sh:path software:homePage ] . + core:creationInfo a owl:DatatypeProperty ; rdfs:comment "CreationInfo provides information about the creation of the Element." ; rdfs:range core:CreationInfo ; @@ -1454,45 +2872,80 @@ core:namespaces a owl:DatatypeProperty ; rdfs:range core:NamespaceMap ; ns0:term_status "Stable" . -software:contentIdentifier a owl:DatatypeProperty ; - rdfs:comment "A contentIdentifier is TODO" ; - rdfs:range xsd:anyURI ; +security:ExploitCatalogType a owl:Class ; + rdfs:comment "ExploitCatalogType specifies the type of exploit catalog that a vulnerability is listed in." ; + ns0:term_status "Stable" . + +security:severity a owl:DatatypeProperty ; + rdfs:comment """The severity field provides a human readable string, a label that can be used +as an English adjective that qualifies its numerical score.""" ; + rdfs:range xsd:string ; ns0:term_status "Stable" . +software:SoftwareArtifact a owl:Class, + sh:NodeShape ; + rdfs:comment """A software artifact is a distinct article or unit related to software +such as a package, a file, or a snippet.""" ; + rdfs:subClassOf core:Artifact ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype software:SoftwarePurpose ; + sh:name "purpose" ; + sh:path software:purpose ], + [ sh:datatype licensing:LicenseField ; + sh:maxCount 1 ; + sh:name "concludedLicense" ; + sh:path software:concludedLicense ], + [ sh:datatype licensing:LicenseField ; + sh:maxCount 1 ; + sh:name "declaredLicense" ; + sh:path software:declaredLicense ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "contentIdentifier" ; + sh:path software:contentIdentifier ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "copyrightText" ; + sh:path software:copyrightText ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "attributionText" ; + sh:path software:attributionText ] . + core:AnnotationType a owl:Class ; rdfs:comment "AnnotationType specifies the type of an annotation." ; ns0:term_status "Stable" . core:CreationInfo a owl:Class, sh:NodeShape ; - rdfs:comment """The CreationInfo provides information about who created the Element, and when and how it was created. + rdfs:comment """The CreationInfo provides information about who created the Element, and when and how it was created. The dateTime created is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.""" ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:ProfileIdentifier ; - sh:minCount 1 ; - sh:name "profile" ; - sh:path core:profile ], + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ], + [ sh:datatype core:SemVer ; + sh:name "specVersion" ; + sh:path core:specVersion ], [ sh:datatype core:Entity ; sh:minCount 1 ; sh:name "createdBy" ; sh:path core:createdBy ], - [ sh:datatype core:SemVer ; - sh:name "specVersion" ; - sh:path core:specVersion ], + [ sh:datatype core:ProfileIdentifierType ; + sh:minCount 1 ; + sh:name "profile" ; + sh:path core:profile ], [ sh:datatype core:Tool ; sh:name "createdUsing" ; sh:path core:createdUsing ], - [ sh:datatype xsd:string ; - sh:name "dataLicense" ; - sh:path core:dataLicense ], - [ sh:datatype xsd:dateTime ; + [ sh:datatype core:DateTime ; sh:name "created" ; sh:path core:created ], [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "comment" ; - sh:path core:comment ] . + sh:name "dataLicense" ; + sh:path core:dataLicense ] . core:Entity a owl:Class, sh:NodeShape ; @@ -1506,7 +2959,6 @@ core:ExternalMap a owl:Class, but defined external to that Document. The external map provides details about the externally-defined Element such as its provenance, where to retrieve it, and how to verify its integrity.""" ; - rdfs:subClassOf core:none ; ns0:term_status "Stable" ; sh:property [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; @@ -1521,12 +2973,6 @@ such as its provenance, where to retrieve it, and how to verify its integrity."" sh:name "locationHint" ; sh:path core:locationHint ] . -core:Identity a owl:Class, - sh:NodeShape ; - rdfs:comment "An Identity is a grouping of identifying characteristics unique to an individual or organization." ; - rdfs:subClassOf core:Entity ; - ns0:term_status "Stable" . - core:IntegrityMethod a owl:Class, sh:NodeShape ; rdfs:comment """An IntegrityMethod provides an independently reproducible mechanism that permits verification @@ -1554,8 +3000,111 @@ human-readable and smaller serialized representation of the Elements.""" ; sh:name "namespace" ; sh:path core:namespace ] . +core:PositiveIntegerRange a owl:Class, + sh:NodeShape ; + rdfs:comment """PositiveIntegerRange is a tuple of two positive integers that define a range. +"begin" must be less than or equal to "end".""" ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:positiveInteger ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "end" ; + sh:path core:end ], + [ sh:datatype xsd:positiveInteger ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "begin" ; + sh:path core:begin ] . + +licensing:LicenseAddition a owl:Class, + sh:NodeShape ; + rdfs:comment """A LicenseAddition represents text which is intended to be added to a License +as additional text, but which is not itself intended to be a standalone +License. + +It may be an exception which is listed on the SPDX Exceptions List +(ListedLicenseException), or may be any other additional text (as an exception +or otherwise) which is defined by an SPDX data creator (CustomLicenseAddition).""" ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "additionId" ; + sh:path licensing:additionId ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "additionName" ; + sh:path licensing:additionName ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "standardAdditionTemplate" ; + sh:path licensing:standardAdditionTemplate ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "additionComment" ; + sh:path licensing:additionComment ], + [ sh:datatype xsd:anyURI ; + sh:name "seeAlso" ; + sh:path licensing:seeAlso ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "additionText" ; + sh:path licensing:additionText ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "obsoletedBy" ; + sh:path licensing:obsoletedBy ], + [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:name "isDeprecatedAdditionId" ; + sh:path licensing:isDeprecatedAdditionId ] . + +security:VexVulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """VexVulnAssessmentRelationship is an abstract subclass that defined the common +properties shared by all the SPDX-VEX status relationships. + +**Constraints** + +When linking elements using a VexVulnAssessmentRelationship, the following +requirements must be observed: + +- The from: end must be a /Security/Vulnerability classed element +- The to: end must point to elements representing the VEX _products_. To +specify a different element where the vulnerability was detected, the VEX +relationship can optionally specify _subcomponents_ using the assessedElement +property. + +VEX inherits information from the document level down to its statements. When a +statement is missing information it can be completed by reading the equivalent +field from the containing document. For example, if a VEX relationship is +missing data in its createdBy property, tools must consider the entity +listed in the CreationInfo section of the document as the VEX author. +In the same way, when a VEX relationship does not have a created property, +the document's date must be considered as authoritative.""" ; + rdfs:subClassOf security:VulnAssessmentRelationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "statusNotes" ; + sh:path security:statusNotes ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "vexVersion" ; + sh:path security:vexVersion ] . + +core:MediaType a owl:Class, + sh:NodeShape ; + rdfs:comment """The MediaType is a String constrained to the RFC 2046 specification. It provides a standardized +way of indicating the type of content of an Element. +A list of all possible media types is available at https://www.iana.org/assignments/media-types/media-types.xhtml.""" ; + rdfs:subClassOf xsd:string ; + ns0:term_status "Stable" . + core:RelationshipCompleteness a owl:Class ; - rdfs:comment """RelationshipCompleteness indicates whether a relationship is complete or + rdfs:comment """RelationshipCompleteness indicates whether a relationship is complete or known to be incomplete or if there is made no assertion either way.""" ; ns0:term_status "Stable" . @@ -1565,23 +3114,176 @@ to the readers/reviewers of the document.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . +licensing:License a owl:Class, + sh:NodeShape ; + rdfs:comment """A License represents a license text, whether listed on the SPDX License List +(ListedLicense) or defined by an SPDX data creator (CustomLicense).""" ; + rdfs:subClassOf licensing:AnyLicenseInfo ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "standardLicenseTemplate" ; + sh:path licensing:standardLicenseTemplate ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "licenseName" ; + sh:path licensing:licenseName ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "obsoletedBy" ; + sh:path licensing:obsoletedBy ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "licenseText" ; + sh:path licensing:licenseText ], + [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:name "isDeprecatedLicenseId" ; + sh:path licensing:isDeprecatedLicenseId ], + [ sh:datatype xsd:anyURI ; + sh:name "seeAlso" ; + sh:path licensing:seeAlso ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "licenseComment" ; + sh:path licensing:licenseComment ], + [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:name "isOsiApproved" ; + sh:path licensing:isOsiApproved ], + [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:name "isFsfLibre" ; + sh:path licensing:isFsfLibre ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "licenseId" ; + sh:path licensing:licenseId ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "standardLicenseHeader" ; + sh:path licensing:standardLicenseHeader ] . + +licensing:LicenseField a owl:Class, + sh:NodeShape ; + rdfs:comment """A LicenseField is the primary value that is used by a licensing field for a +software Package, File or Snippet. It represents either a license expression, +or the values NOASSERTION or NONE. The specific meanings of NOASSERTION or +NONE for the particular licensing field are defined in the corresponding +property description.""" ; + ns0:term_status "Stable" . + ai:SafetyRiskAssessmentType a owl:Class ; rdfs:comment """Lists the different safety risk type values that can be used to describe the safety risk of AI software according to [Article 20 of Regulation 765/2008/EC](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).""" ; ns0:term_status "Stable" . +core:Identity a owl:Class, + sh:NodeShape ; + rdfs:comment "An Identity is a grouping of identifying characteristics unique to an individual or organization." ; + rdfs:subClassOf core:Entity ; + ns0:term_status "Stable" . + +dataset:ConfidentialityLevelType a owl:Class ; + rdfs:comment "Describes the different confidentiality levels as given by the [Traffic Light Protocol](https://en.wikipedia.org/wiki/Traffic_Light_Protocol)." ; + ns0:term_status "Stable" . + +security:SsvcDecisionType a owl:Class ; + rdfs:comment "SsvcDecisionType specifies the type of decision that's been made according to the Stakeholder-Specific Vulnerability Categorization (SSVC) system [https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc](https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc)" ; + ns0:term_status "Stable" . + +security:VulnAssessmentRelationship a owl:Class, + sh:NodeShape ; + rdfs:comment """VulnAssessmentRelationship is the ancestor class common to all vulnerability +assessment relationships. It factors out the common properties shared by them.""" ; + rdfs:subClassOf core:Relationship ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "publishedTime" ; + sh:path security:publishedTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "withdrawnTime" ; + sh:path security:withdrawnTime ], + [ sh:datatype core:Identity ; + sh:maxCount 1 ; + sh:name "suppliedBy" ; + sh:path security:suppliedBy ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "modifiedTime" ; + sh:path security:modifiedTime ], + [ sh:datatype core:Element ; + sh:maxCount 1 ; + sh:name "assessedElement" ; + sh:path security:assessedElement ] . + +software:SoftwareDependencyLinkType a owl:Class ; + rdfs:comment "TODO" ; + ns0:term_status "Stable" . + ai:PresenceType a owl:Class ; rdfs:comment "This type is used to indicate if a given field is present or absent or unknown." ; ns0:term_status "Stable" . -core:ExternalReferenceType a owl:Class ; - rdfs:comment "ExteralReferenceType specifies the type of an external reference." ; +dataset:DatasetAvailabilityType a owl:Class ; + rdfs:comment "Describes the possible types of availability of a dataset, indicating whether the dataset can be directly downloaded, can be assembled using a script for scraping the data, is only available after a clickthrough or a registration form." ; + ns0:term_status "Stable" . + +security:VexJustificationType a owl:Class ; + rdfs:comment "VexJustificationType specifies the type of Vulnerability Exploitability eXchange (VEX) justification." ; + ns0:term_status "Stable" . + +software:DependencyConditionalityType a owl:Class ; + rdfs:comment "TODO" ; + ns0:term_status "Stable" . + +core:LifecycleScopeType a owl:Class ; + rdfs:comment "TODO" ; + ns0:term_status "Stable" . + +licensing:AnyLicenseInfo a owl:Class, + sh:NodeShape ; + rdfs:comment """An AnyLicenseInfo is used by a licensing field for a software package, +file or snippet when its value is not NOASSERTION or NONE. It can be a +single license (either on the SPDX License List or a custom-defined license); +a single license with an "or later" operator applied; the foregoing with +additional text applied; or a set of licenses combined by applying "AND" and +"OR" operators recursively.""" ; + rdfs:subClassOf licensing:LicenseField ; + ns0:term_status "Stable" . + +software:SBOMType a owl:Class ; + rdfs:comment """The set of SBOM types with definitions as defined in [Types of Software Bill of Material (SBOM) Documents](https://www.cisa.gov/sites/default/files/2023-04/sbom-types-document-508c.pdf), published on April 21, 2023. +An SBOM type describes the most likely type of an SBOM from the producer perspective, so that consumers can draw conclusions about the data inside an SBOM. A single SBOM can have multiple SBOM document types associated with it.""" ; ns0:term_status "Stable" . core:ExternalIdentifierType a owl:Class ; rdfs:comment "ExteralIdentifierType specifies the type of an external identifier." ; ns0:term_status "Stable" . +core:ProfileIdentifierType a owl:Class ; + rdfs:comment "There are a set of profiles that have been defined to be valid for a specific release This file enumerates the values that have been agreed on, and may be applied to the creation information for an an element." ; + ns0:term_status "Stable" . + +core:DictionaryEntry a owl:Class, + sh:NodeShape ; + rdfs:comment "The class used for implementing a generic string mapping (also known as associative array, dictionary, or hash map) in SPDX. Each DictionaryEntry contains a key-value pair which maps the key to its associated value. To implement a dictionary, this class is to be used in a collection with unique keys." ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "key" ; + sh:path core:key ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "value" ; + sh:path core:value ] . + core:Element a owl:Class, sh:NodeShape ; rdfs:comment """An Element is a representation of a fundamental concept either directly inherent @@ -1592,15 +3294,27 @@ unifying, and interoperable foundation for all explicit and inter-relatable content objects.""" ; rdfs:subClassOf core:Payload ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "comment" ; - sh:path core:comment ], - [ sh:datatype xsd:anyURI ; + sh:property [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "spdxId" ; sh:path core:spdxId ], + [ sh:datatype core:ExternalIdentifier ; + sh:name "externalIdentifier" ; + sh:path core:externalIdentifier ], + [ sh:datatype core:IntegrityMethod ; + sh:name "verifiedUsing" ; + sh:path core:verifiedUsing ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "name" ; + sh:path core:name ], + [ sh:datatype core:Extension ; + sh:name "extension" ; + sh:path core:extension ], + [ sh:datatype core:ExternalReference ; + sh:name "externalReference" ; + sh:path core:externalReference ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "summary" ; @@ -1609,31 +3323,26 @@ and inter-relatable content objects.""" ; sh:maxCount 1 ; sh:name "description" ; sh:path core:description ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "name" ; - sh:path core:name ], [ sh:datatype core:CreationInfo ; sh:maxCount 1 ; - sh:minCount 1 ; sh:name "creationInfo" ; sh:path core:creationInfo ], - [ sh:datatype core:Extension ; - sh:name "extension" ; - sh:path core:extension ], - [ sh:datatype core:ExternalIdentifier ; - sh:name "externalIdentifier" ; - sh:path core:externalIdentifier ], - [ sh:datatype core:IntegrityMethod ; - sh:name "verifiedUsing" ; - sh:path core:verifiedUsing ], - [ sh:datatype core:ExternalReference ; - sh:name "externalReference" ; - sh:path core:externalReference ] . + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ] . -core:HashAlgorithm a owl:Class ; - rdfs:comment """A HashAlgorithm is a mathematical algorithm that maps data of arbitrary size to a bit string (the hash) -and is a one-way function, that is, a function which is practically infeasible to invert.""" ; +core:ExternalReferenceType a owl:Class ; + rdfs:comment "ExteralReferenceType specifies the type of an external reference." ; + ns0:term_status "Stable" . + +core:DateTime a owl:Class, + sh:NodeShape ; + rdfs:comment """A Datetime is a string representation of a specific date and time. +It has resolution of seconds and is always expressed in UTC timezone. +The specific format is one of the most commonly used ISO-8601 formats. +Format restriction: pattern: ^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\dZ$""" ; + rdfs:subClassOf xsd:string ; ns0:term_status "Stable" . software:SoftwarePurpose a owl:Class ; @@ -1644,6 +3353,11 @@ from the producer and consumer perspective from which both parties can draw conc about the context in which the Element exists.""" ; ns0:term_status "Stable" . +core:HashAlgorithm a owl:Class ; + rdfs:comment """A HashAlgorithm is a mathematical algorithm that maps data of arbitrary size to a bit string (the hash) +and is a one-way function, that is, a function which is practically infeasible to invert.""" ; + ns0:term_status "Stable" . + core:RelationshipType a owl:Class ; rdfs:comment """Provides information about the relationship between two Elements. For example, you can represent a relationship between two different Files, diff --git a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py index 8bf122ec2..08d578825 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py +++ b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py @@ -3,16 +3,38 @@ # SPDX-License-Identifier: Apache-2.0 import json -# current workflow: markdown files + spec_parser -> model.ttl -> convert to json_ld: SPDX_OWL.json -> use the function below (needs to be fixed) to generate context.json -# TODO: Enums should look like this: +# current workflow: markdown files + spec_parser -> model.ttl -> convert to json_ld: SPDX_OWL.json -> use the function below to generate context.json +# properties with Enum range should look like this (probably), so that their values are automatically appended with the Enum URI: # "annotationType": { # "@id": "core:annotationType", # "@type": "@vocab", # "@context": { -# "@vocab": "core:AnnotationType#" <- or "/" at the end, who knows +# "@vocab": "core:AnnotationType/" # } # }, +PROPERTIES_WITH_ENUM_RANGE = [ + "safetyRiskAssessment", + "sensitivePersonalInformation", + "annotationType", + "externalIdentifierType", + "externalReferenceType", + "algorithm", + "scope", + "profile", + "completeness", + "relationshipType", + "confidentialityLevel", + "datasetAvailability", + "decisionType", + "justificationType", + "catalogType", + "conditionality", + "sbomType", + "softwareLinkage", + "purpose", +] + def convert_spdx_owl_to_jsonld_context(): with open("SPDX_OWL.json", "r") as infile: owl_dict = json.load(infile) @@ -31,7 +53,16 @@ def convert_spdx_owl_to_jsonld_context(): continue elif node_type in ["owl:DatatypeProperty", "owl:ObjectProperty"]: name = node["@id"].split(":")[-1] - context_dict[name] = {"@id": node["@id"], "@type": node["rdfs:range"]["@id"]} + if name in PROPERTIES_WITH_ENUM_RANGE: + context_dict[name] = { + "@id": node["@id"], + "@type": "@vocab", + "@context": { + "@vocab": node["rdfs:range"]["@id"] + "/" + } + } + else: + context_dict[name] = {"@id": node["@id"], "@type": node["rdfs:range"]["@id"]} elif node_type == "owl:Class": name = node["@id"].split(":")[-1] @@ -44,5 +75,9 @@ def convert_spdx_owl_to_jsonld_context(): else: print(f"unknown node_type: {node_type}") - with open("src/spdx_tools/spdx3/writer/json_ld/context.json", "w") as infile: + with open("context.json", "w") as infile: json.dump(context_dict, infile) + + +if __name__ == "__main__": + convert_spdx_owl_to_jsonld_context() From fa773a5ba001e6a511ee3473dfef30dceb76cbe6 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 28 Apr 2023 08:28:06 +0200 Subject: [PATCH 234/354] add cli functionality to use json ld serialization Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/clitools/pyspdxtools3.py | 15 ++++++++++----- .../spdx3/writer/json_ld/json_ld_writer.py | 5 +++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/spdx_tools/spdx3/clitools/pyspdxtools3.py b/src/spdx_tools/spdx3/clitools/pyspdxtools3.py index f5b00c6e1..c8d87e187 100644 --- a/src/spdx_tools/spdx3/clitools/pyspdxtools3.py +++ b/src/spdx_tools/spdx3/clitools/pyspdxtools3.py @@ -8,11 +8,12 @@ from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document from spdx_tools.spdx3.payload import Payload -from spdx_tools.spdx3.writer.console.payload_writer import write_payload +from spdx_tools.spdx3.writer.console.payload_writer import write_payload as write_payload_to_console from spdx_tools.spdx.model.document import Document from spdx_tools.spdx.parser.parse_anything import parse_file from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document from spdx_tools.spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload @click.command() @@ -22,7 +23,9 @@ @click.option( "--outfile", "-o", - help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion).", + help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion)." + "For now only a prototype serialization to json_ld is available. The provided file will therefore be extended " + "with `_jsonld.json`.", ) @click.option( "--version", @@ -48,10 +51,12 @@ def main(infile: str, outfile: str, version: str, novalidation: bool): sys.exit(1) else: print("The document is valid.", file=sys.stderr) - - if outfile == "-": + if outfile: payload: Payload = bump_spdx_document(document) - write_payload(payload, sys.stdout) + if outfile == "-": + write_payload_to_console(payload, sys.stdout) + else: + write_payload(payload, outfile) except NotImplementedError as err: print(err.args[0]) diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py index 91d120e47..908979350 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 import json +import os from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx3.writer.json_ld.json_ld_converter import convert_payload_to_json_ld_list_of_elements @@ -11,10 +12,10 @@ def write_payload(payload: Payload, file_name: str): element_list = convert_payload_to_json_ld_list_of_elements(payload) # this will be obsolete as soon as the context is publicly available under some URI - with open("context.json", "r") as infile: + with open(os.path.join(os.path.dirname(__file__), "context.json"), "r") as infile: context = json.load(infile) complete_dict = {"@context": context, "element": element_list} - with open(file_name, "w") as out: + with open(file_name + "_jsonld.json", "w") as out: json.dump(complete_dict, out, indent=2) From f26b9fc9af8aac04789d6cd681c2645c0e5a96fe Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 28 Apr 2023 08:39:31 +0200 Subject: [PATCH 235/354] fix linting Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/clitools/pyspdxtools3.py | 6 +++--- .../spdx3/writer/json_ld/json_ld_converter.py | 10 +++++----- src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py | 4 +++- .../spdx3/validation/json_ld/test_shacl_validation.py | 3 ++- tests/spdx3/writer/json_ld/test_json_ld_writer.py | 4 +--- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/spdx_tools/spdx3/clitools/pyspdxtools3.py b/src/spdx_tools/spdx3/clitools/pyspdxtools3.py index c8d87e187..bb0e07883 100644 --- a/src/spdx_tools/spdx3/clitools/pyspdxtools3.py +++ b/src/spdx_tools/spdx3/clitools/pyspdxtools3.py @@ -9,11 +9,11 @@ from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx3.writer.console.payload_writer import write_payload as write_payload_to_console +from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload from spdx_tools.spdx.model.document import Document from spdx_tools.spdx.parser.parse_anything import parse_file from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document from spdx_tools.spdx.validation.validation_message import ValidationMessage -from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload @click.command() @@ -24,8 +24,8 @@ "--outfile", "-o", help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion)." - "For now only a prototype serialization to json_ld is available. The provided file will therefore be extended " - "with `_jsonld.json`.", + "For now only a prototype serialization to json_ld is available. The provided file will therefore be extended " + "with `_jsonld.json`.", ) @click.option( "--version", diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py index 89c9f2a07..df5e56508 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py @@ -3,16 +3,15 @@ # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from enum import Enum -from typing import Dict, Any, List +from typing import Any, List from semantic_version import Version -from spdx_tools.spdx.casing_tools import snake_case_to_camel_case -from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string -from spdx_tools.spdx3.model import Element from spdx_tools.spdx3.model.creation_information import CreationInformation from spdx_tools.spdx3.model.hash import Hash from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.casing_tools import snake_case_to_camel_case +from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string def convert_payload_to_json_ld_list_of_elements(payload: Payload) -> List: @@ -64,7 +63,8 @@ def _convert_to_json_ld_dict(element: Any, alt_creation_info=False, alt_hash=Fal for creation_info_attr_name in vars(attribute_value): creation_info_attr_value = getattr(attribute_value, creation_info_attr_name) element_dict[snake_case_to_camel_case(creation_info_attr_name)] = _convert_to_json_ld_dict( - creation_info_attr_value) + creation_info_attr_value + ) elif attribute_value: if attribute_name == "_spdx_id": diff --git a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py index 08d578825..af04dfaf7 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py +++ b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 import json -# current workflow: markdown files + spec_parser -> model.ttl -> convert to json_ld: SPDX_OWL.json -> use the function below to generate context.json +# current workflow: markdown files + spec_parser -> model.ttl -> convert to json_ld: SPDX_OWL.json -> +# use the function below to generate context.json # properties with Enum range should look like this (probably), so that their values are automatically appended with the Enum URI: # "annotationType": { # "@id": "core:annotationType", @@ -35,6 +36,7 @@ "purpose", ] + def convert_spdx_owl_to_jsonld_context(): with open("SPDX_OWL.json", "r") as infile: owl_dict = json.load(infile) diff --git a/tests/spdx3/validation/json_ld/test_shacl_validation.py b/tests/spdx3/validation/json_ld/test_shacl_validation.py index 2546452d4..b2772ee20 100644 --- a/tests/spdx3/validation/json_ld/test_shacl_validation.py +++ b/tests/spdx3/validation/json_ld/test_shacl_validation.py @@ -7,6 +7,7 @@ def test_shacl_validation(): some_return = validate_against_shacl_from_file( data_file="/home/armin/PycharmProjects/tools-python/tests/SPDX3_jsonld_test.json", - shacl_file="/home/armin/PycharmProjects/tools-python/src/spdx_tools/spdx3/writer/json_ld/model.ttl") + shacl_file="/home/armin/PycharmProjects/tools-python/src/spdx_tools/spdx3/writer/json_ld/model.ttl", + ) print(some_return) diff --git a/tests/spdx3/writer/json_ld/test_json_ld_writer.py b/tests/spdx3/writer/json_ld/test_json_ld_writer.py index fcdf9864b..9e2010b5f 100644 --- a/tests/spdx3/writer/json_ld/test_json_ld_writer.py +++ b/tests/spdx3/writer/json_ld/test_json_ld_writer.py @@ -2,17 +2,15 @@ # # SPDX-License-Identifier: Apache-2.0 -from spdx_tools.spdx.model.document import Document as Spdx2_Document from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload - +from spdx_tools.spdx.model.document import Document as Spdx2_Document from tests.spdx.fixtures import document_fixture def test_json_writer(): spdx2_document: Spdx2_Document = document_fixture() - # spdx2_document: Spdx2_Document = parse_file("/home/armin/PycharmProjects/tools-python/SPDXExample-v2.3.spdx.json") payload: Payload = bump_spdx_document(spdx2_document) # this currently generates an actual file to look at, this should be changed to a temp file later From 0d89d57f8ad0ea6aecf4cfc1790215a16655be0c Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 28 Apr 2023 10:06:01 +0200 Subject: [PATCH 236/354] update file extension Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/clitools/pyspdxtools3.py | 4 ++-- src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/spdx_tools/spdx3/clitools/pyspdxtools3.py b/src/spdx_tools/spdx3/clitools/pyspdxtools3.py index bb0e07883..3a9b45a7a 100644 --- a/src/spdx_tools/spdx3/clitools/pyspdxtools3.py +++ b/src/spdx_tools/spdx3/clitools/pyspdxtools3.py @@ -24,8 +24,8 @@ "--outfile", "-o", help="The file to write the converted document to (write a dash for output to stdout or omit for no conversion)." - "For now only a prototype serialization to json_ld is available. The provided file will therefore be extended " - "with `_jsonld.json`.", + "For now only a prototype serialization to json-ld is available. The provided file will therefore be extended " + "with `.jsonld`.", ) @click.option( "--version", diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py index 908979350..8027ec953 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py @@ -17,5 +17,5 @@ def write_payload(payload: Payload, file_name: str): complete_dict = {"@context": context, "element": element_list} - with open(file_name + "_jsonld.json", "w") as out: + with open(file_name + ".jsonld", "w") as out: json.dump(complete_dict, out, indent=2) From b3566b8ab2f1c5171dadd9396d01281f792a4500 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 28 Apr 2023 08:39:31 +0200 Subject: [PATCH 237/354] fix linting Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py index af04dfaf7..9719301b2 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py +++ b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py @@ -5,7 +5,8 @@ # current workflow: markdown files + spec_parser -> model.ttl -> convert to json_ld: SPDX_OWL.json -> # use the function below to generate context.json -# properties with Enum range should look like this (probably), so that their values are automatically appended with the Enum URI: +# properties with Enum range should look like this (probably), so that their values are automatically appended +# with the Enum URI: # "annotationType": { # "@id": "core:annotationType", # "@type": "@vocab", @@ -37,6 +38,7 @@ ] + def convert_spdx_owl_to_jsonld_context(): with open("SPDX_OWL.json", "r") as infile: owl_dict = json.load(infile) @@ -59,9 +61,7 @@ def convert_spdx_owl_to_jsonld_context(): context_dict[name] = { "@id": node["@id"], "@type": "@vocab", - "@context": { - "@vocab": node["rdfs:range"]["@id"] + "/" - } + "@context": {"@vocab": node["rdfs:range"]["@id"] + "/"}, } else: context_dict[name] = {"@id": node["@id"], "@type": node["rdfs:range"]["@id"]} From eb08dbb059782ca336c489ff2a31b4f945cc31bf Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Fri, 28 Apr 2023 12:47:39 +0200 Subject: [PATCH 238/354] fix writing of relationship property Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py index df5e56508..5f35694de 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py @@ -69,6 +69,8 @@ def _convert_to_json_ld_dict(element: Any, alt_creation_info=False, alt_hash=Fal elif attribute_value: if attribute_name == "_spdx_id": attribute_name = "@id" + if attribute_name == "_from_element": + attribute_name = "from" else: attribute_name = snake_case_to_camel_case(attribute_name) From 715e8dc3d43380ef284d8e80cfdaf45a113ab9fa Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Tue, 2 May 2023 13:01:35 +0200 Subject: [PATCH 239/354] add documentation and update files Signed-off-by: Meret Behrens --- .github/workflows/install_and_test.yml | 1 + pyproject.toml | 2 +- .../validation/json_ld/shacl_validation.py | 14 +++---- .../spdx3/writer/json_ld/owl_to_context.py | 21 +++++----- .../spdx3/writer/json_ld/process.md | 38 +++++++++++++++++++ .../json_ld/test_shacl_validation.py | 19 +++++++--- 6 files changed, 73 insertions(+), 22 deletions(-) create mode 100644 src/spdx_tools/spdx3/writer/json_ld/process.md diff --git a/.github/workflows/install_and_test.yml b/.github/workflows/install_and_test.yml index f0fae5a3c..637d6a473 100644 --- a/.github/workflows/install_and_test.yml +++ b/.github/workflows/install_and_test.yml @@ -28,6 +28,7 @@ jobs: python -m build -nwx . python -m pip install --upgrade ./dist/*.whl python -m pip install pytest + python -m pip install pyshacl shell: bash - name: Run tests run: pytest diff --git a/pyproject.toml b/pyproject.toml index 1cc724e42..19e1aa59a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ dependencies = ["click", "pyyaml", "xmltodict", "rdflib", "beartype", "uritools" dynamic = ["version"] [project.optional-dependencies] -test = ["pytest"] +test = ["pytest", "pyshacl"] code_style = ["isort", "black", "flake8"] graph_generation = ["pygraphviz", "networkx"] development = ["black", "flake8", "isort", "networkx", "pytest"] diff --git a/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py index 7cd14ebb0..466d331a8 100644 --- a/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py +++ b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py @@ -1,21 +1,21 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from typing import Optional + from pyshacl import validate from rdflib import Graph -def validate_against_shacl_from_file(data_file: str, shacl_file: str): +def validate_against_shacl_from_file( + data_file: str, shacl_file: str, data_format: Optional[str] = "json-ld", shacl_format: Optional[str] = "ttl" +): data_graph = Graph() with open(data_file) as file: - data_graph.parse(file, format="json-ld") + data_graph.parse(file, format=data_format) shacl_graph = Graph() with open(shacl_file) as file: - shacl_graph.parse(file, format="ttl") - - return validate_against_shacl(data_graph, shacl_graph) - + shacl_graph.parse(file, format=shacl_format) -def validate_against_shacl(data_graph: Graph, shacl_graph: Graph): return validate(data_graph=data_graph, shacl_graph=shacl_graph) diff --git a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py index 9719301b2..a1a7944bf 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py +++ b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 import json +import os.path # current workflow: markdown files + spec_parser -> model.ttl -> convert to json_ld: SPDX_OWL.json -> # use the function below to generate context.json @@ -38,27 +39,29 @@ ] - -def convert_spdx_owl_to_jsonld_context(): - with open("SPDX_OWL.json", "r") as infile: +def convert_spdx_owl_to_jsonld_context(spdx_owl: str = "SPDX_OWL.json"): + with open(spdx_owl, "r") as infile: owl_dict = json.load(infile) context_dict = { "core": "https://spdx.org/rdf/Core/", "software": "https://spdx.org/rdf/Software/", - "xsd": "http://www.w3.org/2001/XMLSchema/", + "xsd": "http://www.w3.org/2001/XMLSchema#", } for node in owl_dict["@graph"]: - print(node) - node_type = node["@type"] + # print(node) + node_type = node.get("@type") + if not node_type: + # print(node) + continue if "owl:NamedIndividual" in node_type: continue elif node_type in ["owl:DatatypeProperty", "owl:ObjectProperty"]: name = node["@id"].split(":")[-1] if name in PROPERTIES_WITH_ENUM_RANGE: - context_dict[name] = { + context_dict[name] = { "@id": node["@id"], "@type": "@vocab", "@context": {"@vocab": node["rdfs:range"]["@id"] + "/"}, @@ -77,9 +80,9 @@ def convert_spdx_owl_to_jsonld_context(): else: print(f"unknown node_type: {node_type}") - with open("context.json", "w") as infile: + with open(os.path.join(os.path.dirname(__file__), "context.json"), "w") as infile: json.dump(context_dict, infile) if __name__ == "__main__": - convert_spdx_owl_to_jsonld_context() + convert_spdx_owl_to_jsonld_context("SPDX_OWL.json") diff --git a/src/spdx_tools/spdx3/writer/json_ld/process.md b/src/spdx_tools/spdx3/writer/json_ld/process.md new file mode 100644 index 000000000..069b4c137 --- /dev/null +++ b/src/spdx_tools/spdx3/writer/json_ld/process.md @@ -0,0 +1,38 @@ +### Workflow + +Process to produce context file and a serialization example: + +1. Run +``` +spec-parser --gen-md --gen-refs --gen-rdf ../spdx-3-model/model +``` +- spdx-3-model (commit: 6cb4316, last commit where spec-parser is able to run)
+- spec-parser (main with commits from PR 44, 45) + +2. Convert the generated `spec-parser/md_generated/model.ttl` to a json-ld file using https://frogcat.github.io/ttl2jsonld/demo/. +3. Convert owl to context using `convert_spdx_owl_to_jsonld_context("SPDX_OWL.json")`. +4. Place the generated `context.json` in th `spdx_tools/spdx3/writer/jsonld/` . +5. To generate the jsonld from the testfile run +``` +pyspdxtools3 -i ./tests/spdx/data/SPDXJSONExample-v2.3.spdx.json -o example_with_context +``` + + +### Manually + + +### Known limitations +- Validation of enums does not work +- enums should probably look like this in context file +``` +# how to flag vocabularies? +# "annotationType": { +# "@id": "core:annotationType", +# "@type": "@vocab", +# "@context": { +# "@vocab": "core:AnnotationType#" <- or "/" at the end, who knows +# } +# }, +``` +- Additional keys seem to be ignored in validation +- inherited properties aren't validated diff --git a/tests/spdx3/validation/json_ld/test_shacl_validation.py b/tests/spdx3/validation/json_ld/test_shacl_validation.py index b2772ee20..0e24c0665 100644 --- a/tests/spdx3/validation/json_ld/test_shacl_validation.py +++ b/tests/spdx3/validation/json_ld/test_shacl_validation.py @@ -1,13 +1,22 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +import os + +import pytest + from spdx_tools.spdx3.validation.json_ld.shacl_validation import validate_against_shacl_from_file +@pytest.mark.skip("Currently the validation against SHACL fails, refer to process.md and the known limitations.") def test_shacl_validation(): - some_return = validate_against_shacl_from_file( - data_file="/home/armin/PycharmProjects/tools-python/tests/SPDX3_jsonld_test.json", - shacl_file="/home/armin/PycharmProjects/tools-python/src/spdx_tools/spdx3/writer/json_ld/model.ttl", + # insert path to example json ld + conforms, results_graph, results_text = validate_against_shacl_from_file( + data_file=os.path.join(os.path.dirname(__file__), "../../../SPDX3_jsonld_test.json"), + shacl_file=os.path.join( + os.path.dirname(__file__), "../../../../src/spdx_tools/spdx3/writer/json_ld/model.ttl" + ), ) - - print(some_return) + # results_graph.serialize("validation_result.rdf.xml", format="pretty-xml") + print(results_text) + assert conforms From 41cfc3ffd1753fd1652dcc935f34225f2c0ac594 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Thu, 4 May 2023 15:26:18 +0200 Subject: [PATCH 240/354] use graph as surrounding tag Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py index 8027ec953..69a4d763c 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_writer.py @@ -15,7 +15,7 @@ def write_payload(payload: Payload, file_name: str): with open(os.path.join(os.path.dirname(__file__), "context.json"), "r") as infile: context = json.load(infile) - complete_dict = {"@context": context, "element": element_list} + complete_dict = {"@context": context, "@graph": element_list} with open(file_name + ".jsonld", "w") as out: json.dump(complete_dict, out, indent=2) From b6887673bd56e5d9dbf0b1ad9ec8369744776631 Mon Sep 17 00:00:00 2001 From: Meret Behrens Date: Wed, 10 May 2023 14:13:02 +0200 Subject: [PATCH 241/354] implement review comments Signed-off-by: Meret Behrens --- src/spdx_tools/spdx3/writer/json_ld/process.md | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/process.md b/src/spdx_tools/spdx3/writer/json_ld/process.md index 069b4c137..7d04d5ccd 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/process.md +++ b/src/spdx_tools/spdx3/writer/json_ld/process.md @@ -11,7 +11,7 @@ spec-parser --gen-md --gen-refs --gen-rdf ../spdx-3-model/model 2. Convert the generated `spec-parser/md_generated/model.ttl` to a json-ld file using https://frogcat.github.io/ttl2jsonld/demo/. 3. Convert owl to context using `convert_spdx_owl_to_jsonld_context("SPDX_OWL.json")`. -4. Place the generated `context.json` in th `spdx_tools/spdx3/writer/jsonld/` . +4. Place the generated `context.json` in `spdx_tools/spdx3/writer/jsonld/`. 5. To generate the jsonld from the testfile run ``` pyspdxtools3 -i ./tests/spdx/data/SPDXJSONExample-v2.3.spdx.json -o example_with_context @@ -23,16 +23,5 @@ pyspdxtools3 -i ./tests/spdx/data/SPDXJSONExample-v2.3.spdx.json -o example_wit ### Known limitations - Validation of enums does not work -- enums should probably look like this in context file -``` -# how to flag vocabularies? -# "annotationType": { -# "@id": "core:annotationType", -# "@type": "@vocab", -# "@context": { -# "@vocab": "core:AnnotationType#" <- or "/" at the end, who knows -# } -# }, -``` - Additional keys seem to be ignored in validation - inherited properties aren't validated From 38fa5f2dcd054b5f9bd5d23069c7061ec201b240 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 23 May 2023 09:14:02 +0200 Subject: [PATCH 242/354] Adjust test paths for writer and shacl validation tests to fit together Signed-off-by: Holger Frydrych --- tests/spdx3/validation/json_ld/test_shacl_validation.py | 2 +- tests/spdx3/writer/json_ld/test_json_ld_writer.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/spdx3/validation/json_ld/test_shacl_validation.py b/tests/spdx3/validation/json_ld/test_shacl_validation.py index 0e24c0665..df2bfc17f 100644 --- a/tests/spdx3/validation/json_ld/test_shacl_validation.py +++ b/tests/spdx3/validation/json_ld/test_shacl_validation.py @@ -12,7 +12,7 @@ def test_shacl_validation(): # insert path to example json ld conforms, results_graph, results_text = validate_against_shacl_from_file( - data_file=os.path.join(os.path.dirname(__file__), "../../../SPDX3_jsonld_test.json"), + data_file=os.path.join(os.path.dirname(__file__), "../../../SPDX3_jsonld_test.jsonld"), shacl_file=os.path.join( os.path.dirname(__file__), "../../../../src/spdx_tools/spdx3/writer/json_ld/model.ttl" ), diff --git a/tests/spdx3/writer/json_ld/test_json_ld_writer.py b/tests/spdx3/writer/json_ld/test_json_ld_writer.py index 9e2010b5f..1670844db 100644 --- a/tests/spdx3/writer/json_ld/test_json_ld_writer.py +++ b/tests/spdx3/writer/json_ld/test_json_ld_writer.py @@ -14,4 +14,4 @@ def test_json_writer(): payload: Payload = bump_spdx_document(spdx2_document) # this currently generates an actual file to look at, this should be changed to a temp file later - write_payload(payload, "SPDX3_jsonld_test.json") + write_payload(payload, "../../../SPDX3_jsonld_test") From dbede8dbb22a37876878b8ff07cfd44b959b853f Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 23 May 2023 09:14:47 +0200 Subject: [PATCH 243/354] Fix xsd namespace in generated json-ld Signed-off-by: Holger Frydrych --- src/spdx_tools/spdx3/writer/json_ld/context.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/context.json b/src/spdx_tools/spdx3/writer/json_ld/context.json index 064de1672..6616f9d6b 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/context.json +++ b/src/spdx_tools/spdx3/writer/json_ld/context.json @@ -1,7 +1,7 @@ { "core": "https://spdx.org/rdf/Core/", "software": "https://spdx.org/rdf/Software/", - "xsd": "http://www.w3.org/2001/XMLSchema/", + "xsd": "http://www.w3.org/2001/XMLSchema#", "AIPackage": "ai:AIPackage", "Build": "build:Build", "Annotation": "core:Annotation", From 31bf734597a2d908315c0ca01d503893dbfe00b6 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 23 May 2023 11:51:55 +0200 Subject: [PATCH 244/354] Provide named individuals in separate ontology graph during shacl validation Signed-off-by: Holger Frydrych --- .../spdx3/validation/json_ld/shacl_validation.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py index 466d331a8..7720f85f0 100644 --- a/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py +++ b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py @@ -3,8 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Optional +import owlrl from pyshacl import validate -from rdflib import Graph +from rdflib import Graph, RDF def validate_against_shacl_from_file( @@ -18,4 +19,12 @@ def validate_against_shacl_from_file( with open(shacl_file) as file: shacl_graph.parse(file, format=shacl_format) - return validate(data_graph=data_graph, shacl_graph=shacl_graph) + # we need to copy the named individuals created for our vocabulary types to + # an extra ontology graph since pySHACL ignores them in the provided shacl graph. + # if not provided in the ontology graph, validation fails due to those objects not being defined. + ont_graph = Graph() + named_individuals = shacl_graph.subjects(RDF.type, owlrl.OWL.NamedIndividual) + for named_individual in named_individuals: + ont_graph += shacl_graph.triples((named_individual, None, None)) + + return validate(data_graph=data_graph, shacl_graph=shacl_graph, ont_graph=ont_graph) From 8a6c1c16a2f88306b6a9ab167d8d69ecb4de9a95 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 23 May 2023 13:57:14 +0200 Subject: [PATCH 245/354] Enum values for vocabulary type elements must be written in camelized form Signed-off-by: Holger Frydrych --- src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py index 5f35694de..df756c09d 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py @@ -38,7 +38,7 @@ def _convert_to_json_ld_dict(element: Any, alt_creation_info=False, alt_hash=Fal return datetime_to_iso_string(element) if isinstance(element, Enum): - return element.name + return snake_case_to_camel_case(element.name) if isinstance(element, list): return [_convert_to_json_ld_dict(item) for item in element if item] From c8dee74430cdc4c34d9b141acc00eae0c230945c Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 23 May 2023 17:04:17 +0200 Subject: [PATCH 246/354] Add full shacl graph as ontology graph for validation Signed-off-by: Holger Frydrych --- .../spdx3/validation/json_ld/shacl_validation.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py index 7720f85f0..f1f1b77ae 100644 --- a/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py +++ b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py @@ -19,12 +19,4 @@ def validate_against_shacl_from_file( with open(shacl_file) as file: shacl_graph.parse(file, format=shacl_format) - # we need to copy the named individuals created for our vocabulary types to - # an extra ontology graph since pySHACL ignores them in the provided shacl graph. - # if not provided in the ontology graph, validation fails due to those objects not being defined. - ont_graph = Graph() - named_individuals = shacl_graph.subjects(RDF.type, owlrl.OWL.NamedIndividual) - for named_individual in named_individuals: - ont_graph += shacl_graph.triples((named_individual, None, None)) - - return validate(data_graph=data_graph, shacl_graph=shacl_graph, ont_graph=ont_graph) + return validate(data_graph=data_graph, shacl_graph=shacl_graph, ont_graph=shacl_graph) From 45fbc21e1b193f2e0adb98630d5be14230af0590 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Thu, 25 May 2023 10:29:39 +0200 Subject: [PATCH 247/354] Fix json ld converter after CreationInformation was renamed to CreationInfo Signed-off-by: Holger Frydrych --- src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py index df756c09d..dc400dcb1 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py @@ -7,7 +7,7 @@ from semantic_version import Version -from spdx_tools.spdx3.model.creation_information import CreationInformation +from spdx_tools.spdx3.model.creation_info import CreationInfo from spdx_tools.spdx3.model.hash import Hash from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.casing_tools import snake_case_to_camel_case @@ -59,7 +59,7 @@ def _convert_to_json_ld_dict(element: Any, alt_creation_info=False, alt_hash=Fal for attribute_name in vars(element): attribute_value = getattr(element, attribute_name) - if alt_creation_info and isinstance(attribute_value, CreationInformation): + if alt_creation_info and isinstance(attribute_value, CreationInfo): for creation_info_attr_name in vars(attribute_value): creation_info_attr_value = getattr(attribute_value, creation_info_attr_name) element_dict[snake_case_to_camel_case(creation_info_attr_name)] = _convert_to_json_ld_dict( From 3de1e707a8a4a85eb0b86be5766595ff128137d9 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Thu, 25 May 2023 17:12:00 +0200 Subject: [PATCH 248/354] Fix references and profile enum in json ld context Signed-off-by: Holger Frydrych --- .../spdx3/writer/json_ld/owl_to_context.py | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py index a1a7944bf..49119719e 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py +++ b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py @@ -38,6 +38,11 @@ "purpose", ] +REFERENCE_PROPERTY_TYPES = [ + "core:Element", + "core:Agent", +] + def convert_spdx_owl_to_jsonld_context(spdx_owl: str = "SPDX_OWL.json"): with open(spdx_owl, "r") as infile: @@ -60,14 +65,36 @@ def convert_spdx_owl_to_jsonld_context(spdx_owl: str = "SPDX_OWL.json"): continue elif node_type in ["owl:DatatypeProperty", "owl:ObjectProperty"]: name = node["@id"].split(":")[-1] + type_id = node["rdfs:range"]["@id"] if name in PROPERTIES_WITH_ENUM_RANGE: - context_dict[name] = { - "@id": node["@id"], - "@type": "@vocab", - "@context": {"@vocab": node["rdfs:range"]["@id"] + "/"}, - } + if name == "profile": + # FIXME: since the allowed values for the profile enum collide with + # our namespaces, we need to explicitly remap their meaning in the context + context_dict[name] = { + "@id": node["@id"], + "@type": "@vocab", + "@context": { + "core": "https://spdx.org/rdf/Core/ProfileIdentifierType/core", + "software": "https://spdx.org/rdf/Core/ProfileIdentifierType/software", + "licensing": "https://spdx.org/rdf/Core/ProfileIdentifierType/licensing", + "security": "https://spdx.org/rdf/Core/ProfileIdentifierType/security", + "build": "https://spdx.org/rdf/Core/ProfileIdentifierType/build", + "ai": "https://spdx.org/rdf/Core/ProfileIdentifierType/ai", + "dataset": "https://spdx.org/rdf/Core/ProfileIdentifierType/dataset", + "usage": "https://spdx.org/rdf/Core/ProfileIdentifierType/usage", + "extension": "https://spdx.org/rdf/Core/ProfileIdentifierType/extension", + }, + } + else: + context_dict[name] = { + "@id": node["@id"], + "@type": "@vocab", + "@context": {"@vocab": type_id + "/"}, + } + elif node_type == "owl:ObjectProperty" and type_id in REFERENCE_PROPERTY_TYPES: + context_dict[name] = {"@id": node["@id"], "@type": "@id"} else: - context_dict[name] = {"@id": node["@id"], "@type": node["rdfs:range"]["@id"]} + context_dict[name] = {"@id": node["@id"], "@type": type_id} elif node_type == "owl:Class": name = node["@id"].split(":")[-1] From f8ae6cdc2ba411cc91333faa1085395a2eb5287a Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Thu, 25 May 2023 17:59:13 +0200 Subject: [PATCH 249/354] Fix @id field name being accidentally changed to upper case in json ld output Signed-off-by: Holger Frydrych --- src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py index dc400dcb1..ff6f9f1a6 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py @@ -69,7 +69,7 @@ def _convert_to_json_ld_dict(element: Any, alt_creation_info=False, alt_hash=Fal elif attribute_value: if attribute_name == "_spdx_id": attribute_name = "@id" - if attribute_name == "_from_element": + elif attribute_name == "_from_element": attribute_name = "from" else: attribute_name = snake_case_to_camel_case(attribute_name) From bfc94669ea414a784443a93d07e540ee48ce7906 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Fri, 26 May 2023 14:00:49 +0200 Subject: [PATCH 250/354] Update rdf model Signed-off-by: Holger Frydrych --- .../spdx3/writer/json_ld/SPDX_OWL.json | 2207 +++++++++-------- src/spdx_tools/spdx3/writer/json_ld/model.ttl | 1719 +++++++------ 2 files changed, 2077 insertions(+), 1849 deletions(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json b/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json index ab59eba44..e7313911f 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json +++ b/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json @@ -20,7 +20,7 @@ "owl:Class", "sh:NodeShape" ], - "rdfs:comment": "Metadata information that can be added to a package to describe an AI application or trained AI model.\nExternal property restriction on /Core/Artifact/suppliedBy: minCount: 1\nExternal property restriction on /Software/Package/downloadLocation: minCount: 1\nExternal property restriction on /Software/Package/packageVersion: minCount: 1\nExternal property restriction on /Software/SoftwareArtifact/purpose: minCount: 1\nExternal property restriction on /Core/Relationship/relationshipType: minCount: 1\nExternal property restriction on /Core/Artifact/releaseTime: minCount: 1", + "rdfs:comment": "Metadata information that can be added to a package to describe an AI application or trained AI model.\nExternal property restriction on /Core/Artifact/suppliedBy: minCount: 1\nExternal property restriction on /Software/Package/downloadLocation: minCount: 1\nExternal property restriction on /Software/Package/packageVersion: minCount: 1\nExternal property restriction on /Software/SoftwareArtifact/purpose: minCount: 1\nExternal property restriction on /Core/Artifact/releaseTime: minCount: 1", "rdfs:subClassOf": { "@id": "software:Package" }, @@ -28,61 +28,62 @@ "sh:property": [ { "sh:datatype": { - "@id": "ai:PresenceType" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "sensitivePersonalInformation", + "sh:name": "informationAboutApplication", "sh:path": { - "@id": "ai:sensitivePersonalInformation" + "@id": "ai:informationAboutApplication" } }, { "sh:datatype": { - "@id": "core:DictionaryEntry" + "@id": "xsd:string" }, - "sh:name": "metricDecisionThreshold", + "sh:name": "modelDataPreprocessing", "sh:path": { - "@id": "ai:metricDecisionThreshold" + "@id": "ai:modelDataPreprocessing" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:name": "modelExplainability", + "sh:maxCount": 1, + "sh:name": "informationAboutTraining", "sh:path": { - "@id": "ai:modelExplainability" + "@id": "ai:informationAboutTraining" } }, { - "sh:datatype": { + "sh:class": { "@id": "core:DictionaryEntry" }, - "sh:name": "metric", + "sh:name": "hyperparameter", "sh:path": { - "@id": "ai:metric" + "@id": "ai:hyperparameter" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:name": "standardCompliance", + "sh:name": "modelExplainability", "sh:path": { - "@id": "ai:standardCompliance" + "@id": "ai:modelExplainability" } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "core:DictionaryEntry" }, - "sh:name": "domain", + "sh:name": "metric", "sh:path": { - "@id": "ai:domain" + "@id": "ai:metric" } }, { - "sh:datatype": { + "sh:class": { "@id": "ai:SafetyRiskAssessmentType" }, "sh:maxCount": 1, @@ -93,49 +94,49 @@ }, { "sh:datatype": { - "@id": "core:DictionaryEntry" + "@id": "xsd:string" }, - "sh:name": "hyperparameter", + "sh:name": "typeOfModel", "sh:path": { - "@id": "ai:hyperparameter" + "@id": "ai:typeOfModel" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:name": "typeOfModel", + "sh:name": "standardCompliance", "sh:path": { - "@id": "ai:typeOfModel" + "@id": "ai:standardCompliance" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:maxCount": 1, - "sh:name": "energyConsumption", + "sh:name": "domain", "sh:path": { - "@id": "ai:energyConsumption" + "@id": "ai:domain" } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "ai:PresenceType" }, "sh:maxCount": 1, - "sh:name": "informationAboutApplication", + "sh:name": "autonomyType", "sh:path": { - "@id": "ai:informationAboutApplication" + "@id": "ai:autonomyType" } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "ai:PresenceType" }, - "sh:name": "modelDataPreprocessing", + "sh:maxCount": 1, + "sh:name": "sensitivePersonalInformation", "sh:path": { - "@id": "ai:modelDataPreprocessing" + "@id": "ai:sensitivePersonalInformation" } }, { @@ -143,80 +144,79 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "informationAboutTraining", + "sh:name": "limitation", "sh:path": { - "@id": "ai:informationAboutTraining" + "@id": "ai:limitation" } }, { "sh:datatype": { - "@id": "ai:PresenceType" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "autonomyType", + "sh:name": "energyConsumption", "sh:path": { - "@id": "ai:autonomyType" + "@id": "ai:energyConsumption" } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "core:DictionaryEntry" }, - "sh:maxCount": 1, - "sh:name": "limitation", + "sh:name": "metricDecisionThreshold", "sh:path": { - "@id": "ai:limitation" + "@id": "ai:metricDecisionThreshold" } } ] }, { - "@id": "ai:high", + "@id": "https://spdx.org/rdf/AI/PresenceType/no", "@type": [ "owl:NamedIndividual", - "ai:SafetyRiskAssessmentType" + "ai:PresenceType" ] }, { - "@id": "ai:low", + "@id": "https://spdx.org/rdf/AI/PresenceType/noAssertion", "@type": [ "owl:NamedIndividual", - "ai:SafetyRiskAssessmentType" + "ai:PresenceType" ] }, { - "@id": "ai:medium", + "@id": "https://spdx.org/rdf/AI/PresenceType/yes", "@type": [ "owl:NamedIndividual", - "ai:SafetyRiskAssessmentType" + "ai:PresenceType" ] }, { - "@id": "ai:no", + "@id": "https://spdx.org/rdf/AI/SafetyRiskAssessmentType/high", "@type": [ "owl:NamedIndividual", - "ai:PresenceType" + "ai:SafetyRiskAssessmentType" ] }, { - "@id": "ai:noAssertion", + "@id": "https://spdx.org/rdf/AI/SafetyRiskAssessmentType/low", "@type": [ "owl:NamedIndividual", - "ai:PresenceType" + "ai:SafetyRiskAssessmentType" ] }, { - "@id": "ai:serious", + "@id": "https://spdx.org/rdf/AI/SafetyRiskAssessmentType/medium", "@type": [ "owl:NamedIndividual", "ai:SafetyRiskAssessmentType" ] }, { - "@id": "ai:yes", + "@id": "https://spdx.org/rdf/AI/SafetyRiskAssessmentType/serious", "@type": [ "owl:NamedIndividual", - "ai:PresenceType" + "ai:SafetyRiskAssessmentType" ] }, { @@ -236,9 +236,9 @@ "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "buildStartTime", + "sh:name": "buildEndTime", "sh:path": { - "@id": "build:buildStartTime" + "@id": "build:buildEndTime" } }, { @@ -246,75 +246,75 @@ "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "buildEndTime", + "sh:name": "buildStartTime", "sh:path": { - "@id": "build:buildEndTime" + "@id": "build:buildStartTime" } }, { "sh:datatype": { - "@id": "core:DictionaryEntry" + "@id": "xsd:string" }, - "sh:name": "parameters", + "sh:name": "configSourceEntrypoint", "sh:path": { - "@id": "build:parameters" + "@id": "build:configSourceEntrypoint" } }, { - "sh:datatype": { - "@id": "xsd:anyURI" + "sh:class": { + "@id": "core:Hash" }, - "sh:name": "configSourceUri", + "sh:name": "configSourceDigest", "sh:path": { - "@id": "build:configSourceUri" + "@id": "build:configSourceDigest" } }, { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "buildType", + "sh:name": "buildId", "sh:path": { - "@id": "build:buildType" + "@id": "build:buildId" } }, { - "sh:datatype": { + "sh:class": { "@id": "core:DictionaryEntry" }, - "sh:name": "environment", + "sh:name": "parameters", "sh:path": { - "@id": "build:environment" + "@id": "build:parameters" } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "core:DictionaryEntry" }, - "sh:name": "configSourceEntrypoint", + "sh:name": "environment", "sh:path": { - "@id": "build:configSourceEntrypoint" + "@id": "build:environment" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:anyURI" }, "sh:maxCount": 1, - "sh:name": "buildId", + "sh:minCount": 1, + "sh:name": "buildType", "sh:path": { - "@id": "build:buildId" + "@id": "build:buildType" } }, { "sh:datatype": { - "@id": "core:Hash" + "@id": "xsd:anyURI" }, - "sh:name": "configSourceDigest", + "sh:name": "configSourceUri", "sh:path": { - "@id": "build:configSourceDigest" + "@id": "build:configSourceUri" } } ] @@ -333,6 +333,15 @@ "sh:property": [ { "sh:datatype": { + "@id": "core:MediaType" + }, + "sh:name": "contentType", + "sh:path": { + "@id": "core:contentType" + } + }, + { + "sh:class": { "@id": "core:Element" }, "sh:maxCount": 1, @@ -353,16 +362,7 @@ } }, { - "sh:datatype": { - "@id": "core:MediaType" - }, - "sh:name": "contentType", - "sh:path": { - "@id": "core:contentType" - } - }, - { - "sh:datatype": { + "sh:class": { "@id": "core:AnnotationType" }, "sh:maxCount": 1, @@ -374,6 +374,20 @@ } ] }, + { + "@id": "https://spdx.org/rdf/Core/AnnotationType/other", + "@type": [ + "owl:NamedIndividual", + "core:AnnotationType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/AnnotationType/review", + "@type": [ + "owl:NamedIndividual", + "core:AnnotationType" + ] + }, { "@id": "core:AnonymousPayload", "@type": [ @@ -387,16 +401,7 @@ "ns0:term_status": "Stable", "sh:property": [ { - "sh:datatype": { - "@id": "core:ExternalMap" - }, - "sh:name": "imports", - "sh:path": { - "@id": "core:imports" - } - }, - { - "sh:datatype": { + "sh:class": { "@id": "core:CreationInfo" }, "sh:maxCount": 1, @@ -406,993 +411,1057 @@ } }, { - "sh:datatype": { + "sh:class": { "@id": "core:NamespaceMap" }, "sh:name": "namespaces", "sh:path": { "@id": "core:namespaces" } + }, + { + "sh:class": { + "@id": "core:ExternalMap" + }, + "sh:name": "imports", + "sh:path": { + "@id": "core:imports" + } } ] }, { - "@id": "core:Organization", + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/cpe22", "@type": [ - "owl:Class", - "sh:NodeShape" - ], - "rdfs:comment": "An Organization is a group of people who work together in an organized way for a shared purpose.", - "rdfs:subClassOf": { - "@id": "core:Identity" - }, - "ns0:term_status": "Stable" + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] }, { - "@id": "core:Person", + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/cpe23", "@type": [ - "owl:Class", - "sh:NodeShape" - ], - "rdfs:comment": "A Person is an individual human being.", - "rdfs:subClassOf": { - "@id": "core:Identity" - }, - "ns0:term_status": "Stable" + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] }, { - "@id": "core:SpdxDocument", + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/cve", "@type": [ - "owl:Class", - "sh:NodeShape" - ], - "rdfs:comment": "An SpdxDocument assembles a collection of Elements under a common string, the name of the document.\nCommonly used when representing a unit of transfer of SPDX Elements.\nExternal property restriction on /Core/Element/name: minCount: 1", - "rdfs:subClassOf": { - "@id": "core:Bundle" - }, - "ns0:term_status": "Stable", - "sh:property": { - "sh:datatype": { - "@id": "xsd:string" - }, - "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "name", - "sh:path": { - "@id": "core:name" - } - } + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] }, { - "@id": "core:affects", + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/email", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalIdentifierType" ] }, { - "@id": "core:ai", + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/gitoid", "@type": [ "owl:NamedIndividual", - "core:ProfileIdentifierType" + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/other", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" ] }, { - "@id": "core:altDownloadLocation", + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/pkgUrl", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/securityOther", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/swhid", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/swid", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalIdentifierType/urlScheme", + "@type": [ + "owl:NamedIndividual", + "core:ExternalIdentifierType" + ] + }, + { + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/altDownloadLocation", "@type": [ "owl:NamedIndividual", "core:ExternalReferenceType" ] }, { - "@id": "core:altWebPage", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/altWebPage", "@type": [ "owl:NamedIndividual", "core:ExternalReferenceType" ] }, { - "@id": "core:amends", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/binaryArtifact", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { - "@id": "core:ancestor", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/buildMeta", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { - "@id": "core:availableFrom", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/buildSystem", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { - "@id": "core:binaryArtifact", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/chat", "@type": [ "owl:NamedIndividual", "core:ExternalReferenceType" ] }, { - "@id": "core:blake2b256", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/documentation", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:ExternalReferenceType" ] }, { - "@id": "core:blake2b384", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/funding", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:ExternalReferenceType" ] }, { - "@id": "core:blake2b512", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/issueTracker", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:ExternalReferenceType" ] }, { - "@id": "core:blake3", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/license", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:ExternalReferenceType" ] }, { - "@id": "core:build", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/mailingList", "@type": [ "owl:NamedIndividual", - "core:LifecycleScopeType", - "core:ProfileIdentifierType" + "core:ExternalReferenceType" ] }, { - "@id": "core:buildConfigOf", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/metrics", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { - "@id": "core:buildDependency", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/other", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { - "@id": "core:buildHostOf", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/releaseHistory", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { - "@id": "core:buildInputOf", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/releaseNotes", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { - "@id": "core:buildInvokedBy", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/securityAdvisory", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { - "@id": "core:buildMeta", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/securityFix", "@type": [ "owl:NamedIndividual", "core:ExternalReferenceType" ] }, { - "@id": "core:buildOnBehalfOf", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/securityOther", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { - "@id": "core:buildOutputOf", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/socialMedia", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { - "@id": "core:buildSystem", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/sourceArtifact", "@type": [ "owl:NamedIndividual", "core:ExternalReferenceType" ] }, { - "@id": "core:buildTool", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/support", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ExternalReferenceType" ] }, { - "@id": "core:chat", + "@id": "https://spdx.org/rdf/Core/ExternalReferenceType/vcs", "@type": [ "owl:NamedIndividual", "core:ExternalReferenceType" ] }, { - "@id": "core:complete", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/blake2b256", "@type": [ "owl:NamedIndividual", - "core:RelationshipCompleteness" + "core:HashAlgorithm" ] }, { - "@id": "core:contains", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/blake2b384", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:coordinatedBy", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/blake2b512", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:copy", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/blake3", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:core", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/crystalsDilithium", "@type": [ "owl:NamedIndividual", - "core:ProfileIdentifierType" + "core:HashAlgorithm" ] }, { - "@id": "core:cpe22", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/crystalsKyber", "@type": [ "owl:NamedIndividual", - "core:ExternalIdentifierType" + "core:HashAlgorithm" ] }, { - "@id": "core:cpe23", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/falcon", "@type": [ "owl:NamedIndividual", - "core:ExternalIdentifierType" + "core:HashAlgorithm" ] }, { - "@id": "core:crystalsDilithium", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/md2", "@type": [ "owl:NamedIndividual", "core:HashAlgorithm" ] }, { - "@id": "core:crystalsKyber", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/md4", "@type": [ "owl:NamedIndividual", "core:HashAlgorithm" ] }, { - "@id": "core:dataFile", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/md5", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:dataset", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/md6", "@type": [ "owl:NamedIndividual", - "core:ProfileIdentifierType" + "core:HashAlgorithm" ] }, { - "@id": "core:dependencyManifest", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/other", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:dependsOn", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha1", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:descendant", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha224", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:describes", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha256", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:design", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha384", "@type": [ "owl:NamedIndividual", - "core:LifecycleScopeType" + "core:HashAlgorithm" ] }, { - "@id": "core:devDependency", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha3_224", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:devTool", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha3_256", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:development", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha3_384", "@type": [ "owl:NamedIndividual", - "core:LifecycleScopeType" + "core:HashAlgorithm" ] }, { - "@id": "core:distributionArtifact", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha3_512", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:documentation", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sha512", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:doesNotAffect", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/spdxPvcSha1", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:dynamicLink", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/spdxPvcSha256", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:HashAlgorithm" ] }, { - "@id": "core:email", + "@id": "https://spdx.org/rdf/Core/HashAlgorithm/sphincsPlus", "@type": [ "owl:NamedIndividual", - "core:ExternalIdentifierType" + "core:HashAlgorithm" ] }, { - "@id": "core:example", + "@id": "https://spdx.org/rdf/Core/LifecycleScopeType/build", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:LifecycleScopeType" ] }, { - "@id": "core:expandedFromArchive", + "@id": "https://spdx.org/rdf/Core/LifecycleScopeType/design", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:LifecycleScopeType" ] }, { - "@id": "core:exploitCreatedBy", + "@id": "https://spdx.org/rdf/Core/LifecycleScopeType/development", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:LifecycleScopeType" ] }, { - "@id": "core:falcon", + "@id": "https://spdx.org/rdf/Core/LifecycleScopeType/other", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:LifecycleScopeType" ] }, { - "@id": "core:fileAdded", + "@id": "https://spdx.org/rdf/Core/LifecycleScopeType/runtime", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:LifecycleScopeType" ] }, { - "@id": "core:fileDeleted", + "@id": "https://spdx.org/rdf/Core/LifecycleScopeType/test", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:LifecycleScopeType" ] }, { - "@id": "core:fileModified", + "@id": "core:Organization", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An Organization is a group of people who work together in an organized way for a shared purpose.", + "rdfs:subClassOf": { + "@id": "core:Agent" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "core:Person", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Person is an individual human being.", + "rdfs:subClassOf": { + "@id": "core:Agent" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/ai", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ProfileIdentifierType" ] }, { - "@id": "core:fixedBy", + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/build", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ProfileIdentifierType" ] }, { - "@id": "core:fixedIn", + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/core", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ProfileIdentifierType" ] }, { - "@id": "core:foundBy", + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/dataset", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ProfileIdentifierType" ] }, { - "@id": "core:funding", + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/extension", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:ProfileIdentifierType" ] }, { - "@id": "core:generates", + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/licensing", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ProfileIdentifierType" ] }, { - "@id": "core:gitoid", + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/security", "@type": [ "owl:NamedIndividual", - "core:ExternalIdentifierType" + "core:ProfileIdentifierType" ] }, { - "@id": "core:hasAssociatedVulnerability", + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/software", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ProfileIdentifierType" ] }, { - "@id": "core:hasCvssV2AssessmentFor", + "@id": "https://spdx.org/rdf/Core/ProfileIdentifierType/usage", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:ProfileIdentifierType" ] }, { - "@id": "core:hasCvssV3AssessmentFor", + "@id": "https://spdx.org/rdf/Core/RelationshipCompleteness/complete", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:RelationshipCompleteness" ] }, { - "@id": "core:hasEpssAssessmentFor", + "@id": "https://spdx.org/rdf/Core/RelationshipCompleteness/incomplete", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:RelationshipCompleteness" ] }, { - "@id": "core:hasExploitCatalogAssessmentFor", + "@id": "https://spdx.org/rdf/Core/RelationshipCompleteness/noAssertion", "@type": [ "owl:NamedIndividual", - "core:RelationshipType" + "core:RelationshipCompleteness" ] }, { - "@id": "core:hasSsvcAssessmentFor", + "@id": "https://spdx.org/rdf/Core/RelationshipType/affects", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:incomplete", + "@id": "https://spdx.org/rdf/Core/RelationshipType/amends", "@type": [ "owl:NamedIndividual", - "core:RelationshipCompleteness" + "core:RelationshipType" ] }, { - "@id": "core:issueTracker", + "@id": "https://spdx.org/rdf/Core/RelationshipType/ancestor", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:RelationshipType" ] }, { - "@id": "core:license", + "@id": "https://spdx.org/rdf/Core/RelationshipType/availableFrom", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:RelationshipType" ] }, { - "@id": "core:licensing", + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildConfigOf", "@type": [ "owl:NamedIndividual", - "core:ProfileIdentifierType" + "core:RelationshipType" ] }, { - "@id": "core:mailingList", + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildDependency", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:RelationshipType" ] }, { - "@id": "core:md2", + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildHostOf", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:md4", + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildInputOf", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:md5", + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildInvokedBy", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:md6", + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildOnBehalfOf", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:metafile", + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildOutputOf", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:metrics", + "@id": "https://spdx.org/rdf/Core/RelationshipType/buildTool", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:RelationshipType" ] }, { - "@id": "core:noAssertion", + "@id": "https://spdx.org/rdf/Core/RelationshipType/contains", "@type": [ "owl:NamedIndividual", - "core:RelationshipCompleteness" + "core:RelationshipType" ] }, { - "@id": "core:optionalComponent", + "@id": "https://spdx.org/rdf/Core/RelationshipType/coordinatedBy", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:optionalDependency", + "@id": "https://spdx.org/rdf/Core/RelationshipType/copy", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:other", + "@id": "https://spdx.org/rdf/Core/RelationshipType/dataFile", "@type": [ "owl:NamedIndividual", - "core:AnnotationType", - "core:ExternalIdentifierType", - "core:ExternalReferenceType", - "core:HashAlgorithm", - "core:LifecycleScopeType", "core:RelationshipType" ] }, { - "@id": "core:packages", + "@id": "https://spdx.org/rdf/Core/RelationshipType/dependencyManifest", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:patch", + "@id": "https://spdx.org/rdf/Core/RelationshipType/dependsOn", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:pkgUrl", + "@id": "https://spdx.org/rdf/Core/RelationshipType/descendant", "@type": [ "owl:NamedIndividual", - "core:ExternalIdentifierType" + "core:RelationshipType" ] }, { - "@id": "core:prerequisite", + "@id": "https://spdx.org/rdf/Core/RelationshipType/describes", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:providedDependency", + "@id": "https://spdx.org/rdf/Core/RelationshipType/devDependency", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:publishedBy", + "@id": "https://spdx.org/rdf/Core/RelationshipType/devTool", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:releaseHistory", + "@id": "https://spdx.org/rdf/Core/RelationshipType/distributionArtifact", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:RelationshipType" ] }, { - "@id": "core:releaseNotes", + "@id": "https://spdx.org/rdf/Core/RelationshipType/documentation", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:RelationshipType" ] }, { - "@id": "core:reportedBy", + "@id": "https://spdx.org/rdf/Core/RelationshipType/doesNotAffect", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:republishedBy", + "@id": "https://spdx.org/rdf/Core/RelationshipType/dynamicLink", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:requirementFor", + "@id": "https://spdx.org/rdf/Core/RelationshipType/example", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:review", + "@id": "https://spdx.org/rdf/Core/RelationshipType/expandedFromArchive", "@type": [ "owl:NamedIndividual", - "core:AnnotationType" + "core:RelationshipType" ] }, { - "@id": "core:runtime", + "@id": "https://spdx.org/rdf/Core/RelationshipType/exploitCreatedBy", "@type": [ "owl:NamedIndividual", - "core:LifecycleScopeType" + "core:RelationshipType" ] }, { - "@id": "core:runtimeDependency", + "@id": "https://spdx.org/rdf/Core/RelationshipType/fileAdded", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:security", + "@id": "https://spdx.org/rdf/Core/RelationshipType/fileDeleted", "@type": [ "owl:NamedIndividual", - "core:ProfileIdentifierType" + "core:RelationshipType" ] }, { - "@id": "core:securityAdvisory", + "@id": "https://spdx.org/rdf/Core/RelationshipType/fileModified", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:RelationshipType" ] }, { - "@id": "core:securityFix", + "@id": "https://spdx.org/rdf/Core/RelationshipType/fixedBy", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:RelationshipType" ] }, { - "@id": "core:securityOther", + "@id": "https://spdx.org/rdf/Core/RelationshipType/fixedIn", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:RelationshipType" ] }, { - "@id": "core:sha1", + "@id": "https://spdx.org/rdf/Core/RelationshipType/foundBy", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:sha224", + "@id": "https://spdx.org/rdf/Core/RelationshipType/generates", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:sha256", + "@id": "https://spdx.org/rdf/Core/RelationshipType/hasAssessmentFor", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:sha384", + "@id": "https://spdx.org/rdf/Core/RelationshipType/hasAssociatedVulnerability", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:sha3_224", + "@id": "https://spdx.org/rdf/Core/RelationshipType/metafile", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:sha3_256", + "@id": "https://spdx.org/rdf/Core/RelationshipType/optionalComponent", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:sha3_384", + "@id": "https://spdx.org/rdf/Core/RelationshipType/optionalDependency", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:sha3_512", + "@id": "https://spdx.org/rdf/Core/RelationshipType/other", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:sha512", + "@id": "https://spdx.org/rdf/Core/RelationshipType/packages", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:socialMedia", + "@id": "https://spdx.org/rdf/Core/RelationshipType/patch", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:RelationshipType" ] }, { - "@id": "core:software", + "@id": "https://spdx.org/rdf/Core/RelationshipType/prerequisite", "@type": [ "owl:NamedIndividual", - "core:ProfileIdentifierType" + "core:RelationshipType" ] }, { - "@id": "core:sourceArtifact", + "@id": "https://spdx.org/rdf/Core/RelationshipType/providedDependency", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:RelationshipType" ] }, { - "@id": "core:spdxPvcSha1", + "@id": "https://spdx.org/rdf/Core/RelationshipType/publishedBy", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:spdxPvcSha256", + "@id": "https://spdx.org/rdf/Core/RelationshipType/reportedBy", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:specificationFor", + "@id": "https://spdx.org/rdf/Core/RelationshipType/republishedBy", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:sphincsPlus", + "@id": "https://spdx.org/rdf/Core/RelationshipType/requirementFor", "@type": [ "owl:NamedIndividual", - "core:HashAlgorithm" + "core:RelationshipType" ] }, { - "@id": "core:staticLink", + "@id": "https://spdx.org/rdf/Core/RelationshipType/runtimeDependency", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:support", + "@id": "https://spdx.org/rdf/Core/RelationshipType/specificationFor", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "core:RelationshipType" ] }, { - "@id": "core:swhid", + "@id": "https://spdx.org/rdf/Core/RelationshipType/staticLink", "@type": [ "owl:NamedIndividual", - "core:ExternalIdentifierType" + "core:RelationshipType" ] }, { - "@id": "core:swid", + "@id": "https://spdx.org/rdf/Core/RelationshipType/test", "@type": [ "owl:NamedIndividual", - "core:ExternalIdentifierType" + "core:RelationshipType" ] }, { - "@id": "core:test", + "@id": "https://spdx.org/rdf/Core/RelationshipType/testCase", "@type": [ "owl:NamedIndividual", - "core:LifecycleScopeType", "core:RelationshipType" ] }, { - "@id": "core:testCase", + "@id": "https://spdx.org/rdf/Core/RelationshipType/testDependency", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:testDependency", + "@id": "https://spdx.org/rdf/Core/RelationshipType/testTool", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:testTool", + "@id": "https://spdx.org/rdf/Core/RelationshipType/underInvestigationFor", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:underInvestigationFor", + "@id": "https://spdx.org/rdf/Core/RelationshipType/variant", "@type": [ "owl:NamedIndividual", "core:RelationshipType" ] }, { - "@id": "core:urlScheme", + "@id": "core:SoftwareAgent", "@type": [ - "owl:NamedIndividual", - "core:ExternalIdentifierType" - ] + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A SoftwareAgent is a software program that is given the authority (similar to a user's authority) to act on a system.", + "rdfs:subClassOf": { + "@id": "core:Agent" + }, + "ns0:term_status": "Stable" }, { - "@id": "core:usage", + "@id": "core:SpdxDocument", "@type": [ - "owl:NamedIndividual", - "core:ProfileIdentifierType" - ] + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "An SpdxDocument assembles a collection of Elements under a common string, the name of the document.\nCommonly used when representing a unit of transfer of SPDX Elements.\nExternal property restriction on /Core/Element/name: minCount: 1", + "rdfs:subClassOf": { + "@id": "core:Bundle" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "name", + "sh:path": { + "@id": "core:name" + } + } }, { - "@id": "core:variant", - "@type": [ - "owl:NamedIndividual", - "core:RelationshipType" - ] + "@id": "core:spdxId", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "SpdxId uniquely identifies an Element which may thereby be referenced by other Elements.\nThese references may be internal or external.\nWhile there may be several versions of the same Element, each one needs to be able to be referred to uniquely\nso that relationships between Elements can be clearly articulated.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" }, { - "@id": "core:vcs", + "@id": "https://spdx.org/rdf/Dataset/ConfidentialityLevelType/Amber", "@type": [ "owl:NamedIndividual", - "core:ExternalReferenceType" + "dataset:ConfidentialityLevelType" ] }, { - "@id": "dataset:Amber", + "@id": "https://spdx.org/rdf/Dataset/ConfidentialityLevelType/Clear", "@type": [ "owl:NamedIndividual", "dataset:ConfidentialityLevelType" ] }, { - "@id": "dataset:Clear", + "@id": "https://spdx.org/rdf/Dataset/ConfidentialityLevelType/Green", "@type": [ "owl:NamedIndividual", "dataset:ConfidentialityLevelType" ] }, { - "@id": "dataset:Clickthrough", + "@id": "https://spdx.org/rdf/Dataset/ConfidentialityLevelType/Red", "@type": [ "owl:NamedIndividual", - "dataset:DatasetAvailabilityType" + "dataset:ConfidentialityLevelType" ] }, { @@ -1408,22 +1477,22 @@ "ns0:term_status": "Stable", "sh:property": [ { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "dataset:DatasetAvailabilityType" }, - "sh:name": "dataPreprocessing", + "sh:maxCount": 1, + "sh:name": "datasetAvailability", "sh:path": { - "@id": "dataset:dataPreprocessing" + "@id": "dataset:datasetAvailability" } }, { - "sh:datatype": { - "@id": "xsd:nonNegativeInteger" + "sh:class": { + "@id": "core:DictionaryEntry" }, - "sh:maxCount": 1, - "sh:name": "datasetSize", + "sh:name": "sensor", "sh:path": { - "@id": "dataset:datasetSize" + "@id": "dataset:sensor" } }, { @@ -1431,18 +1500,20 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "dataCollectionProcess", + "sh:minCount": 1, + "sh:name": "datasetType", "sh:path": { - "@id": "dataset:dataCollectionProcess" + "@id": "dataset:datasetType" } }, { - "sh:datatype": { - "@id": "core:DictionaryEntry" + "sh:class": { + "@id": "dataset:ConfidentialityLevelType" }, - "sh:name": "sensor", + "sh:maxCount": 1, + "sh:name": "confidentialityLevel", "sh:path": { - "@id": "dataset:sensor" + "@id": "dataset:confidentialityLevel" } }, { @@ -1466,22 +1537,20 @@ }, { "sh:datatype": { - "@id": "dataset:ConfidentialityLevelType" + "@id": "xsd:string" }, - "sh:maxCount": 1, - "sh:name": "confidentialityLevel", + "sh:name": "dataPreprocessing", "sh:path": { - "@id": "dataset:confidentialityLevel" + "@id": "dataset:dataPreprocessing" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:maxCount": 1, - "sh:name": "intendedUse", + "sh:name": "anonymizationMethodUsed", "sh:path": { - "@id": "dataset:intendedUse" + "@id": "dataset:anonymizationMethodUsed" } }, { @@ -1489,28 +1558,29 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "datasetUpdateMechanism", + "sh:name": "datasetNoise", "sh:path": { - "@id": "dataset:datasetUpdateMechanism" + "@id": "dataset:datasetNoise" } }, { "sh:datatype": { - "@id": "dataset:DatasetAvailabilityType" + "@id": "xsd:nonNegativeInteger" }, "sh:maxCount": 1, - "sh:name": "datasetAvailability", + "sh:name": "datasetSize", "sh:path": { - "@id": "dataset:datasetAvailability" + "@id": "dataset:datasetSize" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:name": "anonymizationMethodUsed", + "sh:maxCount": 1, + "sh:name": "intendedUse", "sh:path": { - "@id": "dataset:anonymizationMethodUsed" + "@id": "dataset:intendedUse" } }, { @@ -1518,10 +1588,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "datasetType", + "sh:name": "dataCollectionProcess", "sh:path": { - "@id": "dataset:datasetType" + "@id": "dataset:dataCollectionProcess" } }, { @@ -1529,50 +1598,43 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "datasetNoise", + "sh:name": "datasetUpdateMechanism", "sh:path": { - "@id": "dataset:datasetNoise" + "@id": "dataset:datasetUpdateMechanism" } } ] }, { - "@id": "dataset:Direct-Download", + "@id": "https://spdx.org/rdf/Dataset/DatasetAvailabilityType/Clickthrough", "@type": [ "owl:NamedIndividual", "dataset:DatasetAvailabilityType" ] }, { - "@id": "dataset:Green", - "@type": [ - "owl:NamedIndividual", - "dataset:ConfidentialityLevelType" - ] - }, - { - "@id": "dataset:Query", + "@id": "https://spdx.org/rdf/Dataset/DatasetAvailabilityType/Direct-Download", "@type": [ "owl:NamedIndividual", "dataset:DatasetAvailabilityType" ] }, { - "@id": "dataset:Red", + "@id": "https://spdx.org/rdf/Dataset/DatasetAvailabilityType/Query", "@type": [ "owl:NamedIndividual", - "dataset:ConfidentialityLevelType" + "dataset:DatasetAvailabilityType" ] }, { - "@id": "dataset:Registration", + "@id": "https://spdx.org/rdf/Dataset/DatasetAvailabilityType/Registration", "@type": [ "owl:NamedIndividual", "dataset:DatasetAvailabilityType" ] }, { - "@id": "dataset:Scraping-Script", + "@id": "https://spdx.org/rdf/Dataset/DatasetAvailabilityType/Scraping-Script", "@type": [ "owl:NamedIndividual", "dataset:DatasetAvailabilityType" @@ -1590,7 +1652,7 @@ }, "ns0:term_status": "Stable", "sh:property": { - "sh:datatype": { + "sh:class": { "@id": "licensing:AnyLicenseInfo" }, "sh:minCount": 2, @@ -1636,7 +1698,7 @@ }, "ns0:term_status": "Stable", "sh:property": { - "sh:datatype": { + "sh:class": { "@id": "licensing:AnyLicenseInfo" }, "sh:minCount": 2, @@ -1750,7 +1812,7 @@ }, "ns0:term_status": "Stable", "sh:property": { - "sh:datatype": { + "sh:class": { "@id": "licensing:License" }, "sh:maxCount": 1, @@ -1774,25 +1836,25 @@ "ns0:term_status": "Stable", "sh:property": [ { - "sh:datatype": { - "@id": "licensing:License" + "sh:class": { + "@id": "licensing:LicenseAddition" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "subjectLicense", + "sh:name": "subjectAddition", "sh:path": { - "@id": "licensing:subjectLicense" + "@id": "licensing:subjectAddition" } }, { - "sh:datatype": { - "@id": "licensing:LicenseAddition" + "sh:class": { + "@id": "licensing:License" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "subjectAddition", + "sh:name": "subjectLicense", "sh:path": { - "@id": "licensing:subjectAddition" + "@id": "licensing:subjectLicense" } } ] @@ -1803,7 +1865,7 @@ "owl:Class", "sh:NodeShape" ], - "rdfs:comment": "A CvssV2VulnAssessmentRelationship relationship describes the determined score and vector of a vulnerability using version 2.0 of the Common Vulnerability Scoring System\n(CVSS) as defined on [https://www.first.org/cvss/v2/guide](https://www.first.org/cvss/v2/guide). It is intented to communicate the results of using a CVSS calculator.\n\n**Constraints**\n\nThe value of severity must be one of 'low', 'medium' or 'high'\n\n**Syntax**\n\n```json\n{\n \"@type\": \"CvssV2VulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:cvssv2-cve-2020-28498\",\n \"relationshipType\": \"hasCvssV2AssessmentFor\",\n \"score\": 4.3,\n \"vector\": \"(AV:N/AC:M/Au:N/C:P/I:N/A:N)\",\n \"severity\": \"low\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"externalReferences\": [\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://nvd.nist.gov/vuln/detail/CVE-2020-28498\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityFix\",\n \"locator\": \"https://github.com/indutny/elliptic/commit/441b742\"\n }\n ],\n \"suppliedBy\": [\"urn:spdx.dev:agent-my-security-vendor\"],\n \"publishedTime\": \"2023-05-06T10:06:13Z\"\n},\n{\n \"@type\": \"Relationship\",\n \"@id\": \"urn:spdx.dev:vulnAgentRel-1\", \n \"relationshipType\": \"publishedBy\", \n \"from\": \"urn:spdx.dev:cvssv2-cve-2020-28498\",\n \"to\": [\"urn:spdx.dev:agent-snyk\"],\n \"startTime\": \"2021-03-08T16:06:50Z\"\n}\n```", + "rdfs:comment": "A CvssV2VulnAssessmentRelationship relationship describes the determined score and vector of a vulnerability using version 2.0 of the Common Vulnerability Scoring System\n(CVSS) as defined on [https://www.first.org/cvss/v2/guide](https://www.first.org/cvss/v2/guide). It is intented to communicate the results of using a CVSS calculator.\n\n**Constraints**\n\n- The value of severity must be one of 'low', 'medium' or 'high'\n- The relationship type must be set to hasAssessmentFor.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"CvssV2VulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:cvssv2-cve-2020-28498\",\n \"relationshipType\": \"hasAssessmentFor\",\n \"score\": 4.3,\n \"vector\": \"(AV:N/AC:M/Au:N/C:P/I:N/A:N)\",\n \"severity\": \"low\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"externalReferences\": [\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://nvd.nist.gov/vuln/detail/CVE-2020-28498\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityFix\",\n \"locator\": \"https://github.com/indutny/elliptic/commit/441b742\"\n }\n ],\n \"suppliedBy\": [\"urn:spdx.dev:agent-my-security-vendor\"],\n \"publishedTime\": \"2023-05-06T10:06:13Z\"\n},\n{\n \"@type\": \"Relationship\",\n \"@id\": \"urn:spdx.dev:vulnAgentRel-1\", \n \"relationshipType\": \"publishedBy\", \n \"from\": \"urn:spdx.dev:cvssv2-cve-2020-28498\",\n \"to\": [\"urn:spdx.dev:agent-snyk\"],\n \"startTime\": \"2021-03-08T16:06:50Z\"\n}\n```", "rdfs:subClassOf": { "@id": "security:VulnAssessmentRelationship" }, @@ -1814,30 +1876,30 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "vector", + "sh:name": "severity", "sh:path": { - "@id": "security:vector" + "@id": "security:severity" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:decimal" }, "sh:maxCount": 1, - "sh:name": "severity", + "sh:minCount": 1, + "sh:name": "score", "sh:path": { - "@id": "security:severity" + "@id": "security:score" } }, { "sh:datatype": { - "@id": "xsd:decimal" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "score", + "sh:name": "vector", "sh:path": { - "@id": "security:score" + "@id": "security:vector" } } ] @@ -1848,7 +1910,7 @@ "owl:Class", "sh:NodeShape" ], - "rdfs:comment": "A CvssV3VulnAssessmentRelationship relationship describes the determined score,\nseverity, and vector of a vulnerability using version 3.1 of the Common\nVulnerability Scoring System (CVSS) as defined on \n[https://www.first.org/cvss/v3.1/specification-document](https://www.first.org/cvss/v3.1/specification-document). It is intented to communicate the results of using a CVSS calculator.\n\n**Constraints**\n\nThe value of severity must be one of 'none', 'low', 'medium', 'high' or 'critical'.\nAbsence of the property shall be interpreted as 'none'.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"CvssV3VulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:cvssv3-cve-2020-28498\",\n \"relationshipType\": \"hasCvssV3AssessmentFor\",\n \"severity\": \"medium\",\n \"score\": 6.8,\n \"vector\": \"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"externalReferences\": [\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://nvd.nist.gov/vuln/detail/CVE-2020-28498\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityFix\",\n \"locator\": \"https://github.com/indutny/elliptic/commit/441b742\"\n }\n ],\n \"suppliedBy\": [\"urn:spdx.dev:agent-my-security-vendor\"],\n \"publishedTime\": \"2023-05-06T10:06:13Z\"\n},\n{\n \"@type\": \"Relationship\",\n \"@id\": \"urn:spdx.dev:vulnAgentRel-1\",\n \"relationshipType\": \"publishedBy\",\n \"from\": \"urn:spdx.dev:cvssv3-cve-2020-28498\",\n \"to\": \"urn:spdx.dev:agent-snyk\",\n \"startTime\": \"2021-03-08T16:06:50Z\"\n}\n```", + "rdfs:comment": "A CvssV3VulnAssessmentRelationship relationship describes the determined score,\nseverity, and vector of a vulnerability using version 3.1 of the Common\nVulnerability Scoring System (CVSS) as defined on \n[https://www.first.org/cvss/v3.1/specification-document](https://www.first.org/cvss/v3.1/specification-document). It is intented to communicate the results of using a CVSS calculator.\n\n**Constraints**\n\n- The value of severity must be one of 'none', 'low', 'medium', 'high' or 'critical'.\n- Absence of the property shall be interpreted as 'none'.\n- The relationship type must be set to hasAssessmentFor.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"CvssV3VulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:cvssv3-cve-2020-28498\",\n \"relationshipType\": \"hasAssessmentFor\",\n \"severity\": \"medium\",\n \"score\": 6.8,\n \"vector\": \"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"externalReferences\": [\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://nvd.nist.gov/vuln/detail/CVE-2020-28498\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityAdvisory\",\n \"locator\": \"https://snyk.io/vuln/SNYK-JS-ELLIPTIC-1064899\"\n },\n {\n \"@type\": \"ExternalReference\",\n \"externalReferenceType\": \"securityFix\",\n \"locator\": \"https://github.com/indutny/elliptic/commit/441b742\"\n }\n ],\n \"suppliedBy\": [\"urn:spdx.dev:agent-my-security-vendor\"],\n \"publishedTime\": \"2023-05-06T10:06:13Z\"\n},\n{\n \"@type\": \"Relationship\",\n \"@id\": \"urn:spdx.dev:vulnAgentRel-1\",\n \"relationshipType\": \"publishedBy\",\n \"from\": \"urn:spdx.dev:cvssv3-cve-2020-28498\",\n \"to\": \"urn:spdx.dev:agent-snyk\",\n \"startTime\": \"2021-03-08T16:06:50Z\"\n}\n```", "rdfs:subClassOf": { "@id": "security:VulnAssessmentRelationship" }, @@ -1856,13 +1918,12 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:decimal" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "score", + "sh:name": "severity", "sh:path": { - "@id": "security:score" + "@id": "security:severity" } }, { @@ -1877,12 +1938,13 @@ }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:decimal" }, "sh:maxCount": 1, - "sh:name": "severity", + "sh:minCount": 1, + "sh:name": "score", "sh:path": { - "@id": "security:severity" + "@id": "security:score" } } ] @@ -1893,7 +1955,7 @@ "owl:Class", "sh:NodeShape" ], - "rdfs:comment": "An EpssVulnAssessmentRelationship relationship describes the likelihood or\nprobability that a vulnerability will be exploited in the wild using the Exploit\nPrediction Scoring System (EPSS) as defined on \n[https://www.first.org/epss/model](https://www.first.org/epss/model).\n\n**Syntax**\n\n```json\n{\n \"@type\": \"EpssVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:epss-1\",\n \"relationshipType\": \"hasEpssAssessmentFor\",\n \"probability\": 80,\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:comment": "An EpssVulnAssessmentRelationship relationship describes the likelihood or\nprobability that a vulnerability will be exploited in the wild using the Exploit\nPrediction Scoring System (EPSS) as defined on \n[https://www.first.org/epss/model](https://www.first.org/epss/model).\n\n**Constraints**\n\n- The relationship type must be set to hasAssessmentFor.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"EpssVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:epss-1\",\n \"relationshipType\": \"hasAssessmentFor\",\n \"probability\": 80,\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", "rdfs:subClassOf": { "@id": "security:VulnAssessmentRelationship" }, @@ -1901,34 +1963,48 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:nonNegativeInteger" }, "sh:maxCount": 1, - "sh:name": "severity", + "sh:minCount": 1, + "sh:name": "probability", "sh:path": { - "@id": "security:severity" + "@id": "security:probability" } }, { "sh:datatype": { - "@id": "xsd:nonNegativeInteger" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "probability", + "sh:name": "severity", "sh:path": { - "@id": "security:probability" + "@id": "security:severity" } } ] }, + { + "@id": "https://spdx.org/rdf/Security/ExploitCatalogType/kev", + "@type": [ + "owl:NamedIndividual", + "security:ExploitCatalogType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/ExploitCatalogType/other", + "@type": [ + "owl:NamedIndividual", + "security:ExploitCatalogType" + ] + }, { "@id": "security:ExploitCatalogVulnAssessmentRelationship", "@type": [ "owl:Class", "sh:NodeShape" ], - "rdfs:comment": "An ExploitCatalogVulnAssessmentRelationship describes if a vulnerability is\nlisted in any exploit catalog such as the CISA Known Exploited Vulnerabilities\nCatalog (KEV) \n[https://www.cisa.gov/known-exploited-vulnerabilities-catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog).\n\n**Syntax**\n\n```json\n{\n \"@type\": \"ExploitCatalogVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:exploit-catalog-1\",\n \"relationshipType\": \"hasExploitCatalogAssessmentFor\",\n \"catalogType\": \"kev\",\n \"locator\": \"https://www.cisa.gov/known-exploited-vulnerabilities-catalog\",\n \"exploited\": \"true\",\n \"from\": \"urn:spdx.dev:vuln-cve-2023-2136\",\n \"to\": [\"urn:product-google-chrome-112.0.5615.136\"],\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:comment": "An ExploitCatalogVulnAssessmentRelationship describes if a vulnerability is\nlisted in any exploit catalog such as the CISA Known Exploited Vulnerabilities\nCatalog (KEV) \n[https://www.cisa.gov/known-exploited-vulnerabilities-catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog).\n\n**Constraints**\n\n- The relationship type must be set to hasAssessmentFor.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"ExploitCatalogVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:exploit-catalog-1\",\n \"relationshipType\": \"hasAssessmentFor\",\n \"catalogType\": \"kev\",\n \"locator\": \"https://www.cisa.gov/known-exploited-vulnerabilities-catalog\",\n \"exploited\": \"true\",\n \"from\": \"urn:spdx.dev:vuln-cve-2023-2136\",\n \"to\": [\"urn:product-google-chrome-112.0.5615.136\"],\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", "rdfs:subClassOf": { "@id": "security:VulnAssessmentRelationship" }, @@ -1936,52 +2012,80 @@ "sh:property": [ { "sh:datatype": { - "@id": "security:ExploitCatalogType" + "@id": "xsd:anyURI" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "catalogType", + "sh:name": "locator", "sh:path": { - "@id": "security:catalogType" + "@id": "security:locator" } }, { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:boolean" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "locator", + "sh:name": "exploited", "sh:path": { - "@id": "security:locator" + "@id": "security:exploited" } }, { - "sh:datatype": { - "@id": "xsd:boolean" + "sh:class": { + "@id": "security:ExploitCatalogType" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "exploited", + "sh:name": "catalogType", "sh:path": { - "@id": "security:exploited" + "@id": "security:catalogType" } } ] }, + { + "@id": "https://spdx.org/rdf/Security/SsvcDecisionType/act", + "@type": [ + "owl:NamedIndividual", + "security:SsvcDecisionType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/SsvcDecisionType/attend", + "@type": [ + "owl:NamedIndividual", + "security:SsvcDecisionType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/SsvcDecisionType/track", + "@type": [ + "owl:NamedIndividual", + "security:SsvcDecisionType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/SsvcDecisionType/trackStar", + "@type": [ + "owl:NamedIndividual", + "security:SsvcDecisionType" + ] + }, { "@id": "security:SsvcVulnAssessmentRelationship", "@type": [ "owl:Class", "sh:NodeShape" ], - "rdfs:comment": "An SsvcVulnAssessmentRelationship describes the decision made using the\nStakeholder-Specific Vulnerability Categorization (SSVC) decision tree as\ndefined on [https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc](https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc).\nIt is intended to communicate the results of using the CISA SSVC Calculator.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"SsvcVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:ssvc-1\",\n \"relationshipType\": \"hasSsvcAssessmentFor\",\n \"decisionType\": \"act\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", + "rdfs:comment": "An SsvcVulnAssessmentRelationship describes the decision made using the\nStakeholder-Specific Vulnerability Categorization (SSVC) decision tree as\ndefined on [https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc](https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc).\nIt is intended to communicate the results of using the CISA SSVC Calculator.\n\n**Constraints**\n\n- The relationship type must be set to hasAssessmentFor.\n\n**Syntax**\n\n```json\n{\n \"@type\": \"SsvcVulnAssessmentRelationship\",\n \"@id\": \"urn:spdx.dev:ssvc-1\",\n \"relationshipType\": \"hasAssessmentFor\",\n \"decisionType\": \"act\",\n \"from\": \"urn:spdx.dev:vuln-cve-2020-28498\",\n \"to\": [\"urn:product-acme-application-1.3\"],\n \"assessedElement\": \"urn:npm-elliptic-6.5.2\",\n \"suppliedBy\": [\"urn:spdx.dev:agent-jane-doe\"],\n \"publishedTime\": \"2021-03-09T11:04:53Z\"\n}\n```", "rdfs:subClassOf": { "@id": "security:VulnAssessmentRelationship" }, "ns0:term_status": "Stable", "sh:property": { - "sh:datatype": { + "sh:class": { "@id": "security:SsvcDecisionType" }, "sh:maxCount": 1, @@ -2006,21 +2110,21 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:dateTime" + "@id": "xsd:string" }, - "sh:name": "actionStatementTime", + "sh:maxCount": 1, + "sh:name": "actionStatement", "sh:path": { - "@id": "security:actionStatementTime" + "@id": "security:actionStatement" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "core:DateTime" }, - "sh:maxCount": 1, - "sh:name": "actionStatement", + "sh:name": "actionStatementTime", "sh:path": { - "@id": "security:actionStatement" + "@id": "security:actionStatementTime" } } ] @@ -2037,6 +2141,41 @@ }, "ns0:term_status": "Stable" }, + { + "@id": "https://spdx.org/rdf/Security/VexJustificationType/componentNotPresent", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/VexJustificationType/inlineMitigationsAlreadyExist", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/VexJustificationType/vulnerableCodeCannotBeControlledByAdversary", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/VexJustificationType/vulnerableCodeNotInExecutePath", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, + { + "@id": "https://spdx.org/rdf/Security/VexJustificationType/vulnerableCodeNotPresent", + "@type": [ + "owl:NamedIndividual", + "security:VexJustificationType" + ] + }, { "@id": "security:VexNotAffectedVulnAssessmentRelationship", "@type": [ @@ -2051,7 +2190,7 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:dateTime" + "@id": "core:DateTime" }, "sh:maxCount": 1, "sh:name": "impactStatementTime", @@ -2060,23 +2199,23 @@ } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "security:VexJustificationType" }, "sh:maxCount": 1, - "sh:name": "impactStatement", + "sh:name": "justificationType", "sh:path": { - "@id": "security:impactStatement" + "@id": "security:justificationType" } }, { "sh:datatype": { - "@id": "security:VexJustificationType" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "justificationType", + "sh:name": "impactStatement", "sh:path": { - "@id": "security:justificationType" + "@id": "security:impactStatement" } } ] @@ -2110,9 +2249,9 @@ "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "publishedTime", + "sh:name": "withdrawnTime", "sh:path": { - "@id": "security:publishedTime" + "@id": "security:withdrawnTime" } }, { @@ -2120,9 +2259,9 @@ "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "withdrawnTime", + "sh:name": "publishedTime", "sh:path": { - "@id": "security:withdrawnTime" + "@id": "security:publishedTime" } }, { @@ -2138,112 +2277,103 @@ ] }, { - "@id": "security:act", + "@id": "https://spdx.org/rdf/Software/DependencyConditionalityType/optional", "@type": [ "owl:NamedIndividual", - "security:SsvcDecisionType" + "software:DependencyConditionalityType" ] }, { - "@id": "security:attend", + "@id": "https://spdx.org/rdf/Software/DependencyConditionalityType/other", "@type": [ "owl:NamedIndividual", - "security:SsvcDecisionType" + "software:DependencyConditionalityType" ] }, { - "@id": "security:componentNotPresent", + "@id": "https://spdx.org/rdf/Software/DependencyConditionalityType/prerequisite", "@type": [ "owl:NamedIndividual", - "security:VexJustificationType" + "software:DependencyConditionalityType" ] }, { - "@id": "security:inlineMitigationsAlreadyExist", + "@id": "https://spdx.org/rdf/Software/DependencyConditionalityType/provided", "@type": [ "owl:NamedIndividual", - "security:VexJustificationType" + "software:DependencyConditionalityType" ] }, { - "@id": "security:kev", + "@id": "https://spdx.org/rdf/Software/DependencyConditionalityType/required", "@type": [ "owl:NamedIndividual", - "security:ExploitCatalogType" + "software:DependencyConditionalityType" ] }, { - "@id": "security:other", + "@id": "software:File", "@type": [ - "owl:NamedIndividual", - "security:ExploitCatalogType" - ] + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "Refers to any object that stores content on a computer.\nThe type of content can optionally be provided in the contentType property.\nExternal property restriction on /Core/Element/name: minCount: 1", + "rdfs:subClassOf": { + "@id": "software:SoftwareArtifact" + }, + "ns0:term_status": "Stable", + "sh:property": { + "sh:datatype": { + "@id": "core:MediaType" + }, + "sh:maxCount": 1, + "sh:name": "contentType", + "sh:path": { + "@id": "software:contentType" + } + } }, { - "@id": "security:track", + "@id": "https://spdx.org/rdf/Software/SBOMType/analyzed", "@type": [ "owl:NamedIndividual", - "security:SsvcDecisionType" + "software:SBOMType" ] }, { - "@id": "security:trackStar", + "@id": "https://spdx.org/rdf/Software/SBOMType/build", "@type": [ "owl:NamedIndividual", - "security:SsvcDecisionType" + "software:SBOMType" ] }, { - "@id": "security:vulnerableCodeCannotBeControlledByAdversary", + "@id": "https://spdx.org/rdf/Software/SBOMType/deployed", "@type": [ "owl:NamedIndividual", - "security:VexJustificationType" + "software:SBOMType" ] }, { - "@id": "security:vulnerableCodeNotInExecutePath", + "@id": "https://spdx.org/rdf/Software/SBOMType/design", "@type": [ "owl:NamedIndividual", - "security:VexJustificationType" + "software:SBOMType" ] }, { - "@id": "security:vulnerableCodeNotPresent", + "@id": "https://spdx.org/rdf/Software/SBOMType/runtime", "@type": [ "owl:NamedIndividual", - "security:VexJustificationType" + "software:SBOMType" ] }, { - "@id": "security:withdrawn", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "Specified the time and date when a vulnerability was withdrawn.", - "rdfs:range": { - "@id": "core:DateTime" - }, - "ns0:term_status": "Stable" - }, - { - "@id": "software:File", + "@id": "https://spdx.org/rdf/Software/SBOMType/source", "@type": [ - "owl:Class", - "sh:NodeShape" - ], - "rdfs:comment": "Refers to any object that stores content on a computer.\nThe type of content can optionally be provided in the contentType property.\nExternal property restriction on /Core/Element/name: minCount: 1", - "rdfs:subClassOf": { - "@id": "software:SoftwareArtifact" - }, - "ns0:term_status": "Stable", - "sh:property": { - "sh:datatype": { - "@id": "core:MediaType" - }, - "sh:maxCount": 1, - "sh:name": "contentType", - "sh:path": { - "@id": "software:contentType" - } - } + "owl:NamedIndividual", + "software:SBOMType" + ] }, { "@id": "software:Sbom", @@ -2257,7 +2387,7 @@ }, "ns0:term_status": "Stable", "sh:property": { - "sh:datatype": { + "sh:class": { "@id": "software:SBOMType" }, "sh:name": "sbomType", @@ -2279,307 +2409,248 @@ "ns0:term_status": "Stable", "sh:property": [ { - "sh:datatype": { - "@id": "core:PositiveIntegerRange" - }, - "sh:maxCount": 1, - "sh:name": "lineRange", - "sh:path": { - "@id": "software:lineRange" - } - }, - { - "sh:datatype": { - "@id": "core:PositiveIntegerRange" - }, - "sh:maxCount": 1, - "sh:name": "byteRange", - "sh:path": { - "@id": "software:byteRange" - } - } - ] - }, - { - "@id": "software:SoftwareDependencyRelationship", - "@type": [ - "owl:Class", - "sh:NodeShape" - ], - "rdfs:comment": "TODO", - "rdfs:subClassOf": { - "@id": "core:LifecycleScopedRelationship" - }, - "ns0:term_status": "Stable", - "sh:property": [ - { - "sh:datatype": { - "@id": "software:DependencyConditionalityType" + "sh:class": { + "@id": "core:PositiveIntegerRange" }, "sh:maxCount": 1, - "sh:name": "conditionality", + "sh:name": "lineRange", "sh:path": { - "@id": "software:conditionality" + "@id": "software:lineRange" } }, { - "sh:datatype": { - "@id": "software:SoftwareDependencyLinkType" + "sh:class": { + "@id": "core:PositiveIntegerRange" }, "sh:maxCount": 1, - "sh:name": "softwareLinkage", + "sh:name": "byteRange", "sh:path": { - "@id": "software:softwareLinkage" + "@id": "software:byteRange" } } ] }, { - "@id": "software:analyzed", + "@id": "https://spdx.org/rdf/Software/SoftwareDependencyLinkType/dynamic", "@type": [ "owl:NamedIndividual", - "software:SBOMType" + "software:SoftwareDependencyLinkType" ] }, { - "@id": "software:application", + "@id": "https://spdx.org/rdf/Software/SoftwareDependencyLinkType/other", "@type": [ "owl:NamedIndividual", - "software:SoftwarePurpose" + "software:SoftwareDependencyLinkType" ] }, { - "@id": "software:archive", + "@id": "https://spdx.org/rdf/Software/SoftwareDependencyLinkType/static", "@type": [ "owl:NamedIndividual", - "software:SoftwarePurpose" + "software:SoftwareDependencyLinkType" ] }, { - "@id": "software:bom", + "@id": "https://spdx.org/rdf/Software/SoftwareDependencyLinkType/tool", "@type": [ "owl:NamedIndividual", - "software:SoftwarePurpose" + "software:SoftwareDependencyLinkType" ] }, { - "@id": "software:build", + "@id": "software:SoftwareDependencyRelationship", "@type": [ - "owl:NamedIndividual", - "software:SBOMType" + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "TODO", + "rdfs:subClassOf": { + "@id": "core:LifecycleScopedRelationship" + }, + "ns0:term_status": "Stable", + "sh:property": [ + { + "sh:class": { + "@id": "software:SoftwareDependencyLinkType" + }, + "sh:maxCount": 1, + "sh:name": "softwareLinkage", + "sh:path": { + "@id": "software:softwareLinkage" + } + }, + { + "sh:class": { + "@id": "software:DependencyConditionalityType" + }, + "sh:maxCount": 1, + "sh:name": "conditionality", + "sh:path": { + "@id": "software:conditionality" + } + } ] }, { - "@id": "software:configuration", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/application", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:container", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/archive", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:data", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/bom", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:deployed", - "@type": [ - "owl:NamedIndividual", - "software:SBOMType" - ] - }, - { - "@id": "software:design", - "@type": [ - "owl:NamedIndividual", - "software:SBOMType" - ] - }, - { - "@id": "software:device", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/configuration", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:documentation", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/container", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:dynamic", - "@type": [ - "owl:NamedIndividual", - "software:SoftwareDependencyLinkType" - ] - }, - { - "@id": "software:evidence", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/data", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:executable", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/device", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:file", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/documentation", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:firmware", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/evidence", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:framework", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/executable", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:install", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/file", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:library", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/firmware", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:manifest", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/framework", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:module", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/install", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:operatingSystem", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/library", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:optional", - "@type": [ - "owl:NamedIndividual", - "software:DependencyConditionalityType" - ] - }, - { - "@id": "software:other", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/manifest", "@type": [ "owl:NamedIndividual", - "software:DependencyConditionalityType", - "software:SoftwareDependencyLinkType", "software:SoftwarePurpose" ] }, { - "@id": "software:patch", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/module", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:prerequisite", - "@type": [ - "owl:NamedIndividual", - "software:DependencyConditionalityType" - ] - }, - { - "@id": "software:provided", - "@type": [ - "owl:NamedIndividual", - "software:DependencyConditionalityType" - ] - }, - { - "@id": "software:required", - "@type": [ - "owl:NamedIndividual", - "software:DependencyConditionalityType" - ] - }, - { - "@id": "software:requirement", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/operatingSystem", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:runtime", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/other", "@type": [ "owl:NamedIndividual", - "software:SBOMType" + "software:SoftwarePurpose" ] }, { - "@id": "software:source", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/patch", "@type": [ "owl:NamedIndividual", - "software:SBOMType", "software:SoftwarePurpose" ] }, { - "@id": "software:specification", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/requirement", "@type": [ "owl:NamedIndividual", "software:SoftwarePurpose" ] }, { - "@id": "software:static", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/source", "@type": [ "owl:NamedIndividual", - "software:SoftwareDependencyLinkType" + "software:SoftwarePurpose" ] }, { - "@id": "software:tool", + "@id": "https://spdx.org/rdf/Software/SoftwarePurpose/specification", "@type": [ "owl:NamedIndividual", - "software:SoftwareDependencyLinkType" + "software:SoftwarePurpose" ] }, { @@ -2811,8 +2882,8 @@ "ns0:term_status": "Stable", "sh:property": [ { - "sh:datatype": { - "@id": "core:Identity" + "sh:class": { + "@id": "core:Agent" }, "sh:name": "suppliedBy", "sh:path": { @@ -2824,28 +2895,28 @@ "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "validUntilTime", + "sh:name": "releaseTime", "sh:path": { - "@id": "core:validUntilTime" + "@id": "core:releaseTime" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "core:DateTime" }, - "sh:name": "standard", + "sh:maxCount": 1, + "sh:name": "validUntilTime", "sh:path": { - "@id": "core:standard" + "@id": "core:validUntilTime" } }, { - "sh:datatype": { - "@id": "core:DateTime" + "sh:class": { + "@id": "core:Agent" }, - "sh:maxCount": 1, - "sh:name": "releaseTime", + "sh:name": "originatedBy", "sh:path": { - "@id": "core:releaseTime" + "@id": "core:originatedBy" } }, { @@ -2860,11 +2931,11 @@ }, { "sh:datatype": { - "@id": "core:Identity" + "@id": "xsd:string" }, - "sh:name": "originatedBy", + "sh:name": "standard", "sh:path": { - "@id": "core:originatedBy" + "@id": "core:standard" } } ] @@ -2894,41 +2965,41 @@ "ns0:term_status": "Stable", "sh:property": [ { - "sh:datatype": { - "@id": "core:Element" + "sh:class": { + "@id": "core:ExternalMap" }, - "sh:minCount": 1, - "sh:name": "rootElement", + "sh:name": "imports", "sh:path": { - "@id": "core:rootElement" + "@id": "core:imports" } }, { - "sh:datatype": { - "@id": "core:ExternalMap" + "sh:class": { + "@id": "core:NamespaceMap" }, - "sh:name": "imports", + "sh:name": "namespaces", "sh:path": { - "@id": "core:imports" + "@id": "core:namespaces" } }, { - "sh:datatype": { + "sh:class": { "@id": "core:Element" }, "sh:minCount": 1, - "sh:name": "element", + "sh:name": "rootElement", "sh:path": { - "@id": "core:element" + "@id": "core:rootElement" } }, { - "sh:datatype": { - "@id": "core:NamespaceMap" + "sh:class": { + "@id": "core:Element" }, - "sh:name": "namespaces", + "sh:minCount": 1, + "sh:name": "element", "sh:path": { - "@id": "core:namespaces" + "@id": "core:element" } } ] @@ -2945,7 +3016,7 @@ }, "ns0:term_status": "Stable", "sh:property": { - "sh:datatype": { + "sh:class": { "@id": "core:LifecycleScopeType" }, "sh:maxCount": 1, @@ -3023,7 +3094,7 @@ "@type": "owl:ObjectProperty", "rdfs:comment": "CreatedBy identifies who or what created the Element.\nThe generation method will assist the recipient of the Element in assessing\nthe general reliability/accuracy of the analysis information.", "rdfs:range": { - "@id": "core:Entity" + "@id": "core:Agent" }, "ns0:term_status": "Stable" }, @@ -3045,6 +3116,15 @@ }, "ns0:term_status": "Stable" }, + { + "@id": "core:definingDocument", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A definingDocument property is used to link an Element identifier to an SpdxDocument which contains the definition for the Element.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, { "@id": "core:description", "@type": "owl:DatatypeProperty", @@ -3083,10 +3163,6 @@ }, { "@id": "core:extension", - "@type": [ - "owl:NamedIndividual", - "core:ProfileIdentifierType" - ], "rdfs:comment": "TODO", "ns0:term_status": "Stable" }, @@ -3221,7 +3297,7 @@ "@type": "owl:ObjectProperty", "rdfs:comment": "OriginatedBy identifies from where or whom the Element originally came.", "rdfs:range": { - "@id": "core:Identity" + "@id": "core:Agent" }, "ns0:term_status": "Stable" }, @@ -3279,15 +3355,6 @@ }, "ns0:term_status": "Stable" }, - { - "@id": "core:spdxId", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "SpdxId uniquely identifies an Element which may thereby be referenced by other Elements.\nThese references may be internal or external.\nWhile there may be several versions of the same Element, each one needs to be able to be referred to uniquely\nso that relationships between Elements can be clearly articulated.", - "rdfs:range": { - "@id": "xsd:anyURI" - }, - "ns0:term_status": "Stable" - }, { "@id": "core:specVersion", "@type": "owl:DatatypeProperty", @@ -3648,6 +3715,15 @@ }, "ns0:term_status": "Stable" }, + { + "@id": "security:actionStatementTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "TODO", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, { "@id": "security:assessedElement", "@type": "owl:ObjectProperty", @@ -3657,6 +3733,15 @@ }, "ns0:term_status": "Stable" }, + { + "@id": "security:catalogType", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A catalogType is a mandatory value and must select one of the two entries in the `ExploitCatalogType.md` vocabulary.", + "rdfs:range": { + "@id": "security:ExploitCatalogType" + }, + "ns0:term_status": "Stable" + }, { "@id": "security:decisionType", "@type": "owl:DatatypeProperty", @@ -3684,6 +3769,15 @@ }, "ns0:term_status": "Stable" }, + { + "@id": "security:impactStatementTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "TODO", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, { "@id": "security:justificationType", "@type": "owl:DatatypeProperty", @@ -3693,6 +3787,15 @@ }, "ns0:term_status": "Stable" }, + { + "@id": "security:locator", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "A locator provides the location of an exploit catalog.", + "rdfs:range": { + "@id": "xsd:anyURI" + }, + "ns0:term_status": "Stable" + }, { "@id": "security:probability", "@type": "owl:DatatypeProperty", @@ -3702,6 +3805,42 @@ }, "ns0:term_status": "Stable" }, + { + "@id": "security:statusNotes", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "TODO", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:suppliedBy", + "@type": "owl:ObjectProperty", + "rdfs:comment": "Identify the actual distribution source for the vulnerability assessment relationship being referenced.", + "rdfs:range": { + "@id": "core:Agent" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "security:vexVersion", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "TODO", + "rdfs:range": { + "@id": "xsd:string" + }, + "ns0:term_status": "Stable" + }, + { + "@id": "software:additionalPurpose", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Additional purpose provides information about the additional purposes of the software artifact in addition to the primaryPurpose.", + "rdfs:range": { + "@id": "software:SoftwarePurpose" + }, + "ns0:term_status": "Stable" + }, { "@id": "software:attributionText", "@type": "owl:DatatypeProperty", @@ -3725,7 +3864,7 @@ "@type": "owl:ObjectProperty", "rdfs:comment": "A concludedLicense is the license identified by the SPDX data creator,\nbased on analyzing the license information in the software Package, File\nor Snippet and other information to arrive at a reasonably objective\nconclusion as to what license governs it.\n\nIf a concludedLicense has a NONE value (NoneLicense), this indicates that the\nSPDX data creator has looked and did not find any license information for this\nsoftware Package, File or Snippet.\n\nIf a concludedLicense has a NOASSERTION value (NoAssertionLicense), this\nindicates that one of the following applies:\n* the SPDX data creator has attempted to but cannot reach a reasonable\n objective determination;\n* the SPDX data creator has made no attempt to determine this field; or\n* the SPDX data creator has intentionally provided no information (no\n meaning should be implied by doing so).\n\nA written explanation of a NOASSERTION value (NoAssertionLicense) MAY be\nprovided in the licenseComment field.\n\nIf the concludedLicense for a software Package, File or Snippet is not the\nsame as its declaredLicense, a written explanation SHOULD be provided in\nthe licenseComment field.\n\nIf the declaredLicense for a software Package, File or Snippet is a choice\nof more than one license (e.g. a license expression combining two licenses\nthrough use of the `OR` operator), then the concludedLicense may either\nretain the license choice or identify which license was chosen.", "rdfs:range": { - "@id": "software:LicenseField" + "@id": "licensing:LicenseField" }, "ns0:term_status": "Stable" }, @@ -3770,7 +3909,7 @@ "@type": "owl:ObjectProperty", "rdfs:comment": "A declaredLicense is the license identified in text in the software package,\nfile or snippet as the license declared by its authors.\n\nThis field is not intended to capture license information obtained from an\nexternal source, such as a package's website. Such information can be\nincluded, as needed, in a concludedLicense field.\n\nA declaredLicense may be expressed differently in practice for different\ntypes of artifacts. For example:\n\n* for Packages:\n * would include license info describing the license of the Package as a\n whole, when it is found in the Package itself (e.g., LICENSE file,\n README file, metadata in the repository, etc.)\n * would not include any license information that is not in the Package\n itself (e.g., license information from the project’s website or from a\n third party repository or website)\n* for Files:\n * would include license info found in the File itself (e.g., license\n header or notice, comments, SPDX-License-Identifier expression)\n * would not include license info found in a different file (e.g., LICENSE\n file in the top directory of a repository)\n* for Snippets:\n * would include license info found in the Snippet itself (e.g., license\n notice, comments, SPDX-License-Identifier expression)\n * would not include license info found elsewhere in the File or in a\n different File (e.g., comment at top of File if it is not within the\n Snippet, LICENSE file in the top directory of a repository)\n\nIf a declaredLicense has a NONE value (NoneLicense), this indicates that the\ncorresponding Package, File or Snippet contains no license information\nwhatsoever.\n\nIf a declaredLicense has a NOASSERTION value (NoAssertionLicense), this\nindicates that one of the following applies:\n* the SPDX data creator has attempted to but cannot reach a reasonable\n objective determination;\n* the SPDX data creator has made no attempt to determine this field; or\n* the SPDX data creator has intentionally provided no information (no meaning\n should be implied by doing so).", "rdfs:range": { - "@id": "software:LicenseField" + "@id": "licensing:LicenseField" }, "ns0:term_status": "Stable" }, @@ -3820,9 +3959,9 @@ "ns0:term_status": "Stable" }, { - "@id": "software:purpose", + "@id": "software:primaryPurpose", "@type": "owl:DatatypeProperty", - "rdfs:comment": "purpose provides information about the primary purpose of the software artifact.", + "rdfs:comment": "primaryPurpose provides information about the primary purpose of the software artifact.", "rdfs:range": { "@id": "software:SoftwarePurpose" }, @@ -3886,35 +4025,23 @@ "rdfs:comment": "An ExternalIdentifier is a reference to a resource outside the scope of SPDX-3.0 content\nthat uniquely identifies an Element.", "ns0:term_status": "Stable", "sh:property": [ - { - "sh:datatype": { - "@id": "xsd:anyURI" - }, - "sh:name": "identifierLocator", - "sh:path": { - "@id": "core:identifierLocator" - } - }, { "sh:datatype": { "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "identifier", + "sh:name": "comment", "sh:path": { - "@id": "core:identifier" + "@id": "core:comment" } }, { "sh:datatype": { - "@id": "core:ExternalIdentifierType" + "@id": "xsd:anyURI" }, - "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "externalIdentifierType", + "sh:name": "identifierLocator", "sh:path": { - "@id": "core:externalIdentifierType" + "@id": "core:identifierLocator" } }, { @@ -3922,9 +4049,10 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "comment", + "sh:minCount": 1, + "sh:name": "identifier", "sh:path": { - "@id": "core:comment" + "@id": "core:identifier" } }, { @@ -3936,6 +4064,17 @@ "sh:path": { "@id": "core:issuingAuthority" } + }, + { + "sh:class": { + "@id": "core:ExternalIdentifierType" + }, + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "externalIdentifierType", + "sh:path": { + "@id": "core:externalIdentifierType" + } } ] }, @@ -3950,11 +4089,12 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "core:MediaType" }, - "sh:name": "locator", + "sh:maxCount": 1, + "sh:name": "contentType", "sh:path": { - "@id": "core:locator" + "@id": "core:contentType" } }, { @@ -3968,23 +4108,22 @@ } }, { - "sh:datatype": { - "@id": "core:MediaType" + "sh:class": { + "@id": "core:ExternalReferenceType" }, "sh:maxCount": 1, - "sh:name": "contentType", + "sh:name": "externalReferenceType", "sh:path": { - "@id": "core:contentType" + "@id": "core:externalReferenceType" } }, { "sh:datatype": { - "@id": "core:ExternalReferenceType" + "@id": "xsd:anyURI" }, - "sh:maxCount": 1, - "sh:name": "externalReferenceType", + "sh:name": "locator", "sh:path": { - "@id": "core:externalReferenceType" + "@id": "core:locator" } } ] @@ -4002,25 +4141,25 @@ "ns0:term_status": "Stable", "sh:property": [ { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "core:HashAlgorithm" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "hashValue", + "sh:name": "algorithm", "sh:path": { - "@id": "core:hashValue" + "@id": "core:algorithm" } }, { "sh:datatype": { - "@id": "core:HashAlgorithm" + "@id": "xsd:string" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "algorithm", + "sh:name": "hashValue", "sh:path": { - "@id": "core:algorithm" + "@id": "core:hashValue" } } ] @@ -4035,16 +4174,16 @@ "ns0:term_status": "Stable", "sh:property": [ { - "sh:datatype": { - "@id": "core:NamespaceMap" + "sh:class": { + "@id": "core:ExternalMap" }, - "sh:name": "namespaces", + "sh:name": "imports", "sh:path": { - "@id": "core:namespaces" + "@id": "core:imports" } }, { - "sh:datatype": { + "sh:class": { "@id": "core:CreationInfo" }, "sh:maxCount": 1, @@ -4054,12 +4193,12 @@ } }, { - "sh:datatype": { - "@id": "core:ExternalMap" + "sh:class": { + "@id": "core:NamespaceMap" }, - "sh:name": "imports", + "sh:name": "namespaces", "sh:path": { - "@id": "core:imports" + "@id": "core:namespaces" } } ] @@ -4086,17 +4225,6 @@ "@id": "core:endTime" } }, - { - "sh:datatype": { - "@id": "core:RelationshipType" - }, - "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "relationshipType", - "sh:path": { - "@id": "core:relationshipType" - } - }, { "sh:datatype": { "@id": "core:DateTime" @@ -4108,7 +4236,7 @@ } }, { - "sh:datatype": { + "sh:class": { "@id": "core:Element" }, "sh:name": "to", @@ -4117,17 +4245,18 @@ } }, { - "sh:datatype": { - "@id": "core:RelationshipCompleteness" + "sh:class": { + "@id": "core:RelationshipType" }, "sh:maxCount": 1, - "sh:name": "completeness", + "sh:minCount": 1, + "sh:name": "relationshipType", "sh:path": { - "@id": "core:completeness" + "@id": "core:relationshipType" } }, { - "sh:datatype": { + "sh:class": { "@id": "core:Element" }, "sh:maxCount": 1, @@ -4136,6 +4265,16 @@ "sh:path": { "@id": "core:from" } + }, + { + "sh:class": { + "@id": "core:RelationshipCompleteness" + }, + "sh:maxCount": 1, + "sh:name": "completeness", + "sh:path": { + "@id": "core:completeness" + } } ] }, @@ -4159,7 +4298,7 @@ ], "rdfs:comment": "A Tool is an element of hardware and/or software utilized to carry out a particular function.", "rdfs:subClassOf": { - "@id": "core:Entity" + "@id": "core:Element" }, "ns0:term_status": "Stable" }, @@ -4280,6 +4419,15 @@ }, "ns0:term_status": "Stable" }, + { + "@id": "security:withdrawnTime", + "@type": "owl:DatatypeProperty", + "rdfs:comment": "Specified the time and date when a vulnerability was withdrawn.", + "rdfs:range": { + "@id": "core:DateTime" + }, + "ns0:term_status": "Stable" + }, { "@id": "software:Package", "@type": [ @@ -4294,42 +4442,42 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:anyURI" }, "sh:maxCount": 1, - "sh:name": "sourceInfo", + "sh:name": "homePage", "sh:path": { - "@id": "software:sourceInfo" + "@id": "software:homePage" } }, { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "packageUrl", + "sh:name": "packageVersion", "sh:path": { - "@id": "software:packageUrl" + "@id": "software:packageVersion" } }, { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "downloadLocation", + "sh:name": "sourceInfo", "sh:path": { - "@id": "software:downloadLocation" + "@id": "software:sourceInfo" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:anyURI" }, "sh:maxCount": 1, - "sh:name": "packageVersion", + "sh:name": "packageUrl", "sh:path": { - "@id": "software:packageVersion" + "@id": "software:packageUrl" } }, { @@ -4337,9 +4485,9 @@ "@id": "xsd:anyURI" }, "sh:maxCount": 1, - "sh:name": "homePage", + "sh:name": "downloadLocation", "sh:path": { - "@id": "software:homePage" + "@id": "software:downloadLocation" } } ] @@ -4371,12 +4519,6 @@ }, "ns0:term_status": "Stable" }, - { - "@id": "security:ExploitCatalogType", - "@type": "owl:Class", - "rdfs:comment": "ExploitCatalogType specifies the type of exploit catalog that a vulnerability is listed in.", - "ns0:term_status": "Stable" - }, { "@id": "security:severity", "@type": "owl:DatatypeProperty", @@ -4400,25 +4542,36 @@ "sh:property": [ { "sh:datatype": { - "@id": "software:SoftwarePurpose" + "@id": "xsd:string" }, - "sh:name": "purpose", + "sh:maxCount": 1, + "sh:name": "copyrightText", "sh:path": { - "@id": "software:purpose" + "@id": "software:copyrightText" } }, { "sh:datatype": { - "@id": "licensing:LicenseField" + "@id": "xsd:anyURI" }, "sh:maxCount": 1, - "sh:name": "concludedLicense", + "sh:name": "contentIdentifier", "sh:path": { - "@id": "software:concludedLicense" + "@id": "software:contentIdentifier" } }, { "sh:datatype": { + "@id": "xsd:string" + }, + "sh:maxCount": 1, + "sh:name": "attributionText", + "sh:path": { + "@id": "software:attributionText" + } + }, + { + "sh:class": { "@id": "licensing:LicenseField" }, "sh:maxCount": 1, @@ -4428,33 +4581,32 @@ } }, { - "sh:datatype": { - "@id": "xsd:anyURI" + "sh:class": { + "@id": "software:SoftwarePurpose" }, - "sh:maxCount": 1, - "sh:name": "contentIdentifier", + "sh:name": "additionalPurpose", "sh:path": { - "@id": "software:contentIdentifier" + "@id": "software:additionalPurpose" } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "software:SoftwarePurpose" }, "sh:maxCount": 1, - "sh:name": "copyrightText", + "sh:name": "primaryPurpose", "sh:path": { - "@id": "software:copyrightText" + "@id": "software:primaryPurpose" } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "licensing:LicenseField" }, "sh:maxCount": 1, - "sh:name": "attributionText", + "sh:name": "concludedLicense", "sh:path": { - "@id": "software:attributionText" + "@id": "software:concludedLicense" } } ] @@ -4494,8 +4646,8 @@ } }, { - "sh:datatype": { - "@id": "core:Entity" + "sh:class": { + "@id": "core:Agent" }, "sh:minCount": 1, "sh:name": "createdBy", @@ -4504,7 +4656,7 @@ } }, { - "sh:datatype": { + "sh:class": { "@id": "core:ProfileIdentifierType" }, "sh:minCount": 1, @@ -4515,11 +4667,11 @@ }, { "sh:datatype": { - "@id": "core:Tool" + "@id": "xsd:string" }, - "sh:name": "createdUsing", + "sh:name": "dataLicense", "sh:path": { - "@id": "core:createdUsing" + "@id": "core:dataLicense" } }, { @@ -4532,28 +4684,16 @@ } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "core:Tool" }, - "sh:name": "dataLicense", + "sh:name": "createdUsing", "sh:path": { - "@id": "core:dataLicense" + "@id": "core:createdUsing" } } ] }, - { - "@id": "core:Entity", - "@type": [ - "owl:Class", - "sh:NodeShape" - ], - "rdfs:comment": "TODO", - "rdfs:subClassOf": { - "@id": "core:Element" - }, - "ns0:term_status": "Stable" - }, { "@id": "core:ExternalMap", "@type": [ @@ -4568,19 +4708,19 @@ "@id": "xsd:anyURI" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "externalId", + "sh:name": "locationHint", "sh:path": { - "@id": "core:externalId" + "@id": "core:locationHint" } }, { "sh:datatype": { - "@id": "core:IntegrityMethod" + "@id": "xsd:anyURI" }, - "sh:name": "verifiedUsing", + "sh:maxCount": 1, + "sh:name": "definingDocument", "sh:path": { - "@id": "core:verifiedUsing" + "@id": "core:definingDocument" } }, { @@ -4588,9 +4728,19 @@ "@id": "xsd:anyURI" }, "sh:maxCount": 1, - "sh:name": "locationHint", + "sh:minCount": 1, + "sh:name": "externalId", "sh:path": { - "@id": "core:locationHint" + "@id": "core:externalId" + } + }, + { + "sh:class": { + "@id": "core:IntegrityMethod" + }, + "sh:name": "verifiedUsing", + "sh:path": { + "@id": "core:verifiedUsing" } } ] @@ -4625,22 +4775,24 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:anyURI" }, "sh:maxCount": 1, - "sh:name": "prefix", + "sh:minCount": 1, + "sh:name": "namespace", "sh:path": { - "@id": "core:prefix" + "@id": "core:namespace" } }, { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "namespace", + "sh:minCount": 1, + "sh:name": "prefix", "sh:path": { - "@id": "core:namespace" + "@id": "core:prefix" } } ] @@ -4689,13 +4841,21 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:anyURI" + }, + "sh:name": "seeAlso", + "sh:path": { + "@id": "licensing:seeAlso" + } + }, + { + "sh:datatype": { + "@id": "xsd:boolean" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "additionId", + "sh:name": "isDeprecatedAdditionId", "sh:path": { - "@id": "licensing:additionId" + "@id": "licensing:isDeprecatedAdditionId" } }, { @@ -4714,9 +4874,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "standardAdditionTemplate", + "sh:name": "additionComment", "sh:path": { - "@id": "licensing:standardAdditionTemplate" + "@id": "licensing:additionComment" } }, { @@ -4724,18 +4884,20 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "additionComment", + "sh:minCount": 1, + "sh:name": "additionId", "sh:path": { - "@id": "licensing:additionComment" + "@id": "licensing:additionId" } }, { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:string" }, - "sh:name": "seeAlso", + "sh:maxCount": 1, + "sh:name": "obsoletedBy", "sh:path": { - "@id": "licensing:seeAlso" + "@id": "licensing:obsoletedBy" } }, { @@ -4754,23 +4916,19 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "obsoletedBy", - "sh:path": { - "@id": "licensing:obsoletedBy" - } - }, - { - "sh:datatype": { - "@id": "xsd:boolean" - }, - "sh:maxCount": 1, - "sh:name": "isDeprecatedAdditionId", + "sh:name": "standardAdditionTemplate", "sh:path": { - "@id": "licensing:isDeprecatedAdditionId" + "@id": "licensing:standardAdditionTemplate" } } ] }, + { + "@id": "security:ExploitCatalogType", + "@type": "owl:Class", + "rdfs:comment": "ExploitCatalogType specifies the type of exploit catalog that a vulnerability is listed in.", + "ns0:term_status": "Stable" + }, { "@id": "security:VexVulnAssessmentRelationship", "@type": [ @@ -4788,9 +4946,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "statusNotes", + "sh:name": "vexVersion", "sh:path": { - "@id": "security:statusNotes" + "@id": "security:vexVersion" } }, { @@ -4798,9 +4956,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "vexVersion", + "sh:name": "statusNotes", "sh:path": { - "@id": "security:vexVersion" + "@id": "security:statusNotes" } } ] @@ -4846,23 +5004,21 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:boolean" }, "sh:maxCount": 1, - "sh:name": "standardLicenseTemplate", + "sh:name": "isOsiApproved", "sh:path": { - "@id": "licensing:standardLicenseTemplate" + "@id": "licensing:isOsiApproved" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:anyURI" }, - "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "licenseName", + "sh:name": "seeAlso", "sh:path": { - "@id": "licensing:licenseName" + "@id": "licensing:seeAlso" } }, { @@ -4870,39 +5026,40 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "obsoletedBy", + "sh:name": "licenseComment", "sh:path": { - "@id": "licensing:obsoletedBy" + "@id": "licensing:licenseComment" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:boolean" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "licenseText", + "sh:name": "isDeprecatedLicenseId", "sh:path": { - "@id": "licensing:licenseText" + "@id": "licensing:isDeprecatedLicenseId" } }, { "sh:datatype": { - "@id": "xsd:boolean" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "isDeprecatedLicenseId", + "sh:name": "standardLicenseHeader", "sh:path": { - "@id": "licensing:isDeprecatedLicenseId" + "@id": "licensing:standardLicenseHeader" } }, { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:string" }, - "sh:name": "seeAlso", + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "licenseText", "sh:path": { - "@id": "licensing:seeAlso" + "@id": "licensing:licenseText" } }, { @@ -4910,40 +5067,41 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "licenseComment", + "sh:name": "obsoletedBy", "sh:path": { - "@id": "licensing:licenseComment" + "@id": "licensing:obsoletedBy" } }, { "sh:datatype": { - "@id": "xsd:boolean" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "isOsiApproved", + "sh:minCount": 1, + "sh:name": "licenseId", "sh:path": { - "@id": "licensing:isOsiApproved" + "@id": "licensing:licenseId" } }, { "sh:datatype": { - "@id": "xsd:boolean" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "isFsfLibre", + "sh:minCount": 1, + "sh:name": "licenseName", "sh:path": { - "@id": "licensing:isFsfLibre" + "@id": "licensing:licenseName" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:boolean" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "licenseId", + "sh:name": "isFsfLibre", "sh:path": { - "@id": "licensing:licenseId" + "@id": "licensing:isFsfLibre" } }, { @@ -4951,40 +5109,19 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "standardLicenseHeader", + "sh:name": "standardLicenseTemplate", "sh:path": { - "@id": "licensing:standardLicenseHeader" + "@id": "licensing:standardLicenseTemplate" } } ] }, - { - "@id": "licensing:LicenseField", - "@type": [ - "owl:Class", - "sh:NodeShape" - ], - "rdfs:comment": "A LicenseField is the primary value that is used by a licensing field for a\nsoftware Package, File or Snippet. It represents either a license expression,\nor the values NOASSERTION or NONE. The specific meanings of NOASSERTION or\nNONE for the particular licensing field are defined in the corresponding\nproperty description.", - "ns0:term_status": "Stable" - }, { "@id": "ai:SafetyRiskAssessmentType", "@type": "owl:Class", "rdfs:comment": "Lists the different safety risk type values that can be used to describe the safety risk of AI software\naccording to [Article 20 of Regulation 765/2008/EC](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).", "ns0:term_status": "Stable" }, - { - "@id": "core:Identity", - "@type": [ - "owl:Class", - "sh:NodeShape" - ], - "rdfs:comment": "An Identity is a grouping of identifying characteristics unique to an individual or organization.", - "rdfs:subClassOf": { - "@id": "core:Entity" - }, - "ns0:term_status": "Stable" - }, { "@id": "dataset:ConfidentialityLevelType", "@type": "owl:Class", @@ -5003,7 +5140,7 @@ "owl:Class", "sh:NodeShape" ], - "rdfs:comment": "VulnAssessmentRelationship is the ancestor class common to all vulnerability\nassessment relationships. It factors out the common properties shared by them.", + "rdfs:comment": "VulnAssessmentRelationship is the ancestor class common to all vulnerability\nassessment relationships. It factors out the common properties shared by them.\nExternal property restriction on /Core/Relationship/to: minCount: 1", "rdfs:subClassOf": { "@id": "core:Relationship" }, @@ -5029,16 +5166,6 @@ "@id": "security:withdrawnTime" } }, - { - "sh:datatype": { - "@id": "core:Identity" - }, - "sh:maxCount": 1, - "sh:name": "suppliedBy", - "sh:path": { - "@id": "security:suppliedBy" - } - }, { "sh:datatype": { "@id": "core:DateTime" @@ -5050,7 +5177,7 @@ } }, { - "sh:datatype": { + "sh:class": { "@id": "core:Element" }, "sh:maxCount": 1, @@ -5058,6 +5185,16 @@ "sh:path": { "@id": "security:assessedElement" } + }, + { + "sh:class": { + "@id": "core:Agent" + }, + "sh:maxCount": 1, + "sh:name": "suppliedBy", + "sh:path": { + "@id": "security:suppliedBy" + } } ] }, @@ -5079,6 +5216,15 @@ "rdfs:comment": "Describes the possible types of availability of a dataset, indicating whether the dataset can be directly downloaded, can be assembled using a script for scraping the data, is only available after a clickthrough or a registration form.", "ns0:term_status": "Stable" }, + { + "@id": "licensing:LicenseField", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A LicenseField is the primary value that is used by a licensing field for a\nsoftware Package, File or Snippet. It represents either a license expression,\nor the values NOASSERTION or NONE. The specific meanings of NOASSERTION or\nNONE for the particular licensing field are defined in the corresponding\nproperty description.", + "ns0:term_status": "Stable" + }, { "@id": "security:VexJustificationType", "@type": "owl:Class", @@ -5116,9 +5262,15 @@ "ns0:term_status": "Stable" }, { - "@id": "core:ExternalIdentifierType", - "@type": "owl:Class", - "rdfs:comment": "ExteralIdentifierType specifies the type of an external identifier.", + "@id": "core:Agent", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "The Agent class represents anything that has the potential to act on a system. This could be a person, organization, software agent, etc. This is not to be confused with tools that are used to perform tasks.", + "rdfs:subClassOf": { + "@id": "core:Element" + }, "ns0:term_status": "Stable" }, { @@ -5159,6 +5311,12 @@ } ] }, + { + "@id": "core:ExternalIdentifierType", + "@type": "owl:Class", + "rdfs:comment": "ExteralIdentifierType specifies the type of an external identifier.", + "ns0:term_status": "Stable" + }, { "@id": "core:Element", "@type": [ @@ -5172,27 +5330,7 @@ "ns0:term_status": "Stable", "sh:property": [ { - "sh:datatype": { - "@id": "xsd:anyURI" - }, - "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "spdxId", - "sh:path": { - "@id": "core:spdxId" - } - }, - { - "sh:datatype": { - "@id": "core:ExternalIdentifier" - }, - "sh:name": "externalIdentifier", - "sh:path": { - "@id": "core:externalIdentifier" - } - }, - { - "sh:datatype": { + "sh:class": { "@id": "core:IntegrityMethod" }, "sh:name": "verifiedUsing", @@ -5205,9 +5343,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "name", + "sh:name": "summary", "sh:path": { - "@id": "core:name" + "@id": "core:summary" } }, { @@ -5220,12 +5358,12 @@ } }, { - "sh:datatype": { - "@id": "core:ExternalReference" + "sh:class": { + "@id": "core:ExternalIdentifier" }, - "sh:name": "externalReference", + "sh:name": "externalIdentifier", "sh:path": { - "@id": "core:externalReference" + "@id": "core:externalIdentifier" } }, { @@ -5233,29 +5371,38 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "summary", + "sh:name": "comment", "sh:path": { - "@id": "core:summary" + "@id": "core:comment" } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "core:CreationInfo" }, "sh:maxCount": 1, - "sh:name": "description", + "sh:name": "creationInfo", "sh:path": { - "@id": "core:description" + "@id": "core:creationInfo" + } + }, + { + "sh:class": { + "@id": "core:ExternalReference" + }, + "sh:name": "externalReference", + "sh:path": { + "@id": "core:externalReference" } }, { "sh:datatype": { - "@id": "core:CreationInfo" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "creationInfo", + "sh:name": "name", "sh:path": { - "@id": "core:creationInfo" + "@id": "core:name" } }, { @@ -5263,9 +5410,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "comment", + "sh:name": "description", "sh:path": { - "@id": "core:comment" + "@id": "core:description" } } ] @@ -5277,15 +5424,9 @@ "ns0:term_status": "Stable" }, { - "@id": "core:DateTime", - "@type": [ - "owl:Class", - "sh:NodeShape" - ], - "rdfs:comment": "A Datetime is a string representation of a specific date and time.\nIt has resolution of seconds and is always expressed in UTC timezone.\nThe specific format is one of the most commonly used ISO-8601 formats.\nFormat restriction: pattern: ^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\dZ$", - "rdfs:subClassOf": { - "@id": "xsd:string" - }, + "@id": "core:HashAlgorithm", + "@type": "owl:Class", + "rdfs:comment": "A HashAlgorithm is a mathematical algorithm that maps data of arbitrary size to a bit string (the hash)\nand is a one-way function, that is, a function which is practically infeasible to invert.", "ns0:term_status": "Stable" }, { @@ -5295,9 +5436,15 @@ "ns0:term_status": "Stable" }, { - "@id": "core:HashAlgorithm", - "@type": "owl:Class", - "rdfs:comment": "A HashAlgorithm is a mathematical algorithm that maps data of arbitrary size to a bit string (the hash)\nand is a one-way function, that is, a function which is practically infeasible to invert.", + "@id": "core:DateTime", + "@type": [ + "owl:Class", + "sh:NodeShape" + ], + "rdfs:comment": "A Datetime is a string representation of a specific date and time.\nIt has resolution of seconds and is always expressed in UTC timezone.\nThe specific format is one of the most commonly used ISO-8601 formats.\nFormat restriction: pattern: ^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\dZ$", + "rdfs:subClassOf": { + "@id": "xsd:string" + }, "ns0:term_status": "Stable" }, { diff --git a/src/spdx_tools/spdx3/writer/json_ld/model.ttl b/src/spdx_tools/spdx3/writer/json_ld/model.ttl index b703f22f5..eaa3513ac 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/model.ttl +++ b/src/spdx_tools/spdx3/writer/json_ld/model.ttl @@ -18,83 +18,82 @@ External property restriction on /Core/Artifact/suppliedBy: minCount: 1 External property restriction on /Software/Package/downloadLocation: minCount: 1 External property restriction on /Software/Package/packageVersion: minCount: 1 External property restriction on /Software/SoftwareArtifact/purpose: minCount: 1 -External property restriction on /Core/Relationship/relationshipType: minCount: 1 External property restriction on /Core/Artifact/releaseTime: minCount: 1""" ; rdfs:subClassOf software:Package ; ns0:term_status "Stable" ; - sh:property [ sh:datatype ai:PresenceType ; + sh:property [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "sensitivePersonalInformation" ; - sh:path ai:sensitivePersonalInformation ], - [ sh:datatype core:DictionaryEntry ; - sh:name "metricDecisionThreshold" ; - sh:path ai:metricDecisionThreshold ], + sh:name "informationAboutApplication" ; + sh:path ai:informationAboutApplication ], + [ sh:datatype xsd:string ; + sh:name "modelDataPreprocessing" ; + sh:path ai:modelDataPreprocessing ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "informationAboutTraining" ; + sh:path ai:informationAboutTraining ], + [ sh:class core:DictionaryEntry ; + sh:name "hyperparameter" ; + sh:path ai:hyperparameter ], [ sh:datatype xsd:string ; sh:name "modelExplainability" ; sh:path ai:modelExplainability ], - [ sh:datatype core:DictionaryEntry ; + [ sh:class core:DictionaryEntry ; sh:name "metric" ; sh:path ai:metric ], - [ sh:datatype xsd:string ; - sh:name "standardCompliance" ; - sh:path ai:standardCompliance ], - [ sh:datatype xsd:string ; - sh:name "domain" ; - sh:path ai:domain ], - [ sh:datatype ai:SafetyRiskAssessmentType ; + [ sh:class ai:SafetyRiskAssessmentType ; sh:maxCount 1 ; sh:name "safetyRiskAssessment" ; sh:path ai:safetyRiskAssessment ], - [ sh:datatype core:DictionaryEntry ; - sh:name "hyperparameter" ; - sh:path ai:hyperparameter ], [ sh:datatype xsd:string ; sh:name "typeOfModel" ; sh:path ai:typeOfModel ], [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "energyConsumption" ; - sh:path ai:energyConsumption ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "informationAboutApplication" ; - sh:path ai:informationAboutApplication ], - [ sh:datatype xsd:string ; - sh:name "modelDataPreprocessing" ; - sh:path ai:modelDataPreprocessing ], + sh:name "standardCompliance" ; + sh:path ai:standardCompliance ], [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "informationAboutTraining" ; - sh:path ai:informationAboutTraining ], - [ sh:datatype ai:PresenceType ; + sh:name "domain" ; + sh:path ai:domain ], + [ sh:class ai:PresenceType ; sh:maxCount 1 ; sh:name "autonomyType" ; sh:path ai:autonomyType ], + [ sh:class ai:PresenceType ; + sh:maxCount 1 ; + sh:name "sensitivePersonalInformation" ; + sh:path ai:sensitivePersonalInformation ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "limitation" ; - sh:path ai:limitation ] . - -ai:high a owl:NamedIndividual, - ai:SafetyRiskAssessmentType . - -ai:low a owl:NamedIndividual, - ai:SafetyRiskAssessmentType . + sh:path ai:limitation ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "energyConsumption" ; + sh:path ai:energyConsumption ], + [ sh:class core:DictionaryEntry ; + sh:name "metricDecisionThreshold" ; + sh:path ai:metricDecisionThreshold ] . -ai:medium a owl:NamedIndividual, - ai:SafetyRiskAssessmentType . + a owl:NamedIndividual, + ai:PresenceType . -ai:no a owl:NamedIndividual, + a owl:NamedIndividual, ai:PresenceType . -ai:noAssertion a owl:NamedIndividual, + a owl:NamedIndividual, ai:PresenceType . -ai:serious a owl:NamedIndividual, + a owl:NamedIndividual, ai:SafetyRiskAssessmentType . -ai:yes a owl:NamedIndividual, - ai:PresenceType . + a owl:NamedIndividual, + ai:SafetyRiskAssessmentType . + + a owl:NamedIndividual, + ai:SafetyRiskAssessmentType . + + a owl:NamedIndividual, + ai:SafetyRiskAssessmentType . build:Build a owl:Class, sh:NodeShape ; @@ -110,44 +109,47 @@ Note that buildStart and buildEnd are optional, and may be omitted to simplify c rdfs:subClassOf core:Element ; ns0:term_status "Stable" ; sh:property [ sh:datatype core:DateTime ; - sh:maxCount 1 ; - sh:name "buildStartTime" ; - sh:path build:buildStartTime ], - [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "buildEndTime" ; sh:path build:buildEndTime ], - [ sh:datatype core:DictionaryEntry ; - sh:name "parameters" ; - sh:path build:parameters ], - [ sh:datatype xsd:anyURI ; - sh:name "configSourceUri" ; - sh:path build:configSourceUri ], - [ sh:datatype xsd:anyURI ; + [ sh:datatype core:DateTime ; sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "buildType" ; - sh:path build:buildType ], - [ sh:datatype core:DictionaryEntry ; - sh:name "environment" ; - sh:path build:environment ], + sh:name "buildStartTime" ; + sh:path build:buildStartTime ], [ sh:datatype xsd:string ; sh:name "configSourceEntrypoint" ; sh:path build:configSourceEntrypoint ], + [ sh:class core:Hash ; + sh:name "configSourceDigest" ; + sh:path build:configSourceDigest ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "buildId" ; sh:path build:buildId ], - [ sh:datatype core:Hash ; - sh:name "configSourceDigest" ; - sh:path build:configSourceDigest ] . + [ sh:class core:DictionaryEntry ; + sh:name "parameters" ; + sh:path build:parameters ], + [ sh:class core:DictionaryEntry ; + sh:name "environment" ; + sh:path build:environment ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "buildType" ; + sh:path build:buildType ], + [ sh:datatype xsd:anyURI ; + sh:name "configSourceUri" ; + sh:path build:configSourceUri ] . core:Annotation a owl:Class, sh:NodeShape ; rdfs:comment "An Annotation is an assertion made in relation to one or more elements." ; rdfs:subClassOf core:Element ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:Element ; + sh:property [ sh:datatype core:MediaType ; + sh:name "contentType" ; + sh:path core:contentType ], + [ sh:class core:Element ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "subject" ; @@ -156,459 +158,486 @@ core:Annotation a owl:Class, sh:maxCount 1 ; sh:name "statement" ; sh:path core:statement ], - [ sh:datatype core:MediaType ; - sh:name "contentType" ; - sh:path core:contentType ], - [ sh:datatype core:AnnotationType ; + [ sh:class core:AnnotationType ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "annotationType" ; sh:path core:annotationType ] . + a owl:NamedIndividual, + core:AnnotationType . + + a owl:NamedIndividual, + core:AnnotationType . + core:AnonymousPayload a owl:Class, sh:NodeShape ; rdfs:comment "TODO" ; rdfs:subClassOf core:Payload ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:ExternalMap ; - sh:name "imports" ; - sh:path core:imports ], - [ sh:datatype core:CreationInfo ; + sh:property [ sh:class core:CreationInfo ; sh:maxCount 1 ; sh:name "creationInfo" ; sh:path core:creationInfo ], - [ sh:datatype core:NamespaceMap ; + [ sh:class core:NamespaceMap ; sh:name "namespaces" ; - sh:path core:namespaces ] . + sh:path core:namespaces ], + [ sh:class core:ExternalMap ; + sh:name "imports" ; + sh:path core:imports ] . -core:Organization a owl:Class, - sh:NodeShape ; - rdfs:comment "An Organization is a group of people who work together in an organized way for a shared purpose." ; - rdfs:subClassOf core:Identity ; - ns0:term_status "Stable" . + a owl:NamedIndividual, + core:ExternalIdentifierType . -core:Person a owl:Class, - sh:NodeShape ; - rdfs:comment "A Person is an individual human being." ; - rdfs:subClassOf core:Identity ; - ns0:term_status "Stable" . + a owl:NamedIndividual, + core:ExternalIdentifierType . -core:SpdxDocument a owl:Class, - sh:NodeShape ; - rdfs:comment """An SpdxDocument assembles a collection of Elements under a common string, the name of the document. -Commonly used when representing a unit of transfer of SPDX Elements. -External property restriction on /Core/Element/name: minCount: 1""" ; - rdfs:subClassOf core:Bundle ; - ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "name" ; - sh:path core:name ] . + a owl:NamedIndividual, + core:ExternalIdentifierType . -core:affects a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ExternalIdentifierType . -core:ai a owl:NamedIndividual, - core:ProfileIdentifierType . + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . -core:altDownloadLocation a owl:NamedIndividual, + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, + core:ExternalIdentifierType . + + a owl:NamedIndividual, core:ExternalReferenceType . -core:altWebPage a owl:NamedIndividual, + a owl:NamedIndividual, core:ExternalReferenceType . -core:amends a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:ancestor a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:availableFrom a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:binaryArtifact a owl:NamedIndividual, + a owl:NamedIndividual, core:ExternalReferenceType . -core:blake2b256 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:blake2b384 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:blake2b512 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:blake3 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:build a owl:NamedIndividual, - core:LifecycleScopeType, - core:ProfileIdentifierType . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:buildConfigOf a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:buildDependency a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:buildHostOf a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:buildInputOf a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:buildInvokedBy a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:buildMeta a owl:NamedIndividual, + a owl:NamedIndividual, core:ExternalReferenceType . -core:buildOnBehalfOf a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:buildOutputOf a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:buildSystem a owl:NamedIndividual, + a owl:NamedIndividual, core:ExternalReferenceType . -core:buildTool a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ExternalReferenceType . -core:chat a owl:NamedIndividual, + a owl:NamedIndividual, core:ExternalReferenceType . -core:complete a owl:NamedIndividual, - core:RelationshipCompleteness . + a owl:NamedIndividual, + core:HashAlgorithm . -core:contains a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:coordinatedBy a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:copy a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:core a owl:NamedIndividual, - core:ProfileIdentifierType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:cpe22 a owl:NamedIndividual, - core:ExternalIdentifierType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:cpe23 a owl:NamedIndividual, - core:ExternalIdentifierType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:crystalsDilithium a owl:NamedIndividual, + a owl:NamedIndividual, core:HashAlgorithm . -core:crystalsKyber a owl:NamedIndividual, + a owl:NamedIndividual, core:HashAlgorithm . -core:dataFile a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:dataset a owl:NamedIndividual, - core:ProfileIdentifierType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:dependencyManifest a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:dependsOn a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:descendant a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:describes a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:design a owl:NamedIndividual, - core:LifecycleScopeType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:devDependency a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:HashAlgorithm . -core:devTool a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . + + a owl:NamedIndividual, + core:HashAlgorithm . -core:development a owl:NamedIndividual, + a owl:NamedIndividual, core:LifecycleScopeType . -core:distributionArtifact a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:LifecycleScopeType . -core:documentation a owl:NamedIndividual, - core:ExternalReferenceType, - core:RelationshipType . + a owl:NamedIndividual, + core:LifecycleScopeType . -core:doesNotAffect a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:LifecycleScopeType . -core:dynamicLink a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:LifecycleScopeType . -core:email a owl:NamedIndividual, - core:ExternalIdentifierType . + a owl:NamedIndividual, + core:LifecycleScopeType . -core:example a owl:NamedIndividual, - core:RelationshipType . +core:Organization a owl:Class, + sh:NodeShape ; + rdfs:comment "An Organization is a group of people who work together in an organized way for a shared purpose." ; + rdfs:subClassOf core:Agent ; + ns0:term_status "Stable" . -core:expandedFromArchive a owl:NamedIndividual, - core:RelationshipType . +core:Person a owl:Class, + sh:NodeShape ; + rdfs:comment "A Person is an individual human being." ; + rdfs:subClassOf core:Agent ; + ns0:term_status "Stable" . -core:exploitCreatedBy a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ProfileIdentifierType . -core:falcon a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:ProfileIdentifierType . -core:fileAdded a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ProfileIdentifierType . -core:fileDeleted a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ProfileIdentifierType . -core:fileModified a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ProfileIdentifierType . -core:fixedBy a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ProfileIdentifierType . -core:fixedIn a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ProfileIdentifierType . -core:foundBy a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:ProfileIdentifierType . -core:funding a owl:NamedIndividual, - core:ExternalReferenceType . + a owl:NamedIndividual, + core:ProfileIdentifierType . -core:generates a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:RelationshipCompleteness . -core:gitoid a owl:NamedIndividual, - core:ExternalIdentifierType . + a owl:NamedIndividual, + core:RelationshipCompleteness . -core:hasAssociatedVulnerability a owl:NamedIndividual, - core:RelationshipType . + a owl:NamedIndividual, + core:RelationshipCompleteness . -core:hasCvssV2AssessmentFor a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:hasCvssV3AssessmentFor a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:hasEpssAssessmentFor a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:hasExploitCatalogAssessmentFor a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:hasSsvcAssessmentFor a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:incomplete a owl:NamedIndividual, - core:RelationshipCompleteness . - -core:issueTracker a owl:NamedIndividual, - core:ExternalReferenceType . - -core:license a owl:NamedIndividual, - core:ExternalReferenceType . - -core:licensing a owl:NamedIndividual, - core:ProfileIdentifierType . - -core:mailingList a owl:NamedIndividual, - core:ExternalReferenceType . + a owl:NamedIndividual, + core:RelationshipType . -core:md2 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:md4 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:md5 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:md6 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:metafile a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:metrics a owl:NamedIndividual, - core:ExternalReferenceType . + a owl:NamedIndividual, + core:RelationshipType . -core:noAssertion a owl:NamedIndividual, - core:RelationshipCompleteness . + a owl:NamedIndividual, + core:RelationshipType . -core:optionalComponent a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:optionalDependency a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:other a owl:NamedIndividual, - core:AnnotationType, - core:ExternalIdentifierType, - core:ExternalReferenceType, - core:HashAlgorithm, - core:LifecycleScopeType, + a owl:NamedIndividual, core:RelationshipType . -core:packages a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:patch a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:pkgUrl a owl:NamedIndividual, - core:ExternalIdentifierType . + a owl:NamedIndividual, + core:RelationshipType . -core:prerequisite a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:providedDependency a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:publishedBy a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:releaseHistory a owl:NamedIndividual, - core:ExternalReferenceType . + a owl:NamedIndividual, + core:RelationshipType . -core:releaseNotes a owl:NamedIndividual, - core:ExternalReferenceType . + a owl:NamedIndividual, + core:RelationshipType . -core:reportedBy a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:republishedBy a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:requirementFor a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:review a owl:NamedIndividual, - core:AnnotationType . + a owl:NamedIndividual, + core:RelationshipType . -core:runtime a owl:NamedIndividual, - core:LifecycleScopeType . + a owl:NamedIndividual, + core:RelationshipType . -core:runtimeDependency a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:security a owl:NamedIndividual, - core:ProfileIdentifierType . + a owl:NamedIndividual, + core:RelationshipType . -core:securityAdvisory a owl:NamedIndividual, - core:ExternalReferenceType . + a owl:NamedIndividual, + core:RelationshipType . -core:securityFix a owl:NamedIndividual, - core:ExternalReferenceType . + a owl:NamedIndividual, + core:RelationshipType . -core:securityOther a owl:NamedIndividual, - core:ExternalReferenceType . + a owl:NamedIndividual, + core:RelationshipType . -core:sha1 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:sha224 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:sha256 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:sha384 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:sha3_224 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:sha3_256 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:sha3_384 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:sha3_512 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:sha512 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:socialMedia a owl:NamedIndividual, - core:ExternalReferenceType . + a owl:NamedIndividual, + core:RelationshipType . -core:software a owl:NamedIndividual, - core:ProfileIdentifierType . + a owl:NamedIndividual, + core:RelationshipType . -core:sourceArtifact a owl:NamedIndividual, - core:ExternalReferenceType . + a owl:NamedIndividual, + core:RelationshipType . -core:spdxPvcSha1 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:spdxPvcSha256 a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:specificationFor a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:sphincsPlus a owl:NamedIndividual, - core:HashAlgorithm . + a owl:NamedIndividual, + core:RelationshipType . -core:staticLink a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:support a owl:NamedIndividual, - core:ExternalReferenceType . + a owl:NamedIndividual, + core:RelationshipType . -core:swhid a owl:NamedIndividual, - core:ExternalIdentifierType . + a owl:NamedIndividual, + core:RelationshipType . -core:swid a owl:NamedIndividual, - core:ExternalIdentifierType . + a owl:NamedIndividual, + core:RelationshipType . -core:test a owl:NamedIndividual, - core:LifecycleScopeType, + a owl:NamedIndividual, core:RelationshipType . -core:testCase a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:testDependency a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:testTool a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:underInvestigationFor a owl:NamedIndividual, + a owl:NamedIndividual, core:RelationshipType . -core:urlScheme a owl:NamedIndividual, - core:ExternalIdentifierType . +core:SoftwareAgent a owl:Class, + sh:NodeShape ; + rdfs:comment "A SoftwareAgent is a software program that is given the authority (similar to a user's authority) to act on a system." ; + rdfs:subClassOf core:Agent ; + ns0:term_status "Stable" . -core:usage a owl:NamedIndividual, - core:ProfileIdentifierType . +core:SpdxDocument a owl:Class, + sh:NodeShape ; + rdfs:comment """An SpdxDocument assembles a collection of Elements under a common string, the name of the document. +Commonly used when representing a unit of transfer of SPDX Elements. +External property restriction on /Core/Element/name: minCount: 1""" ; + rdfs:subClassOf core:Bundle ; + ns0:term_status "Stable" ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "name" ; + sh:path core:name ] . -core:variant a owl:NamedIndividual, - core:RelationshipType . +core:spdxId a owl:DatatypeProperty ; + rdfs:comment """SpdxId uniquely identifies an Element which may thereby be referenced by other Elements. +These references may be internal or external. +While there may be several versions of the same Element, each one needs to be able to be referred to uniquely +so that relationships between Elements can be clearly articulated.""" ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . -core:vcs a owl:NamedIndividual, - core:ExternalReferenceType . + a owl:NamedIndividual, + dataset:ConfidentialityLevelType . -dataset:Amber a owl:NamedIndividual, + a owl:NamedIndividual, dataset:ConfidentialityLevelType . -dataset:Clear a owl:NamedIndividual, + a owl:NamedIndividual, dataset:ConfidentialityLevelType . -dataset:Clickthrough a owl:NamedIndividual, - dataset:DatasetAvailabilityType . + a owl:NamedIndividual, + dataset:ConfidentialityLevelType . dataset:Dataset a owl:Class, sh:NodeShape ; @@ -620,20 +649,22 @@ External property restriction on /Core/Artifact/releaseTime: minCount: 1 External property restriction on /Core/Artifact/builtTime: minCount: 1""" ; rdfs:subClassOf software:Package ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; - sh:name "dataPreprocessing" ; - sh:path dataset:dataPreprocessing ], - [ sh:datatype xsd:nonNegativeInteger ; + sh:property [ sh:class dataset:DatasetAvailabilityType ; sh:maxCount 1 ; - sh:name "datasetSize" ; - sh:path dataset:datasetSize ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "dataCollectionProcess" ; - sh:path dataset:dataCollectionProcess ], - [ sh:datatype core:DictionaryEntry ; + sh:name "datasetAvailability" ; + sh:path dataset:datasetAvailability ], + [ sh:class core:DictionaryEntry ; sh:name "sensor" ; sh:path dataset:sensor ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "datasetType" ; + sh:path dataset:datasetType ], + [ sh:class dataset:ConfidentialityLevelType ; + sh:maxCount 1 ; + sh:name "confidentialityLevel" ; + sh:path dataset:confidentialityLevel ], [ sh:datatype xsd:string ; sh:name "knownBias" ; sh:path dataset:knownBias ], @@ -641,51 +672,46 @@ External property restriction on /Core/Artifact/builtTime: minCount: 1""" ; sh:maxCount 1 ; sh:name "sensitivePersonalInformation" ; sh:path dataset:sensitivePersonalInformation ], - [ sh:datatype dataset:ConfidentialityLevelType ; - sh:maxCount 1 ; - sh:name "confidentialityLevel" ; - sh:path dataset:confidentialityLevel ], [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "intendedUse" ; - sh:path dataset:intendedUse ], + sh:name "dataPreprocessing" ; + sh:path dataset:dataPreprocessing ], + [ sh:datatype xsd:string ; + sh:name "anonymizationMethodUsed" ; + sh:path dataset:anonymizationMethodUsed ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "datasetUpdateMechanism" ; - sh:path dataset:datasetUpdateMechanism ], - [ sh:datatype dataset:DatasetAvailabilityType ; + sh:name "datasetNoise" ; + sh:path dataset:datasetNoise ], + [ sh:datatype xsd:nonNegativeInteger ; sh:maxCount 1 ; - sh:name "datasetAvailability" ; - sh:path dataset:datasetAvailability ], + sh:name "datasetSize" ; + sh:path dataset:datasetSize ], [ sh:datatype xsd:string ; - sh:name "anonymizationMethodUsed" ; - sh:path dataset:anonymizationMethodUsed ], + sh:maxCount 1 ; + sh:name "intendedUse" ; + sh:path dataset:intendedUse ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "datasetType" ; - sh:path dataset:datasetType ], + sh:name "dataCollectionProcess" ; + sh:path dataset:dataCollectionProcess ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "datasetNoise" ; - sh:path dataset:datasetNoise ] . + sh:name "datasetUpdateMechanism" ; + sh:path dataset:datasetUpdateMechanism ] . -dataset:Direct-Download a owl:NamedIndividual, + a owl:NamedIndividual, dataset:DatasetAvailabilityType . -dataset:Green a owl:NamedIndividual, - dataset:ConfidentialityLevelType . - -dataset:Query a owl:NamedIndividual, + a owl:NamedIndividual, dataset:DatasetAvailabilityType . -dataset:Red a owl:NamedIndividual, - dataset:ConfidentialityLevelType . + a owl:NamedIndividual, + dataset:DatasetAvailabilityType . -dataset:Registration a owl:NamedIndividual, + a owl:NamedIndividual, dataset:DatasetAvailabilityType . -dataset:Scraping-Script a owl:NamedIndividual, + a owl:NamedIndividual, dataset:DatasetAvailabilityType . licensing:ConjunctiveLicenseSet a owl:Class, @@ -703,7 +729,7 @@ Syntax does not take into account interpretation of license texts, which is left to the consumer of SPDX data to determine for themselves.""" ; rdfs:subClassOf licensing:AnyLicenseInfo ; ns0:term_status "Stable" ; - sh:property [ sh:datatype licensing:AnyLicenseInfo ; + sh:property [ sh:class licensing:AnyLicenseInfo ; sh:minCount 2 ; sh:name "member" ; sh:path licensing:member ] . @@ -739,7 +765,7 @@ would prefer to use. It is represented in the SPDX License Expression Syntax by the `OR` operator.""" ; rdfs:subClassOf licensing:AnyLicenseInfo ; ns0:term_status "Stable" ; - sh:property [ sh:datatype licensing:AnyLicenseInfo ; + sh:property [ sh:class licensing:AnyLicenseInfo ; sh:minCount 2 ; sh:name "member" ; sh:path licensing:member ] . @@ -815,7 +841,7 @@ data will need to determine for themselves what meaning to attribute to a "later version" operator for a particular License.""" ; rdfs:subClassOf licensing:AnyLicenseInfo ; ns0:term_status "Stable" ; - sh:property [ sh:datatype licensing:License ; + sh:property [ sh:class licensing:License ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "subjectLicense" ; @@ -830,16 +856,16 @@ Exceptions List (ListedLicenseException) or may be other additional text Syntax by the `WITH` operator.""" ; rdfs:subClassOf licensing:AnyLicenseInfo ; ns0:term_status "Stable" ; - sh:property [ sh:datatype licensing:License ; + sh:property [ sh:class licensing:LicenseAddition ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "subjectLicense" ; - sh:path licensing:subjectLicense ], - [ sh:datatype licensing:LicenseAddition ; + sh:name "subjectAddition" ; + sh:path licensing:subjectAddition ], + [ sh:class licensing:License ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "subjectAddition" ; - sh:path licensing:subjectAddition ] . + sh:name "subjectLicense" ; + sh:path licensing:subjectLicense ] . security:CvssV2VulnAssessmentRelationship a owl:Class, sh:NodeShape ; @@ -848,7 +874,8 @@ security:CvssV2VulnAssessmentRelationship a owl:Class, **Constraints** -The value of severity must be one of 'low', 'medium' or 'high' +- The value of severity must be one of 'low', 'medium' or 'high' +- The relationship type must be set to hasAssessmentFor. **Syntax** @@ -856,7 +883,7 @@ The value of severity must be one of 'low', 'medium' or 'high' { "@type": "CvssV2VulnAssessmentRelationship", "@id": "urn:spdx.dev:cvssv2-cve-2020-28498", - "relationshipType": "hasCvssV2AssessmentFor", + "relationshipType": "hasAssessmentFor", "score": 4.3, "vector": "(AV:N/AC:M/Au:N/C:P/I:N/A:N)", "severity": "low", @@ -885,8 +912,8 @@ The value of severity must be one of 'low', 'medium' or 'high' }, { "@type": "Relationship", - "@id": "urn:spdx.dev:vulnAgentRel-1", - "relationshipType": "publishedBy", + "@id": "urn:spdx.dev:vulnAgentRel-1", + "relationshipType": "publishedBy", "from": "urn:spdx.dev:cvssv2-cve-2020-28498", "to": ["urn:spdx.dev:agent-snyk"], "startTime": "2021-03-08T16:06:50Z" @@ -894,11 +921,7 @@ The value of severity must be one of 'low', 'medium' or 'high' ```""" ; rdfs:subClassOf security:VulnAssessmentRelationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "vector" ; - sh:path security:vector ], - [ sh:datatype xsd:string ; + sh:property [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "severity" ; sh:path security:severity ], @@ -906,19 +929,24 @@ The value of severity must be one of 'low', 'medium' or 'high' sh:maxCount 1 ; sh:minCount 1 ; sh:name "score" ; - sh:path security:score ] . + sh:path security:score ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "vector" ; + sh:path security:vector ] . security:CvssV3VulnAssessmentRelationship a owl:Class, sh:NodeShape ; rdfs:comment """A CvssV3VulnAssessmentRelationship relationship describes the determined score, severity, and vector of a vulnerability using version 3.1 of the Common -Vulnerability Scoring System (CVSS) as defined on +Vulnerability Scoring System (CVSS) as defined on [https://www.first.org/cvss/v3.1/specification-document](https://www.first.org/cvss/v3.1/specification-document). It is intented to communicate the results of using a CVSS calculator. **Constraints** -The value of severity must be one of 'none', 'low', 'medium', 'high' or 'critical'. -Absence of the property shall be interpreted as 'none'. +- The value of severity must be one of 'none', 'low', 'medium', 'high' or 'critical'. +- Absence of the property shall be interpreted as 'none'. +- The relationship type must be set to hasAssessmentFor. **Syntax** @@ -926,7 +954,7 @@ Absence of the property shall be interpreted as 'none'. { "@type": "CvssV3VulnAssessmentRelationship", "@id": "urn:spdx.dev:cvssv3-cve-2020-28498", - "relationshipType": "hasCvssV3AssessmentFor", + "relationshipType": "hasAssessmentFor", "severity": "medium", "score": 6.8, "vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N", @@ -964,34 +992,38 @@ Absence of the property shall be interpreted as 'none'. ```""" ; rdfs:subClassOf security:VulnAssessmentRelationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:decimal ; + sh:property [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "score" ; - sh:path security:score ], + sh:name "severity" ; + sh:path security:severity ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "vector" ; sh:path security:vector ], - [ sh:datatype xsd:string ; + [ sh:datatype xsd:decimal ; sh:maxCount 1 ; - sh:name "severity" ; - sh:path security:severity ] . + sh:minCount 1 ; + sh:name "score" ; + sh:path security:score ] . security:EpssVulnAssessmentRelationship a owl:Class, sh:NodeShape ; rdfs:comment """An EpssVulnAssessmentRelationship relationship describes the likelihood or probability that a vulnerability will be exploited in the wild using the Exploit -Prediction Scoring System (EPSS) as defined on +Prediction Scoring System (EPSS) as defined on [https://www.first.org/epss/model](https://www.first.org/epss/model). +**Constraints** + +- The relationship type must be set to hasAssessmentFor. + **Syntax** ```json { "@type": "EpssVulnAssessmentRelationship", "@id": "urn:spdx.dev:epss-1", - "relationshipType": "hasEpssAssessmentFor", + "relationshipType": "hasAssessmentFor", "probability": 80, "from": "urn:spdx.dev:vuln-cve-2020-28498", "to": ["urn:product-acme-application-1.3"], @@ -1001,30 +1033,40 @@ Prediction Scoring System (EPSS) as defined on ```""" ; rdfs:subClassOf security:VulnAssessmentRelationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "severity" ; - sh:path security:severity ], - [ sh:datatype xsd:nonNegativeInteger ; + sh:property [ sh:datatype xsd:nonNegativeInteger ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "probability" ; - sh:path security:probability ] . + sh:path security:probability ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "severity" ; + sh:path security:severity ] . + + a owl:NamedIndividual, + security:ExploitCatalogType . + + a owl:NamedIndividual, + security:ExploitCatalogType . security:ExploitCatalogVulnAssessmentRelationship a owl:Class, sh:NodeShape ; rdfs:comment """An ExploitCatalogVulnAssessmentRelationship describes if a vulnerability is listed in any exploit catalog such as the CISA Known Exploited Vulnerabilities -Catalog (KEV) +Catalog (KEV) [https://www.cisa.gov/known-exploited-vulnerabilities-catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog). +**Constraints** + +- The relationship type must be set to hasAssessmentFor. + **Syntax** ```json { "@type": "ExploitCatalogVulnAssessmentRelationship", "@id": "urn:spdx.dev:exploit-catalog-1", - "relationshipType": "hasExploitCatalogAssessmentFor", + "relationshipType": "hasAssessmentFor", "catalogType": "kev", "locator": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog", "exploited": "true", @@ -1036,12 +1078,7 @@ Catalog (KEV) ```""" ; rdfs:subClassOf security:VulnAssessmentRelationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype security:ExploitCatalogType ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "catalogType" ; - sh:path security:catalogType ], - [ sh:datatype xsd:anyURI ; + sh:property [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "locator" ; @@ -1050,7 +1087,24 @@ Catalog (KEV) sh:maxCount 1 ; sh:minCount 1 ; sh:name "exploited" ; - sh:path security:exploited ] . + sh:path security:exploited ], + [ sh:class security:ExploitCatalogType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "catalogType" ; + sh:path security:catalogType ] . + + a owl:NamedIndividual, + security:SsvcDecisionType . + + a owl:NamedIndividual, + security:SsvcDecisionType . + + a owl:NamedIndividual, + security:SsvcDecisionType . + + a owl:NamedIndividual, + security:SsvcDecisionType . security:SsvcVulnAssessmentRelationship a owl:Class, sh:NodeShape ; @@ -1059,13 +1113,17 @@ Stakeholder-Specific Vulnerability Categorization (SSVC) decision tree as defined on [https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc](https://www.cisa.gov/stakeholder-specific-vulnerability-categorization-ssvc). It is intended to communicate the results of using the CISA SSVC Calculator. +**Constraints** + +- The relationship type must be set to hasAssessmentFor. + **Syntax** ```json { "@type": "SsvcVulnAssessmentRelationship", "@id": "urn:spdx.dev:ssvc-1", - "relationshipType": "hasSsvcAssessmentFor", + "relationshipType": "hasAssessmentFor", "decisionType": "act", "from": "urn:spdx.dev:vuln-cve-2020-28498", "to": ["urn:product-acme-application-1.3"], @@ -1076,7 +1134,7 @@ It is intended to communicate the results of using the CISA SSVC Calculator. ```""" ; rdfs:subClassOf security:VulnAssessmentRelationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype security:SsvcDecisionType ; + sh:property [ sh:class security:SsvcDecisionType ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "decisionType" ; @@ -1113,13 +1171,13 @@ to the affects relationship type. ```""" ; rdfs:subClassOf security:VexVulnAssessmentRelationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:dateTime ; - sh:name "actionStatementTime" ; - sh:path security:actionStatementTime ], - [ sh:datatype xsd:string ; + sh:property [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "actionStatement" ; - sh:path security:actionStatement ] . + sh:path security:actionStatement ], + [ sh:datatype core:DateTime ; + sh:name "actionStatementTime" ; + sh:path security:actionStatementTime ] . security:VexFixedVulnAssessmentRelationship a owl:Class, sh:NodeShape ; @@ -1154,6 +1212,21 @@ element. rdfs:subClassOf security:VexVulnAssessmentRelationship ; ns0:term_status "Stable" . + a owl:NamedIndividual, + security:VexJustificationType . + + a owl:NamedIndividual, + security:VexJustificationType . + + a owl:NamedIndividual, + security:VexJustificationType . + + a owl:NamedIndividual, + security:VexJustificationType . + + a owl:NamedIndividual, + security:VexJustificationType . + security:VexNotAffectedVulnAssessmentRelationship a owl:Class, sh:NodeShape ; rdfs:comment """VexNotAffectedVulnAssessmentRelationship connects a vulnerability and a number @@ -1192,18 +1265,18 @@ for VEX. ```""" ; rdfs:subClassOf security:VexVulnAssessmentRelationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:dateTime ; + sh:property [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "impactStatementTime" ; sh:path security:impactStatementTime ], + [ sh:class security:VexJustificationType ; + sh:maxCount 1 ; + sh:name "justificationType" ; + sh:path security:justificationType ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "impactStatement" ; - sh:path security:impactStatement ], - [ sh:datatype security:VexJustificationType ; - sh:maxCount 1 ; - sh:name "justificationType" ; - sh:path security:justificationType ] . + sh:path security:impactStatement ] . security:VexUnderInvestigationVulnAssessmentRelationship a owl:Class, sh:NodeShape ; @@ -1249,7 +1322,7 @@ security:Vulnerability a owl:Class, "@type": "Vulnerability", "@id": "urn:spdx.dev:vuln-1", "summary": "Use of a Broken or Risky Cryptographic Algorithm", - "description": "The npm package `elliptic` before version 6.5.4 are vulnerable to Cryptographic Issues via the secp256k1 implementation in elliptic/ec/key.js. There is no check to confirm that the public key point passed into the derive function actually exists on the secp256k1 curve. This results in the potential for the private key used in this implementation to be revealed after a number of ECDH operations are performed.", + "description": "The npm package `elliptic` before version 6.5.4 are vulnerable to Cryptographic Issues via the secp256k1 implementation in elliptic/ec/key.js. There is no check to confirm that the public key point passed into the derive function actually exists on the secp256k1 curve. This results in the potential for the private key used in this implementation to be revealed after a number of ECDH operations are performed.", "modified": "2021-03-08T16:02:43Z", "published": "2021-03-08T16:06:50Z", "externalIdentifiers": [ @@ -1309,8 +1382,8 @@ security:Vulnerability a owl:Class, }, { "@type": "Relationship", - "@id": "urn:spdx.dev:vulnAgentRel-1", - "relationshipType": "publishedBy", + "@id": "urn:spdx.dev:vulnAgentRel-1", + "relationshipType": "publishedBy", "from": "urn:spdx.dev:vuln-1", "to": ["urn:spdx.dev:agent-snyk"], "startTime": "2021-03-08T16:06:50Z" @@ -1319,55 +1392,32 @@ security:Vulnerability a owl:Class, rdfs:subClassOf core:Element ; ns0:term_status "Stable" ; sh:property [ sh:datatype core:DateTime ; - sh:maxCount 1 ; - sh:name "publishedTime" ; - sh:path security:publishedTime ], - [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "withdrawnTime" ; sh:path security:withdrawnTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "publishedTime" ; + sh:path security:publishedTime ], [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "modifiedTime" ; sh:path security:modifiedTime ] . -security:act a owl:NamedIndividual, - security:SsvcDecisionType . - -security:attend a owl:NamedIndividual, - security:SsvcDecisionType . - -security:componentNotPresent a owl:NamedIndividual, - security:VexJustificationType . - -security:inlineMitigationsAlreadyExist a owl:NamedIndividual, - security:VexJustificationType . - -security:kev a owl:NamedIndividual, - security:ExploitCatalogType . - -security:other a owl:NamedIndividual, - security:ExploitCatalogType . - -security:track a owl:NamedIndividual, - security:SsvcDecisionType . - -security:trackStar a owl:NamedIndividual, - security:SsvcDecisionType . + a owl:NamedIndividual, + software:DependencyConditionalityType . -security:vulnerableCodeCannotBeControlledByAdversary a owl:NamedIndividual, - security:VexJustificationType . + a owl:NamedIndividual, + software:DependencyConditionalityType . -security:vulnerableCodeNotInExecutePath a owl:NamedIndividual, - security:VexJustificationType . + a owl:NamedIndividual, + software:DependencyConditionalityType . -security:vulnerableCodeNotPresent a owl:NamedIndividual, - security:VexJustificationType . + a owl:NamedIndividual, + software:DependencyConditionalityType . -security:withdrawn a owl:DatatypeProperty ; - rdfs:comment "Specified the time and date when a vulnerability was withdrawn." ; - rdfs:range core:DateTime ; - ns0:term_status "Stable" . + a owl:NamedIndividual, + software:DependencyConditionalityType . software:File a owl:Class, sh:NodeShape ; @@ -1381,6 +1431,24 @@ External property restriction on /Core/Element/name: minCount: 1""" ; sh:name "contentType" ; sh:path software:contentType ] . + a owl:NamedIndividual, + software:SBOMType . + + a owl:NamedIndividual, + software:SBOMType . + + a owl:NamedIndividual, + software:SBOMType . + + a owl:NamedIndividual, + software:SBOMType . + + a owl:NamedIndividual, + software:SBOMType . + + a owl:NamedIndividual, + software:SBOMType . + software:Sbom a owl:Class, sh:NodeShape ; rdfs:comment """A Software Bill of Materials (SBOM) is a collection of SPDX Elements describing a single package. @@ -1389,7 +1457,7 @@ provenance details of the product and/or its composition, licensing information, known quality or security issues, etc.""" ; rdfs:subClassOf core:Bom ; ns0:term_status "Stable" ; - sh:property [ sh:datatype software:SBOMType ; + sh:property [ sh:class software:SBOMType ; sh:name "sbomType" ; sh:path software:sbomType ] . @@ -1400,137 +1468,110 @@ that has been included from another original source. Snippets are useful for den may have been originally created under another license or copied from a place with a known vulnerability.""" ; rdfs:subClassOf software:SoftwareArtifact ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:PositiveIntegerRange ; + sh:property [ sh:class core:PositiveIntegerRange ; sh:maxCount 1 ; sh:name "lineRange" ; sh:path software:lineRange ], - [ sh:datatype core:PositiveIntegerRange ; + [ sh:class core:PositiveIntegerRange ; sh:maxCount 1 ; sh:name "byteRange" ; sh:path software:byteRange ] . + a owl:NamedIndividual, + software:SoftwareDependencyLinkType . + + a owl:NamedIndividual, + software:SoftwareDependencyLinkType . + + a owl:NamedIndividual, + software:SoftwareDependencyLinkType . + + a owl:NamedIndividual, + software:SoftwareDependencyLinkType . + software:SoftwareDependencyRelationship a owl:Class, sh:NodeShape ; rdfs:comment "TODO" ; rdfs:subClassOf core:LifecycleScopedRelationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype software:DependencyConditionalityType ; - sh:maxCount 1 ; - sh:name "conditionality" ; - sh:path software:conditionality ], - [ sh:datatype software:SoftwareDependencyLinkType ; + sh:property [ sh:class software:SoftwareDependencyLinkType ; sh:maxCount 1 ; sh:name "softwareLinkage" ; - sh:path software:softwareLinkage ] . - -software:analyzed a owl:NamedIndividual, - software:SBOMType . + sh:path software:softwareLinkage ], + [ sh:class software:DependencyConditionalityType ; + sh:maxCount 1 ; + sh:name "conditionality" ; + sh:path software:conditionality ] . -software:application a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:archive a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:bom a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:build a owl:NamedIndividual, - software:SBOMType . - -software:configuration a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:container a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:data a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:deployed a owl:NamedIndividual, - software:SBOMType . - -software:design a owl:NamedIndividual, - software:SBOMType . - -software:device a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:documentation a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:dynamic a owl:NamedIndividual, - software:SoftwareDependencyLinkType . - -software:evidence a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:executable a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:file a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:firmware a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:framework a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:install a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:library a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:manifest a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:module a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:operatingSystem a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:optional a owl:NamedIndividual, - software:DependencyConditionalityType . - -software:other a owl:NamedIndividual, - software:DependencyConditionalityType, - software:SoftwareDependencyLinkType, + a owl:NamedIndividual, software:SoftwarePurpose . -software:patch a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:prerequisite a owl:NamedIndividual, - software:DependencyConditionalityType . - -software:provided a owl:NamedIndividual, - software:DependencyConditionalityType . - -software:required a owl:NamedIndividual, - software:DependencyConditionalityType . - -software:requirement a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:runtime a owl:NamedIndividual, - software:SBOMType . - -software:source a owl:NamedIndividual, - software:SBOMType, + a owl:NamedIndividual, software:SoftwarePurpose . -software:specification a owl:NamedIndividual, + a owl:NamedIndividual, software:SoftwarePurpose . -software:static a owl:NamedIndividual, - software:SoftwareDependencyLinkType . - -software:tool a owl:NamedIndividual, - software:SoftwareDependencyLinkType . - ai:autonomyType a owl:DatatypeProperty ; rdfs:comment """AutonomyType indicates if a human is involved in any of the decisions of the AI software or if that software is fully automatic.""" ; @@ -1544,7 +1585,7 @@ can be expected to operate successfully. Examples include computer vision, natur ns0:term_status "Stable" . ai:energyConsumption a owl:DatatypeProperty ; - rdfs:comment """EnergyConsumption captures the amount of energy needed to train and operate the AI model. + rdfs:comment """EnergyConsumption captures the amount of energy needed to train and operate the AI model. This value is also known as training energy consumption or inference energy consumption.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . @@ -1557,14 +1598,14 @@ for example the optimization and learning rate used during the training of the m ns0:term_status "Stable" . ai:informationAboutApplication a owl:DatatypeProperty ; - rdfs:comment """InformationAboutApplication describes any relevant information in free form text about + rdfs:comment """InformationAboutApplication describes any relevant information in free form text about how the AI model is used inside the software, as well as any relevant pre-processing steps, third party APIs etc.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . ai:informationAboutTraining a owl:DatatypeProperty ; rdfs:comment """InformationAboutTraining describes the specific steps involved in the training of the AI model. -For example, it can be specified whether supervised fine-tuning +For example, it can be specified whether supervised fine-tuning or active learning is used as part of training the model.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . @@ -1577,14 +1618,14 @@ For instance, a limitation might be that the AI package cannot be used on datase ns0:term_status "Stable" . ai:metric a owl:DatatypeProperty ; - rdfs:comment """Metric records the measurement with which the AI model was evaluated. + rdfs:comment """Metric records the measurement with which the AI model was evaluated. This makes statements about the prediction quality including uncertainty, accuracy, characteristics of the tested population, quality, fairness, explainability, robustness etc.""" ; rdfs:range core:DictionaryEntry ; ns0:term_status "Stable" . ai:metricDecisionThreshold a owl:DatatypeProperty ; - rdfs:comment """Each metric might be computed based on a decision threshold. + rdfs:comment """Each metric might be computed based on a decision threshold. For instance, precision or recall is typically computed by checking if the probability of the outcome is larger than 0.5. Each decision threshold should match with a metric field defined in the AI Package.""" ; @@ -1617,14 +1658,14 @@ This might include biometric data, addresses or other data that can be used to i ns0:term_status "Stable" . ai:standardCompliance a owl:DatatypeProperty ; - rdfs:comment """StandardCompliance captures a standard that the AI software complies with. -This includes both published and unpublished standards, for example ISO, IEEE, ETSI etc. + rdfs:comment """StandardCompliance captures a standard that the AI software complies with. +This includes both published and unpublished standards, for example ISO, IEEE, ETSI etc. The standard could (but not necessarily have to) be used to satisfy a legal or regulatory requirement.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . ai:typeOfModel a owl:DatatypeProperty ; - rdfs:comment """TypeOfModel records the type of the AI model(s) used in the software. + rdfs:comment """TypeOfModel records the type of the AI model(s) used in the software. For instance, if it is a supervised model, unsupervised model, reinforcement learning model or a combination of those.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . @@ -1676,7 +1717,7 @@ steps: ns0:term_status "Stable" . build:configSourceUri a owl:DatatypeProperty ; - rdfs:comment """If a build configuration exists for the toolchain or platform performing the build, the configSourceUri of a build is the URI of that build configuration. For example, a build triggered by a GitHub action is defined by a build configuration YAML file. In this case, the configSourceUri is the URL of that YAML file. + rdfs:comment """If a build configuration exists for the toolchain or platform performing the build, the configSourceUri of a build is the URI of that build configuration. For example, a build triggered by a GitHub action is defined by a build configuration YAML file. In this case, the configSourceUri is the URL of that YAML file. m""" ; rdfs:range xsd:anyURI ; ns0:term_status "Stable" . @@ -1697,27 +1738,27 @@ core:Artifact a owl:Class, such as an electronic file, a software package, a device or an element of data.""" ; rdfs:subClassOf core:Element ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:Identity ; + sh:property [ sh:class core:Agent ; sh:name "suppliedBy" ; sh:path core:suppliedBy ], - [ sh:datatype core:DateTime ; - sh:maxCount 1 ; - sh:name "validUntilTime" ; - sh:path core:validUntilTime ], - [ sh:datatype xsd:string ; - sh:name "standard" ; - sh:path core:standard ], [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "releaseTime" ; sh:path core:releaseTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "validUntilTime" ; + sh:path core:validUntilTime ], + [ sh:class core:Agent ; + sh:name "originatedBy" ; + sh:path core:originatedBy ], [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "builtTime" ; sh:path core:builtTime ], - [ sh:datatype core:Identity ; - sh:name "originatedBy" ; - sh:path core:originatedBy ] . + [ sh:datatype xsd:string ; + sh:name "standard" ; + sh:path core:standard ] . core:Bom a owl:Class, sh:NodeShape ; @@ -1734,27 +1775,27 @@ core:ElementCollection a owl:Class, rdfs:comment "An SpdxCollection is a collection of Elements, not necessarily with unifying context." ; rdfs:subClassOf core:Element ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:Element ; + sh:property [ sh:class core:ExternalMap ; + sh:name "imports" ; + sh:path core:imports ], + [ sh:class core:NamespaceMap ; + sh:name "namespaces" ; + sh:path core:namespaces ], + [ sh:class core:Element ; sh:minCount 1 ; sh:name "rootElement" ; sh:path core:rootElement ], - [ sh:datatype core:ExternalMap ; - sh:name "imports" ; - sh:path core:imports ], - [ sh:datatype core:Element ; + [ sh:class core:Element ; sh:minCount 1 ; sh:name "element" ; - sh:path core:element ], - [ sh:datatype core:NamespaceMap ; - sh:name "namespaces" ; - sh:path core:namespaces ] . + sh:path core:element ] . core:LifecycleScopedRelationship a owl:Class, sh:NodeShape ; rdfs:comment "TODO" ; rdfs:subClassOf core:Relationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:LifecycleScopeType ; + sh:property [ sh:class core:LifecycleScopeType ; sh:maxCount 1 ; sh:name "scope" ; sh:path core:scope ] . @@ -1801,7 +1842,7 @@ core:createdBy a owl:ObjectProperty ; rdfs:comment """CreatedBy identifies who or what created the Element. The generation method will assist the recipient of the Element in assessing the general reliability/accuracy of the analysis information.""" ; - rdfs:range core:Entity ; + rdfs:range core:Agent ; ns0:term_status "Stable" . core:createdUsing a owl:ObjectProperty ; @@ -1821,7 +1862,7 @@ however individuals can still contract with each other to restrict release of specific collections of SPDX files (which map to software bill of materials) and the identification of the supplier of SPDX files. Compliance with this document includes populating the SPDX fields therein -with data related to such fields ("SPDX-Metadata"). +with data related to such fields ("SPDX-Metadata"). This document contains numerous fields where an SPDX file creator may provide relevant explanatory text in SPDX-Metadata. Without opining on the lawfulness of "database rights" (in jurisdictions where applicable), @@ -1829,8 +1870,8 @@ such explanatory text is copyrightable subject matter in most Berne Convention c By using the SPDX specification, or any portion hereof, you hereby agree that any copyright rights (as determined by your jurisdiction) in any SPDX-Metadata, including without limitation explanatory text, -shall be subject to the terms of the Creative Commons CC0 1.0 Universal license. -For SPDX-Metadata not containing any copyright rights, +shall be subject to the terms of the Creative Commons CC0 1.0 Universal license. +For SPDX-Metadata not containing any copyright rights, you hereby agree and acknowledge that the SPDX-Metadata is provided to you “as-is” and without any representations or warranties of any kind concerning the SPDX-Metadata, express, implied, statutory or otherwise, including without limitation warranties @@ -1840,6 +1881,11 @@ whether or not discoverable, all to the greatest extent permissible under applic rdfs:range xsd:string ; ns0:term_status "Stable" . +core:definingDocument a owl:DatatypeProperty ; + rdfs:comment "A definingDocument property is used to link an Element identifier to an SpdxDocument which contains the definition for the Element." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + core:description a owl:DatatypeProperty ; rdfs:comment """This field is a detailed description of the Element. It may also be extracted from the Element itself. The intent is to provide recipients of the SPDX file with a detailed technical explanation @@ -1863,9 +1909,7 @@ core:endTime a owl:DatatypeProperty ; rdfs:range core:DateTime ; ns0:term_status "Stable" . -core:extension a owl:NamedIndividual, - core:ProfileIdentifierType ; - rdfs:comment "TODO" ; +core:extension rdfs:comment "TODO" ; ns0:term_status "Stable" . core:externalId a owl:DatatypeProperty ; @@ -1943,7 +1987,7 @@ core:namespace a owl:DatatypeProperty ; core:originatedBy a owl:ObjectProperty ; rdfs:comment "OriginatedBy identifies from where or whom the Element originally came." ; - rdfs:range core:Identity ; + rdfs:range core:Agent ; ns0:term_status "Stable" . core:prefix a owl:DatatypeProperty ; @@ -1978,14 +2022,6 @@ core:scope a owl:DatatypeProperty ; rdfs:range core:LifecycleScopeType ; ns0:term_status "Stable" . -core:spdxId a owl:DatatypeProperty ; - rdfs:comment """SpdxId uniquely identifies an Element which may thereby be referenced by other Elements. -These references may be internal or external. -While there may be several versions of the same Element, each one needs to be able to be referred to uniquely -so that relationships between Elements can be clearly articulated.""" ; - rdfs:range xsd:anyURI ; - ns0:term_status "Stable" . - core:specVersion a owl:DatatypeProperty ; rdfs:comment """The specVersion provides a reference number that can be used to understand how to parse and interpret an Element. It will enable both future changes to the specification and to support backward compatibility. @@ -1993,7 +2029,7 @@ The major version number shall be incremented when incompatible changes between (one or more sections are created, modified or deleted). The minor version number shall be incremented when backwards compatible changes are made. -Here, parties exchanging information in accordance with the SPDX specification need to provide +Here, parties exchanging information in accordance with the SPDX specification need to provide 100% transparency as to which SPDX specification version such information is conforming to.""" ; rdfs:range core:SemVer ; ns0:term_status "Stable" . @@ -2019,7 +2055,7 @@ core:subject a owl:ObjectProperty ; ns0:term_status "Stable" . core:summary a owl:DatatypeProperty ; - rdfs:comment """A summary is a short description of an Element. Here, the intent is to allow the Element creator to + rdfs:comment """A summary is a short description of an Element. Here, the intent is to allow the Element creator to provide concise information about the function or use of the Element.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . @@ -2099,7 +2135,7 @@ dataset:datasetUpdateMechanism a owl:DatatypeProperty ; dataset:intendedUse a owl:DatatypeProperty ; rdfs:comment """IntendedUse describes what the given dataset should be used for. -Some datasets are collected to be used only for particular purposes. +Some datasets are collected to be used only for particular purposes. For example, medical data collected from a specific demography might only be applicable for training machine learning models to make predictions for that demography. In such a case, the intendedUse field would capture this information. @@ -2339,12 +2375,22 @@ to remediate or mitigate the vulnerability.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . +security:actionStatementTime a owl:DatatypeProperty ; + rdfs:comment "TODO" ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + security:assessedElement a owl:ObjectProperty ; rdfs:comment """Specifies subpackages, files or snippets referenced by a security assessment to specify the precise location where a vulnerability was found.""" ; rdfs:range core:Element ; ns0:term_status "Stable" . +security:catalogType a owl:DatatypeProperty ; + rdfs:comment "A catalogType is a mandatory value and must select one of the two entries in the `ExploitCatalogType.md` vocabulary." ; + rdfs:range security:ExploitCatalogType ; + ns0:term_status "Stable" . + security:decisionType a owl:DatatypeProperty ; rdfs:comment "A decisionType is a mandatory value and must select one of the four entries in the `SsvcDecisionType.md` vocabulary." ; rdfs:range security:SsvcDecisionType ; @@ -2363,6 +2409,11 @@ must be provided.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . +security:impactStatementTime a owl:DatatypeProperty ; + rdfs:comment "TODO" ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + security:justificationType a owl:DatatypeProperty ; rdfs:comment """When stating that an element is not affected by a vulnerability, the VexNotAffectedVulnAssessmentRelationship must include a justification from the @@ -2373,12 +2424,37 @@ complementary to the justification label, but one of both MUST be defined.""" ; rdfs:range security:VexJustificationType ; ns0:term_status "Stable" . +security:locator a owl:DatatypeProperty ; + rdfs:comment "A locator provides the location of an exploit catalog." ; + rdfs:range xsd:anyURI ; + ns0:term_status "Stable" . + security:probability a owl:DatatypeProperty ; rdfs:comment """The probability score between 0 and 1 (0 and 100%) estimating the likelihood that a vulnerability will be exploited in the next 12 months.""" ; rdfs:range xsd:decimal ; ns0:term_status "Stable" . +security:statusNotes a owl:DatatypeProperty ; + rdfs:comment "TODO" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +security:suppliedBy a owl:ObjectProperty ; + rdfs:comment "Identify the actual distribution source for the vulnerability assessment relationship being referenced." ; + rdfs:range core:Agent ; + ns0:term_status "Stable" . + +security:vexVersion a owl:DatatypeProperty ; + rdfs:comment "TODO" ; + rdfs:range xsd:string ; + ns0:term_status "Stable" . + +software:additionalPurpose a owl:DatatypeProperty ; + rdfs:comment "Additional purpose provides information about the additional purposes of the software artifact in addition to the primaryPurpose." ; + rdfs:range software:SoftwarePurpose ; + ns0:term_status "Stable" . + software:attributionText a owl:DatatypeProperty ; rdfs:comment """An attributionText for a software Package, File or Snippet provides a consumer of SPDX data with acknowledgement content, to assist redistributors of the @@ -2401,8 +2477,8 @@ corresponding license).""" ; software:byteRange a owl:DatatypeProperty ; rdfs:comment """This field defines the byte range in the original host file that the snippet information applies to. -A range of bytes is independent of various formatting concerns, and the most accurate way -of referring to the differences. The choice was made to start the numbering of +A range of bytes is independent of various formatting concerns, and the most accurate way +of referring to the differences. The choice was made to start the numbering of the byte range at 1 to be consistent with the W3C pointer method vocabulary.""" ; rdfs:range core:PositiveIntegerRange ; ns0:term_status "Stable" . @@ -2436,7 +2512,7 @@ If the declaredLicense for a software Package, File or Snippet is a choice of more than one license (e.g. a license expression combining two licenses through use of the `OR` operator), then the concludedLicense may either retain the license choice or identify which license was chosen.""" ; - rdfs:range software:LicenseField ; + rdfs:range licensing:LicenseField ; ns0:term_status "Stable" . software:conditionality a owl:DatatypeProperty ; @@ -2517,13 +2593,13 @@ indicates that one of the following applies: * the SPDX data creator has made no attempt to determine this field; or * the SPDX data creator has intentionally provided no information (no meaning should be implied by doing so).""" ; - rdfs:range software:LicenseField ; + rdfs:range licensing:LicenseField ; ns0:term_status "Stable" . software:downloadLocation a owl:DatatypeProperty ; - rdfs:comment """DownloadLocation identifies the download Uniform Resource Identifier + rdfs:comment """DownloadLocation identifies the download Uniform Resource Identifier for the package at the time that the document was created. -Where and how to download the exact package being referenced +Where and how to download the exact package being referenced is critical for verification and tracking data.""" ; rdfs:range xsd:anyURI ; ns0:term_status "Stable" . @@ -2540,7 +2616,7 @@ referenced by the SPDX document creator.""" ; software:lineRange a owl:DatatypeProperty ; rdfs:comment """This field defines the line range in the original host file that the snippet information applies to. If there is a disagreement between the byte range and line range, the byte range values will take precedence. -A range of lines is a convenient reference for those files where there is a known line delimiter. +A range of lines is a convenient reference for those files where there is a known line delimiter. The choice was made to start the numbering of the lines at 1 to be consistent with the W3C pointer method vocabulary.""" ; rdfs:range core:PositiveIntegerRange ; ns0:term_status "Stable" . @@ -2555,8 +2631,8 @@ software:packageVersion a owl:DatatypeProperty ; rdfs:range xsd:string ; ns0:term_status "Stable" . -software:purpose a owl:DatatypeProperty ; - rdfs:comment "purpose provides information about the primary purpose of the software artifact." ; +software:primaryPurpose a owl:DatatypeProperty ; + rdfs:comment "primaryPurpose provides information about the primary purpose of the software artifact." ; rdfs:range software:SoftwarePurpose ; ns0:term_status "Stable" . @@ -2574,8 +2650,8 @@ software:softwareLinkage a owl:DatatypeProperty ; software:sourceInfo a owl:DatatypeProperty ; rdfs:comment """SourceInfo records any relevant background information or additional comments -about the origin of the package. For example, this field might include comments -indicating whether the package was pulled from a source code management system +about the origin of the package. For example, this field might include comments +indicating whether the package was pulled from a source code management system or has been repackaged. The creator can provide additional information to describe any anomalies or discoveries in the determination of the origin of the package.""" ; rdfs:range xsd:string ; @@ -2596,7 +2672,11 @@ core:ExternalIdentifier a owl:Class, rdfs:comment """An ExternalIdentifier is a reference to a resource outside the scope of SPDX-3.0 content that uniquely identifies an Element.""" ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:anyURI ; + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "comment" ; + sh:path core:comment ], + [ sh:datatype xsd:anyURI ; sh:name "identifierLocator" ; sh:path core:identifierLocator ], [ sh:datatype xsd:string ; @@ -2604,40 +2684,36 @@ that uniquely identifies an Element.""" ; sh:minCount 1 ; sh:name "identifier" ; sh:path core:identifier ], - [ sh:datatype core:ExternalIdentifierType ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "externalIdentifierType" ; - sh:path core:externalIdentifierType ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "comment" ; - sh:path core:comment ], [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:name "issuingAuthority" ; - sh:path core:issuingAuthority ] . + sh:path core:issuingAuthority ], + [ sh:class core:ExternalIdentifierType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "externalIdentifierType" ; + sh:path core:externalIdentifierType ] . core:ExternalReference a owl:Class, sh:NodeShape ; rdfs:comment """An External Reference points to a resource outside the scope of the SPDX-3.0 content that provides additional characteristics of an Element.""" ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:anyURI ; - sh:name "locator" ; - sh:path core:locator ], + sh:property [ sh:datatype core:MediaType ; + sh:maxCount 1 ; + sh:name "contentType" ; + sh:path core:contentType ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "comment" ; sh:path core:comment ], - [ sh:datatype core:MediaType ; - sh:maxCount 1 ; - sh:name "contentType" ; - sh:path core:contentType ], - [ sh:datatype core:ExternalReferenceType ; + [ sh:class core:ExternalReferenceType ; sh:maxCount 1 ; sh:name "externalReferenceType" ; - sh:path core:externalReferenceType ] . + sh:path core:externalReferenceType ], + [ sh:datatype xsd:anyURI ; + sh:name "locator" ; + sh:path core:locator ] . core:Hash a owl:Class, sh:NodeShape ; @@ -2649,31 +2725,31 @@ a function which is practically infeasible to invert. This is commonly used for integrity checking of data.""" ; rdfs:subClassOf core:IntegrityMethod ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; + sh:property [ sh:class core:HashAlgorithm ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "hashValue" ; - sh:path core:hashValue ], - [ sh:datatype core:HashAlgorithm ; + sh:name "algorithm" ; + sh:path core:algorithm ], + [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "algorithm" ; - sh:path core:algorithm ] . + sh:name "hashValue" ; + sh:path core:hashValue ] . core:Payload a owl:Class, sh:NodeShape ; rdfs:comment "TODO" ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:NamespaceMap ; - sh:name "namespaces" ; - sh:path core:namespaces ], - [ sh:datatype core:CreationInfo ; + sh:property [ sh:class core:ExternalMap ; + sh:name "imports" ; + sh:path core:imports ], + [ sh:class core:CreationInfo ; sh:maxCount 1 ; sh:name "creationInfo" ; sh:path core:creationInfo ], - [ sh:datatype core:ExternalMap ; - sh:name "imports" ; - sh:path core:imports ] . + [ sh:class core:NamespaceMap ; + sh:name "namespaces" ; + sh:path core:namespaces ] . core:Relationship a owl:Class, sh:NodeShape ; @@ -2685,27 +2761,27 @@ that one Element is related to one or more other Elements in some way.""" ; sh:maxCount 1 ; sh:name "endTime" ; sh:path core:endTime ], - [ sh:datatype core:RelationshipType ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "relationshipType" ; - sh:path core:relationshipType ], [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "startTime" ; sh:path core:startTime ], - [ sh:datatype core:Element ; + [ sh:class core:Element ; sh:name "to" ; sh:path core:to ], - [ sh:datatype core:RelationshipCompleteness ; + [ sh:class core:RelationshipType ; sh:maxCount 1 ; - sh:name "completeness" ; - sh:path core:completeness ], - [ sh:datatype core:Element ; + sh:minCount 1 ; + sh:name "relationshipType" ; + sh:path core:relationshipType ], + [ sh:class core:Element ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "from" ; - sh:path core:from ] . + sh:path core:from ], + [ sh:class core:RelationshipCompleteness ; + sh:maxCount 1 ; + sh:name "completeness" ; + sh:path core:completeness ] . core:SemVer a owl:Class, sh:NodeShape ; @@ -2718,7 +2794,7 @@ Format restriction: pattern: ^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-( core:Tool a owl:Class, sh:NodeShape ; rdfs:comment "A Tool is an element of hardware and/or software utilized to carry out a particular function." ; - rdfs:subClassOf core:Entity ; + rdfs:subClassOf core:Element ; ns0:term_status "Stable" . core:contentType a owl:DatatypeProperty ; @@ -2727,7 +2803,7 @@ core:contentType a owl:DatatypeProperty ; ns0:term_status "Stable" . core:name a owl:DatatypeProperty ; - rdfs:comment """This field identifies the name of an Element as designated by the creator. + rdfs:comment """This field identifies the name of an Element as designated by the creator. The name of an Element is an important convention and easier to refer to than the URI.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . @@ -2818,10 +2894,15 @@ from an assessment of its severity.""" ; rdfs:range xsd:string ; ns0:term_status "Stable" . +security:withdrawnTime a owl:DatatypeProperty ; + rdfs:comment "Specified the time and date when a vulnerability was withdrawn." ; + rdfs:range core:DateTime ; + ns0:term_status "Stable" . + software:Package a owl:Class, sh:NodeShape ; rdfs:comment """A package refers to any unit of content that can be associated with a distribution of software. -Typically, a package is composed of one or more files. +Typically, a package is composed of one or more files. Any of the following non-limiting examples may be (but are not required to be) represented in SPDX as a package: - a tarball, zip file or other archive @@ -2835,7 +2916,15 @@ Note that some of these could be represented in SPDX as a file as well. External property restriction on /Core/Element/name: minCount: 1""" ; rdfs:subClassOf software:SoftwareArtifact ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; + sh:property [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "homePage" ; + sh:path software:homePage ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "packageVersion" ; + sh:path software:packageVersion ], + [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "sourceInfo" ; sh:path software:sourceInfo ], @@ -2846,15 +2935,7 @@ External property restriction on /Core/Element/name: minCount: 1""" ; [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:name "downloadLocation" ; - sh:path software:downloadLocation ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "packageVersion" ; - sh:path software:packageVersion ], - [ sh:datatype xsd:anyURI ; - sh:maxCount 1 ; - sh:name "homePage" ; - sh:path software:homePage ] . + sh:path software:downloadLocation ] . core:creationInfo a owl:DatatypeProperty ; rdfs:comment "CreationInfo provides information about the creation of the Element." ; @@ -2872,10 +2953,6 @@ core:namespaces a owl:DatatypeProperty ; rdfs:range core:NamespaceMap ; ns0:term_status "Stable" . -security:ExploitCatalogType a owl:Class ; - rdfs:comment "ExploitCatalogType specifies the type of exploit catalog that a vulnerability is listed in." ; - ns0:term_status "Stable" . - security:severity a owl:DatatypeProperty ; rdfs:comment """The severity field provides a human readable string, a label that can be used as an English adjective that qualifies its numerical score.""" ; @@ -2888,29 +2965,33 @@ software:SoftwareArtifact a owl:Class, such as a package, a file, or a snippet.""" ; rdfs:subClassOf core:Artifact ; ns0:term_status "Stable" ; - sh:property [ sh:datatype software:SoftwarePurpose ; - sh:name "purpose" ; - sh:path software:purpose ], - [ sh:datatype licensing:LicenseField ; - sh:maxCount 1 ; - sh:name "concludedLicense" ; - sh:path software:concludedLicense ], - [ sh:datatype licensing:LicenseField ; + sh:property [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "declaredLicense" ; - sh:path software:declaredLicense ], + sh:name "copyrightText" ; + sh:path software:copyrightText ], [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:name "contentIdentifier" ; sh:path software:contentIdentifier ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "copyrightText" ; - sh:path software:copyrightText ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "attributionText" ; - sh:path software:attributionText ] . + sh:path software:attributionText ], + [ sh:class licensing:LicenseField ; + sh:maxCount 1 ; + sh:name "declaredLicense" ; + sh:path software:declaredLicense ], + [ sh:class software:SoftwarePurpose ; + sh:name "additionalPurpose" ; + sh:path software:additionalPurpose ], + [ sh:class software:SoftwarePurpose ; + sh:maxCount 1 ; + sh:name "primaryPurpose" ; + sh:path software:primaryPurpose ], + [ sh:class licensing:LicenseField ; + sh:maxCount 1 ; + sh:name "concludedLicense" ; + sh:path software:concludedLicense ] . core:AnnotationType a owl:Class ; rdfs:comment "AnnotationType specifies the type of an annotation." ; @@ -2918,7 +2999,7 @@ core:AnnotationType a owl:Class ; core:CreationInfo a owl:Class, sh:NodeShape ; - rdfs:comment """The CreationInfo provides information about who created the Element, and when and how it was created. + rdfs:comment """The CreationInfo provides information about who created the Element, and when and how it was created. The dateTime created is often the date of last change (e.g., a git commit date), not the date when the SPDX data was created, as doing so supports reproducible builds.""" ; ns0:term_status "Stable" ; @@ -2929,29 +3010,23 @@ The dateTime created is often the date of last change (e.g., a git commit date), [ sh:datatype core:SemVer ; sh:name "specVersion" ; sh:path core:specVersion ], - [ sh:datatype core:Entity ; + [ sh:class core:Agent ; sh:minCount 1 ; sh:name "createdBy" ; sh:path core:createdBy ], - [ sh:datatype core:ProfileIdentifierType ; + [ sh:class core:ProfileIdentifierType ; sh:minCount 1 ; sh:name "profile" ; sh:path core:profile ], - [ sh:datatype core:Tool ; - sh:name "createdUsing" ; - sh:path core:createdUsing ], + [ sh:datatype xsd:string ; + sh:name "dataLicense" ; + sh:path core:dataLicense ], [ sh:datatype core:DateTime ; sh:name "created" ; sh:path core:created ], - [ sh:datatype xsd:string ; - sh:name "dataLicense" ; - sh:path core:dataLicense ] . - -core:Entity a owl:Class, - sh:NodeShape ; - rdfs:comment "TODO" ; - rdfs:subClassOf core:Element ; - ns0:term_status "Stable" . + [ sh:class core:Tool ; + sh:name "createdUsing" ; + sh:path core:createdUsing ] . core:ExternalMap a owl:Class, sh:NodeShape ; @@ -2961,17 +3036,21 @@ The external map provides details about the externally-defined Element such as its provenance, where to retrieve it, and how to verify its integrity.""" ; ns0:term_status "Stable" ; sh:property [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "locationHint" ; + sh:path core:locationHint ], + [ sh:datatype xsd:anyURI ; + sh:maxCount 1 ; + sh:name "definingDocument" ; + sh:path core:definingDocument ], + [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "externalId" ; sh:path core:externalId ], - [ sh:datatype core:IntegrityMethod ; + [ sh:class core:IntegrityMethod ; sh:name "verifiedUsing" ; - sh:path core:verifiedUsing ], - [ sh:datatype xsd:anyURI ; - sh:maxCount 1 ; - sh:name "locationHint" ; - sh:path core:locationHint ] . + sh:path core:verifiedUsing ] . core:IntegrityMethod a owl:Class, sh:NodeShape ; @@ -2991,14 +3070,16 @@ core:NamespaceMap a owl:Class, shorter identifiers ("prefixes") instead of URIs to provide a more human-readable and smaller serialized representation of the Elements.""" ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "prefix" ; - sh:path core:prefix ], - [ sh:datatype xsd:anyURI ; + sh:property [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; + sh:minCount 1 ; sh:name "namespace" ; - sh:path core:namespace ] . + sh:path core:namespace ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "prefix" ; + sh:path core:prefix ] . core:PositiveIntegerRange a owl:Class, sh:NodeShape ; @@ -3026,45 +3107,49 @@ It may be an exception which is listed on the SPDX Exceptions List (ListedLicenseException), or may be any other additional text (as an exception or otherwise) which is defined by an SPDX data creator (CustomLicenseAddition).""" ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; + sh:property [ sh:datatype xsd:anyURI ; + sh:name "seeAlso" ; + sh:path licensing:seeAlso ], + [ sh:datatype xsd:boolean ; sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "additionId" ; - sh:path licensing:additionId ], + sh:name "isDeprecatedAdditionId" ; + sh:path licensing:isDeprecatedAdditionId ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "additionName" ; sh:path licensing:additionName ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "standardAdditionTemplate" ; - sh:path licensing:standardAdditionTemplate ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "additionComment" ; sh:path licensing:additionComment ], - [ sh:datatype xsd:anyURI ; - sh:name "seeAlso" ; - sh:path licensing:seeAlso ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "additionText" ; - sh:path licensing:additionText ], + sh:name "additionId" ; + sh:path licensing:additionId ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "obsoletedBy" ; sh:path licensing:obsoletedBy ], - [ sh:datatype xsd:boolean ; + [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "isDeprecatedAdditionId" ; - sh:path licensing:isDeprecatedAdditionId ] . + sh:minCount 1 ; + sh:name "additionText" ; + sh:path licensing:additionText ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "standardAdditionTemplate" ; + sh:path licensing:standardAdditionTemplate ] . + +security:ExploitCatalogType a owl:Class ; + rdfs:comment "ExploitCatalogType specifies the type of exploit catalog that a vulnerability is listed in." ; + ns0:term_status "Stable" . security:VexVulnAssessmentRelationship a owl:Class, sh:NodeShape ; rdfs:comment """VexVulnAssessmentRelationship is an abstract subclass that defined the common -properties shared by all the SPDX-VEX status relationships. +properties shared by all the SPDX-VEX status relationships. **Constraints** @@ -3078,7 +3163,7 @@ relationship can optionally specify _subcomponents_ using the assessedElement property. VEX inherits information from the document level down to its statements. When a -statement is missing information it can be completed by reading the equivalent +statement is missing information it can be completed by reading the equivalent field from the containing document. For example, if a VEX relationship is missing data in its createdBy property, tools must consider the entity listed in the CreationInfo section of the document as the VEX author. @@ -3088,12 +3173,12 @@ the document's date must be considered as authoritative.""" ; ns0:term_status "Stable" ; sh:property [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "statusNotes" ; - sh:path security:statusNotes ], + sh:name "vexVersion" ; + sh:path security:vexVersion ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "vexVersion" ; - sh:path security:vexVersion ] . + sh:name "statusNotes" ; + sh:path security:statusNotes ] . core:MediaType a owl:Class, sh:NodeShape ; @@ -3104,7 +3189,7 @@ A list of all possible media types is available at https://www.iana.org/assignme ns0:term_status "Stable" . core:RelationshipCompleteness a owl:Class ; - rdfs:comment """RelationshipCompleteness indicates whether a relationship is complete or + rdfs:comment """RelationshipCompleteness indicates whether a relationship is complete or known to be incomplete or if there is made no assertion either way.""" ; ns0:term_status "Stable" . @@ -3120,73 +3205,58 @@ licensing:License a owl:Class, (ListedLicense) or defined by an SPDX data creator (CustomLicense).""" ; rdfs:subClassOf licensing:AnyLicenseInfo ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; + sh:property [ sh:datatype xsd:boolean ; sh:maxCount 1 ; - sh:name "standardLicenseTemplate" ; - sh:path licensing:standardLicenseTemplate ], + sh:name "isOsiApproved" ; + sh:path licensing:isOsiApproved ], + [ sh:datatype xsd:anyURI ; + sh:name "seeAlso" ; + sh:path licensing:seeAlso ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "licenseName" ; - sh:path licensing:licenseName ], + sh:name "licenseComment" ; + sh:path licensing:licenseComment ], + [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:name "isDeprecatedLicenseId" ; + sh:path licensing:isDeprecatedLicenseId ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "obsoletedBy" ; - sh:path licensing:obsoletedBy ], + sh:name "standardLicenseHeader" ; + sh:path licensing:standardLicenseHeader ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "licenseText" ; sh:path licensing:licenseText ], - [ sh:datatype xsd:boolean ; + [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "isDeprecatedLicenseId" ; - sh:path licensing:isDeprecatedLicenseId ], - [ sh:datatype xsd:anyURI ; - sh:name "seeAlso" ; - sh:path licensing:seeAlso ], + sh:name "obsoletedBy" ; + sh:path licensing:obsoletedBy ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "licenseComment" ; - sh:path licensing:licenseComment ], - [ sh:datatype xsd:boolean ; + sh:minCount 1 ; + sh:name "licenseId" ; + sh:path licensing:licenseId ], + [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "isOsiApproved" ; - sh:path licensing:isOsiApproved ], + sh:minCount 1 ; + sh:name "licenseName" ; + sh:path licensing:licenseName ], [ sh:datatype xsd:boolean ; sh:maxCount 1 ; sh:name "isFsfLibre" ; sh:path licensing:isFsfLibre ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "licenseId" ; - sh:path licensing:licenseId ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "standardLicenseHeader" ; - sh:path licensing:standardLicenseHeader ] . - -licensing:LicenseField a owl:Class, - sh:NodeShape ; - rdfs:comment """A LicenseField is the primary value that is used by a licensing field for a -software Package, File or Snippet. It represents either a license expression, -or the values NOASSERTION or NONE. The specific meanings of NOASSERTION or -NONE for the particular licensing field are defined in the corresponding -property description.""" ; - ns0:term_status "Stable" . + sh:name "standardLicenseTemplate" ; + sh:path licensing:standardLicenseTemplate ] . ai:SafetyRiskAssessmentType a owl:Class ; rdfs:comment """Lists the different safety risk type values that can be used to describe the safety risk of AI software according to [Article 20 of Regulation 765/2008/EC](https://ec.europa.eu/docsroom/documents/17107/attachments/1/translations/en/renditions/pdf).""" ; ns0:term_status "Stable" . -core:Identity a owl:Class, - sh:NodeShape ; - rdfs:comment "An Identity is a grouping of identifying characteristics unique to an individual or organization." ; - rdfs:subClassOf core:Entity ; - ns0:term_status "Stable" . - dataset:ConfidentialityLevelType a owl:Class ; rdfs:comment "Describes the different confidentiality levels as given by the [Traffic Light Protocol](https://en.wikipedia.org/wiki/Traffic_Light_Protocol)." ; ns0:term_status "Stable" . @@ -3198,7 +3268,8 @@ security:SsvcDecisionType a owl:Class ; security:VulnAssessmentRelationship a owl:Class, sh:NodeShape ; rdfs:comment """VulnAssessmentRelationship is the ancestor class common to all vulnerability -assessment relationships. It factors out the common properties shared by them.""" ; +assessment relationships. It factors out the common properties shared by them. +External property restriction on /Core/Relationship/to: minCount: 1""" ; rdfs:subClassOf core:Relationship ; ns0:term_status "Stable" ; sh:property [ sh:datatype core:DateTime ; @@ -3209,18 +3280,18 @@ assessment relationships. It factors out the common properties shared by them."" sh:maxCount 1 ; sh:name "withdrawnTime" ; sh:path security:withdrawnTime ], - [ sh:datatype core:Identity ; - sh:maxCount 1 ; - sh:name "suppliedBy" ; - sh:path security:suppliedBy ], [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "modifiedTime" ; sh:path security:modifiedTime ], - [ sh:datatype core:Element ; + [ sh:class core:Element ; sh:maxCount 1 ; sh:name "assessedElement" ; - sh:path security:assessedElement ] . + sh:path security:assessedElement ], + [ sh:class core:Agent ; + sh:maxCount 1 ; + sh:name "suppliedBy" ; + sh:path security:suppliedBy ] . software:SoftwareDependencyLinkType a owl:Class ; rdfs:comment "TODO" ; @@ -3234,6 +3305,15 @@ dataset:DatasetAvailabilityType a owl:Class ; rdfs:comment "Describes the possible types of availability of a dataset, indicating whether the dataset can be directly downloaded, can be assembled using a script for scraping the data, is only available after a clickthrough or a registration form." ; ns0:term_status "Stable" . +licensing:LicenseField a owl:Class, + sh:NodeShape ; + rdfs:comment """A LicenseField is the primary value that is used by a licensing field for a +software Package, File or Snippet. It represents either a license expression, +or the values NOASSERTION or NONE. The specific meanings of NOASSERTION or +NONE for the particular licensing field are defined in the corresponding +property description.""" ; + ns0:term_status "Stable" . + security:VexJustificationType a owl:Class ; rdfs:comment "VexJustificationType specifies the type of Vulnerability Exploitability eXchange (VEX) justification." ; ns0:term_status "Stable" . @@ -3258,12 +3338,14 @@ additional text applied; or a set of licenses combined by applying "AND" and ns0:term_status "Stable" . software:SBOMType a owl:Class ; - rdfs:comment """The set of SBOM types with definitions as defined in [Types of Software Bill of Material (SBOM) Documents](https://www.cisa.gov/sites/default/files/2023-04/sbom-types-document-508c.pdf), published on April 21, 2023. + rdfs:comment """The set of SBOM types with definitions as defined in [Types of Software Bill of Material (SBOM) Documents](https://www.cisa.gov/sites/default/files/2023-04/sbom-types-document-508c.pdf), published on April 21, 2023. An SBOM type describes the most likely type of an SBOM from the producer perspective, so that consumers can draw conclusions about the data inside an SBOM. A single SBOM can have multiple SBOM document types associated with it.""" ; ns0:term_status "Stable" . -core:ExternalIdentifierType a owl:Class ; - rdfs:comment "ExteralIdentifierType specifies the type of an external identifier." ; +core:Agent a owl:Class, + sh:NodeShape ; + rdfs:comment "The Agent class represents anything that has the potential to act on a system. This could be a person, organization, software agent, etc. This is not to be confused with tools that are used to perform tasks." ; + rdfs:subClassOf core:Element ; ns0:term_status "Stable" . core:ProfileIdentifierType a owl:Class ; @@ -3284,6 +3366,10 @@ core:DictionaryEntry a owl:Class, sh:name "value" ; sh:path core:value ] . +core:ExternalIdentifierType a owl:Class ; + rdfs:comment "ExteralIdentifierType specifies the type of an external identifier." ; + ns0:term_status "Stable" . + core:Element a owl:Class, sh:NodeShape ; rdfs:comment """An Element is a representation of a fundamental concept either directly inherent @@ -3294,55 +3380,46 @@ unifying, and interoperable foundation for all explicit and inter-relatable content objects.""" ; rdfs:subClassOf core:Payload ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:anyURI ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "spdxId" ; - sh:path core:spdxId ], - [ sh:datatype core:ExternalIdentifier ; - sh:name "externalIdentifier" ; - sh:path core:externalIdentifier ], - [ sh:datatype core:IntegrityMethod ; + sh:property [ sh:class core:IntegrityMethod ; sh:name "verifiedUsing" ; sh:path core:verifiedUsing ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "name" ; - sh:path core:name ], + sh:name "summary" ; + sh:path core:summary ], [ sh:datatype core:Extension ; sh:name "extension" ; sh:path core:extension ], - [ sh:datatype core:ExternalReference ; - sh:name "externalReference" ; - sh:path core:externalReference ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "summary" ; - sh:path core:summary ], + [ sh:class core:ExternalIdentifier ; + sh:name "externalIdentifier" ; + sh:path core:externalIdentifier ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "description" ; - sh:path core:description ], - [ sh:datatype core:CreationInfo ; + sh:name "comment" ; + sh:path core:comment ], + [ sh:class core:CreationInfo ; sh:maxCount 1 ; sh:name "creationInfo" ; sh:path core:creationInfo ], + [ sh:class core:ExternalReference ; + sh:name "externalReference" ; + sh:path core:externalReference ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "comment" ; - sh:path core:comment ] . + sh:name "name" ; + sh:path core:name ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "description" ; + sh:path core:description ] . core:ExternalReferenceType a owl:Class ; rdfs:comment "ExteralReferenceType specifies the type of an external reference." ; ns0:term_status "Stable" . -core:DateTime a owl:Class, - sh:NodeShape ; - rdfs:comment """A Datetime is a string representation of a specific date and time. -It has resolution of seconds and is always expressed in UTC timezone. -The specific format is one of the most commonly used ISO-8601 formats. -Format restriction: pattern: ^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\dZ$""" ; - rdfs:subClassOf xsd:string ; +core:HashAlgorithm a owl:Class ; + rdfs:comment """A HashAlgorithm is a mathematical algorithm that maps data of arbitrary size to a bit string (the hash) +and is a one-way function, that is, a function which is practically infeasible to invert.""" ; ns0:term_status "Stable" . software:SoftwarePurpose a owl:Class ; @@ -3353,9 +3430,13 @@ from the producer and consumer perspective from which both parties can draw conc about the context in which the Element exists.""" ; ns0:term_status "Stable" . -core:HashAlgorithm a owl:Class ; - rdfs:comment """A HashAlgorithm is a mathematical algorithm that maps data of arbitrary size to a bit string (the hash) -and is a one-way function, that is, a function which is practically infeasible to invert.""" ; +core:DateTime a owl:Class, + sh:NodeShape ; + rdfs:comment """A Datetime is a string representation of a specific date and time. +It has resolution of seconds and is always expressed in UTC timezone. +The specific format is one of the most commonly used ISO-8601 formats. +Format restriction: pattern: ^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\dZ$""" ; + rdfs:subClassOf xsd:string ; ns0:term_status "Stable" . core:RelationshipType a owl:Class ; From fee2adb51431f00c52c2b2f55e089b74689572cb Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Fri, 26 May 2023 14:02:59 +0200 Subject: [PATCH 251/354] Properly add all namespaces from OWL to json-ld context Signed-off-by: Holger Frydrych --- src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py index 49119719e..2a55b62d8 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py +++ b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py @@ -48,11 +48,7 @@ def convert_spdx_owl_to_jsonld_context(spdx_owl: str = "SPDX_OWL.json"): with open(spdx_owl, "r") as infile: owl_dict = json.load(infile) - context_dict = { - "core": "https://spdx.org/rdf/Core/", - "software": "https://spdx.org/rdf/Software/", - "xsd": "http://www.w3.org/2001/XMLSchema#", - } + context_dict = owl_dict["@context"] for node in owl_dict["@graph"]: # print(node) From a990d04bbb64bdd049f1caa947cabd7b106441c0 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Fri, 26 May 2023 14:03:21 +0200 Subject: [PATCH 252/354] Update json-ld context Signed-off-by: Holger Frydrych --- .../spdx3/writer/json_ld/context.json | 115 ++++++++++++------ 1 file changed, 80 insertions(+), 35 deletions(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/context.json b/src/spdx_tools/spdx3/writer/json_ld/context.json index 6616f9d6b..b1015ce7f 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/context.json +++ b/src/spdx_tools/spdx3/writer/json_ld/context.json @@ -1,5 +1,14 @@ { + "ai": "https://spdx.org/rdf/AI/", + "build": "https://spdx.org/rdf/Build/", "core": "https://spdx.org/rdf/Core/", + "dataset": "https://spdx.org/rdf/Dataset/", + "licensing": "https://spdx.org/rdf/Licensing/", + "ns0": "http://www.w3.org/2003/06/sw-vocab-status/ns#", + "owl": "http://www.w3.org/2002/07/owl#", + "rdfs": "http://www.w3.org/2000/01/rdf-schema#", + "security": "https://spdx.org/rdf/Security/", + "sh": "http://www.w3.org/ns/shacl#", "software": "https://spdx.org/rdf/Software/", "xsd": "http://www.w3.org/2001/XMLSchema#", "AIPackage": "ai:AIPackage", @@ -8,7 +17,12 @@ "AnonymousPayload": "core:AnonymousPayload", "Organization": "core:Organization", "Person": "core:Person", + "SoftwareAgent": "core:SoftwareAgent", "SpdxDocument": "core:SpdxDocument", + "spdxId": { + "@id": "core:spdxId", + "@type": "xsd:anyURI" + }, "Dataset": "dataset:Dataset", "ConjunctiveLicenseSet": "licensing:ConjunctiveLicenseSet", "CustomLicense": "licensing:CustomLicense", @@ -30,10 +44,6 @@ "VexNotAffectedVulnAssessmentRelationship": "security:VexNotAffectedVulnAssessmentRelationship", "VexUnderInvestigationVulnAssessmentRelationship": "security:VexUnderInvestigationVulnAssessmentRelationship", "Vulnerability": "security:Vulnerability", - "withdrawn": { - "@id": "security:withdrawn", - "@type": "core:DateTime" - }, "File": "software:File", "Sbom": "software:Sbom", "Snippet": "software:Snippet", @@ -183,7 +193,7 @@ }, "createdBy": { "@id": "core:createdBy", - "@type": "core:Entity" + "@type": "@id" }, "createdUsing": { "@id": "core:createdUsing", @@ -193,13 +203,17 @@ "@id": "core:dataLicense", "@type": "xsd:string" }, + "definingDocument": { + "@id": "core:definingDocument", + "@type": "xsd:anyURI" + }, "description": { "@id": "core:description", "@type": "xsd:string" }, "element": { "@id": "core:element", - "@type": "core:Element" + "@type": "@id" }, "end": { "@id": "core:end", @@ -237,7 +251,7 @@ }, "from": { "@id": "core:from", - "@type": "core:Element" + "@type": "@id" }, "hashValue": { "@id": "core:hashValue", @@ -264,7 +278,7 @@ "@type": "xsd:anyURI" }, "locator": { - "@id": "core:locator", + "@id": "security:locator", "@type": "xsd:anyURI" }, "namespace": { @@ -273,7 +287,7 @@ }, "originatedBy": { "@id": "core:originatedBy", - "@type": "core:Identity" + "@type": "@id" }, "prefix": { "@id": "core:prefix", @@ -283,7 +297,15 @@ "@id": "core:profile", "@type": "@vocab", "@context": { - "@vocab": "core:ProfileIdentifierType/" + "core": "https://spdx.org/rdf/Core/ProfileIdentifierType/core", + "software": "https://spdx.org/rdf/Core/ProfileIdentifierType/software", + "licensing": "https://spdx.org/rdf/Core/ProfileIdentifierType/licensing", + "security": "https://spdx.org/rdf/Core/ProfileIdentifierType/security", + "build": "https://spdx.org/rdf/Core/ProfileIdentifierType/build", + "ai": "https://spdx.org/rdf/Core/ProfileIdentifierType/ai", + "dataset": "https://spdx.org/rdf/Core/ProfileIdentifierType/dataset", + "usage": "https://spdx.org/rdf/Core/ProfileIdentifierType/usage", + "extension": "https://spdx.org/rdf/Core/ProfileIdentifierType/extension" } }, "relationshipType": { @@ -299,7 +321,7 @@ }, "rootElement": { "@id": "core:rootElement", - "@type": "core:Element" + "@type": "@id" }, "scope": { "@id": "core:scope", @@ -308,10 +330,6 @@ "@vocab": "core:LifecycleScopeType/" } }, - "spdxId": { - "@id": "core:spdxId", - "@type": "xsd:anyURI" - }, "specVersion": { "@id": "core:specVersion", "@type": "core:SemVer" @@ -330,19 +348,19 @@ }, "subject": { "@id": "core:subject", - "@type": "core:Element" + "@type": "@id" }, "summary": { "@id": "core:summary", "@type": "xsd:string" }, "suppliedBy": { - "@id": "core:suppliedBy", - "@type": "core:Agent" + "@id": "security:suppliedBy", + "@type": "@id" }, "to": { "@id": "core:to", - "@type": "core:Element" + "@type": "@id" }, "validUntilTime": { "@id": "core:validUntilTime", @@ -474,9 +492,20 @@ "@id": "security:actionStatement", "@type": "xsd:string" }, + "actionStatementTime": { + "@id": "security:actionStatementTime", + "@type": "core:DateTime" + }, "assessedElement": { "@id": "security:assessedElement", - "@type": "core:Element" + "@type": "@id" + }, + "catalogType": { + "@id": "security:catalogType", + "@type": "@vocab", + "@context": { + "@vocab": "security:ExploitCatalogType/" + } }, "decisionType": { "@id": "security:decisionType", @@ -493,6 +522,10 @@ "@id": "security:impactStatement", "@type": "xsd:string" }, + "impactStatementTime": { + "@id": "security:impactStatementTime", + "@type": "core:DateTime" + }, "justificationType": { "@id": "security:justificationType", "@type": "@vocab", @@ -504,6 +537,18 @@ "@id": "security:probability", "@type": "xsd:decimal" }, + "statusNotes": { + "@id": "security:statusNotes", + "@type": "xsd:string" + }, + "vexVersion": { + "@id": "security:vexVersion", + "@type": "xsd:string" + }, + "additionalPurpose": { + "@id": "software:additionalPurpose", + "@type": "software:SoftwarePurpose" + }, "attributionText": { "@id": "software:attributionText", "@type": "xsd:string" @@ -514,7 +559,7 @@ }, "concludedLicense": { "@id": "software:concludedLicense", - "@type": "software:LicenseField" + "@type": "licensing:LicenseField" }, "conditionality": { "@id": "software:conditionality", @@ -537,7 +582,7 @@ }, "declaredLicense": { "@id": "software:declaredLicense", - "@type": "software:LicenseField" + "@type": "licensing:LicenseField" }, "downloadLocation": { "@id": "software:downloadLocation", @@ -559,12 +604,9 @@ "@id": "software:packageVersion", "@type": "xsd:string" }, - "purpose": { - "@id": "software:purpose", - "@type": "@vocab", - "@context": { - "@vocab": "software:SoftwarePurpose/" - } + "primaryPurpose": { + "@id": "software:primaryPurpose", + "@type": "software:SoftwarePurpose" }, "sbomType": { "@id": "software:sbomType", @@ -640,6 +682,10 @@ "@id": "security:vector", "@type": "xsd:string" }, + "withdrawnTime": { + "@id": "security:withdrawnTime", + "@type": "core:DateTime" + }, "Package": "software:Package", "creationInfo": { "@id": "core:creationInfo", @@ -653,7 +699,6 @@ "@id": "core:namespaces", "@type": "core:NamespaceMap" }, - "ExploitCatalogType": "security:ExploitCatalogType", "severity": { "@id": "security:severity", "@type": "xsd:string" @@ -661,12 +706,12 @@ "SoftwareArtifact": "software:SoftwareArtifact", "AnnotationType": "core:AnnotationType", "CreationInfo": "core:CreationInfo", - "Entity": "core:Entity", "ExternalMap": "core:ExternalMap", "IntegrityMethod": "core:IntegrityMethod", "NamespaceMap": "core:NamespaceMap", "PositiveIntegerRange": "core:PositiveIntegerRange", "LicenseAddition": "licensing:LicenseAddition", + "ExploitCatalogType": "security:ExploitCatalogType", "VexVulnAssessmentRelationship": "security:VexVulnAssessmentRelationship", "MediaType": "core:MediaType", "RelationshipCompleteness": "core:RelationshipCompleteness", @@ -675,27 +720,27 @@ "@type": "xsd:string" }, "License": "licensing:License", - "LicenseField": "licensing:LicenseField", "SafetyRiskAssessmentType": "ai:SafetyRiskAssessmentType", - "Identity": "core:Identity", "ConfidentialityLevelType": "dataset:ConfidentialityLevelType", "SsvcDecisionType": "security:SsvcDecisionType", "VulnAssessmentRelationship": "security:VulnAssessmentRelationship", "SoftwareDependencyLinkType": "software:SoftwareDependencyLinkType", "PresenceType": "ai:PresenceType", "DatasetAvailabilityType": "dataset:DatasetAvailabilityType", + "LicenseField": "licensing:LicenseField", "VexJustificationType": "security:VexJustificationType", "DependencyConditionalityType": "software:DependencyConditionalityType", "LifecycleScopeType": "core:LifecycleScopeType", "AnyLicenseInfo": "licensing:AnyLicenseInfo", "SBOMType": "software:SBOMType", - "ExternalIdentifierType": "core:ExternalIdentifierType", + "Agent": "core:Agent", "ProfileIdentifierType": "core:ProfileIdentifierType", "DictionaryEntry": "core:DictionaryEntry", + "ExternalIdentifierType": "core:ExternalIdentifierType", "Element": "core:Element", "ExternalReferenceType": "core:ExternalReferenceType", - "DateTime": "core:DateTime", - "SoftwarePurpose": "software:SoftwarePurpose", "HashAlgorithm": "core:HashAlgorithm", + "SoftwarePurpose": "software:SoftwarePurpose", + "DateTime": "core:DateTime", "RelationshipType": "core:RelationshipType" } From 1a03af6fcd784f9e810d1db66a996d654f6e5731 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Fri, 26 May 2023 14:29:22 +0200 Subject: [PATCH 253/354] Properly represent byte_range and line_range with explicit PositiveIntegerRange type Signed-off-by: Holger Frydrych --- .../spdx3/bump_from_spdx2/snippet.py | 11 ++++++++--- .../spdx3/model/positive_integer_range.py | 18 ++++++++++++++++++ src/spdx_tools/spdx3/model/software/snippet.py | 11 ++++++----- 3 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 src/spdx_tools/spdx3/model/positive_integer_range.py diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index 78f9bb7d1..af7f48d17 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -1,11 +1,12 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from typing import List, Tuple, Optional from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import CreationInfo, ExternalMap +from spdx_tools.spdx3.model.positive_integer_range import PositiveIntegerRange from spdx_tools.spdx3.model.software import Snippet from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model import ExternalDocumentRef, ExtractedLicensingInfo, SpdxNoAssertion @@ -13,6 +14,10 @@ from spdx_tools.spdx.spdx_element_utils import get_full_element_spdx_id +def bump_integer_range(spdx2_range: Optional[Tuple[int, int]]) -> PositiveIntegerRange: + return PositiveIntegerRange(spdx2_range[0], spdx2_range[1]) if spdx2_range else None + + def bump_snippet( spdx2_snippet: Spdx2_Snippet, payload: Payload, @@ -52,8 +57,8 @@ def bump_snippet( creation_info=creation_info, name=spdx2_snippet.name, comment=spdx2_snippet.comment, - byte_range=spdx2_snippet.byte_range, - line_range=spdx2_snippet.line_range, + byte_range=bump_integer_range(spdx2_snippet.byte_range), + line_range=bump_integer_range(spdx2_snippet.line_range), copyright_text=copyright_text, attribution_text=", ".join(spdx2_snippet.attribution_texts), concluded_license=concluded_license, diff --git a/src/spdx_tools/spdx3/model/positive_integer_range.py b/src/spdx_tools/spdx3/model/positive_integer_range.py new file mode 100644 index 000000000..cbe1c6322 --- /dev/null +++ b/src/spdx_tools/spdx3/model/positive_integer_range.py @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties +from spdx_tools.common.typing.type_checks import check_types_and_set_values + + +@dataclass_with_properties +class PositiveIntegerRange: + begin: int + end: int + + def __init__( + self, + begin: int, + end: int, + ): + check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py index 3869de8b0..b3d955a20 100644 --- a/src/spdx_tools/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -2,20 +2,21 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import List, Optional, Tuple +from typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod from spdx_tools.spdx3.model.licensing import LicenseField +from spdx_tools.spdx3.model.positive_integer_range import PositiveIntegerRange from spdx_tools.spdx3.model.software import SoftwarePurpose from spdx_tools.spdx3.model.software.software_artifact import SoftwareArtifact @dataclass_with_properties class Snippet(SoftwareArtifact): - byte_range: Optional[Tuple[int, int]] = None - line_range: Optional[Tuple[int, int]] = None + byte_range: Optional[PositiveIntegerRange] = None + line_range: Optional[PositiveIntegerRange] = None def __init__( self, @@ -41,8 +42,8 @@ def __init__( declared_license: Optional[LicenseField] = None, copyright_text: Optional[str] = None, attribution_text: Optional[str] = None, - byte_range: Optional[Tuple[int, int]] = None, - line_range: Optional[Tuple[int, int]] = None, + byte_range: Optional[PositiveIntegerRange] = None, + line_range: Optional[PositiveIntegerRange] = None, ): verified_using = [] if verified_using is None else verified_using external_references = [] if external_references is None else external_references From 7bef1fe8a642f20204e3c7ea09d4705af9225d99 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Fri, 26 May 2023 14:48:57 +0200 Subject: [PATCH 254/354] fixme: licenseText is not optional in SPDX3, and an empty string is omitted in serialization Signed-off-by: Holger Frydrych --- src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py b/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py index 30dc0814e..6b65b6642 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py @@ -63,7 +63,7 @@ def bump_license_expression( ) if isinstance(license_expression, LicenseSymbol): if not get_spdx_licensing().validate(license_expression).invalid_symbols: - return ListedLicense(license_expression.key, license_expression.obj, "") + return ListedLicense(license_expression.key, license_expression.obj, "blank") else: for licensing_info in extracted_licensing_info: if licensing_info.license_id == license_expression.key: From 66f3dbe595721c01f523cc6215d9e5c728d252ac Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Fri, 26 May 2023 15:24:41 +0200 Subject: [PATCH 255/354] Fix broken references during bump so that the written test json validates properly against the shacl model. Also fill in required root elements for document. Signed-off-by: Holger Frydrych --- src/spdx_tools/spdx3/bump_from_spdx2/annotation.py | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/relationship.py | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py index 18519ec97..adcb51046 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py @@ -43,7 +43,7 @@ def bump_annotation( spdx_id, annotation_type, creation_info=creation_info, - subject=spdx2_annotation.spdx_id, + subject=f"{document_namespace}#{spdx2_annotation.spdx_id}", statement=spdx2_annotation.annotation_comment, ) ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py index 9be0c6330..106c92169 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py @@ -73,7 +73,7 @@ def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload name=spdx2_creation_info.name, comment=document_comment, element=[], - root_element=[], + root_element=[spdx_id], imports=imports, namespaces=namespaces, ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py index 0dbe264c6..d406713e6 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -204,9 +204,9 @@ def bump_relationship( return SoftwareDependencyRelationship( spdx_id, - from_element, + f"{document_namespace}#{from_element}", relationship_type, - to, + [f"{document_namespace}#{t}" for t in to], creation_info=creation_info, comment=spdx2_relationship.comment, completeness=completeness, @@ -217,9 +217,9 @@ def bump_relationship( return Relationship( spdx_id, - from_element, + f"{document_namespace}#{from_element}", relationship_type, - to, + [f"{document_namespace}#{t}" for t in to], creation_info=creation_info, comment=spdx2_relationship.comment, completeness=completeness, From d6635fcf29aebc1ee6677305f97e9b773e449769 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 30 May 2023 08:47:57 +0200 Subject: [PATCH 256/354] Update model and json-ld context with spdxId references removed Signed-off-by: Holger Frydrych --- .../spdx3/writer/json_ld/SPDX_OWL.json | 761 +++++++++--------- .../spdx3/writer/json_ld/context.json | 4 - src/spdx_tools/spdx3/writer/json_ld/model.ttl | 516 ++++++------ 3 files changed, 630 insertions(+), 651 deletions(-) diff --git a/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json b/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json index e7313911f..96e744e79 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json +++ b/src/spdx_tools/spdx3/writer/json_ld/SPDX_OWL.json @@ -26,33 +26,40 @@ }, "ns0:term_status": "Stable", "sh:property": [ + { + "sh:class": { + "@id": "core:DictionaryEntry" + }, + "sh:name": "metric", + "sh:path": { + "@id": "ai:metric" + } + }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:maxCount": 1, - "sh:name": "informationAboutApplication", + "sh:name": "modelExplainability", "sh:path": { - "@id": "ai:informationAboutApplication" + "@id": "ai:modelExplainability" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:name": "modelDataPreprocessing", + "sh:name": "domain", "sh:path": { - "@id": "ai:modelDataPreprocessing" + "@id": "ai:domain" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:maxCount": 1, - "sh:name": "informationAboutTraining", + "sh:name": "standardCompliance", "sh:path": { - "@id": "ai:informationAboutTraining" + "@id": "ai:standardCompliance" } }, { @@ -68,18 +75,20 @@ "sh:datatype": { "@id": "xsd:string" }, - "sh:name": "modelExplainability", + "sh:maxCount": 1, + "sh:name": "energyConsumption", "sh:path": { - "@id": "ai:modelExplainability" + "@id": "ai:energyConsumption" } }, { - "sh:class": { - "@id": "core:DictionaryEntry" + "sh:datatype": { + "@id": "xsd:string" }, - "sh:name": "metric", + "sh:maxCount": 1, + "sh:name": "limitation", "sh:path": { - "@id": "ai:metric" + "@id": "ai:limitation" } }, { @@ -96,67 +105,58 @@ "sh:datatype": { "@id": "xsd:string" }, - "sh:name": "typeOfModel", + "sh:name": "modelDataPreprocessing", "sh:path": { - "@id": "ai:typeOfModel" + "@id": "ai:modelDataPreprocessing" } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "ai:PresenceType" }, - "sh:name": "standardCompliance", + "sh:maxCount": 1, + "sh:name": "sensitivePersonalInformation", "sh:path": { - "@id": "ai:standardCompliance" + "@id": "ai:sensitivePersonalInformation" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:name": "domain", - "sh:path": { - "@id": "ai:domain" - } - }, - { - "sh:class": { - "@id": "ai:PresenceType" - }, "sh:maxCount": 1, - "sh:name": "autonomyType", + "sh:name": "informationAboutTraining", "sh:path": { - "@id": "ai:autonomyType" + "@id": "ai:informationAboutTraining" } }, { - "sh:class": { - "@id": "ai:PresenceType" + "sh:datatype": { + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "sensitivePersonalInformation", + "sh:name": "informationAboutApplication", "sh:path": { - "@id": "ai:sensitivePersonalInformation" + "@id": "ai:informationAboutApplication" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:maxCount": 1, - "sh:name": "limitation", + "sh:name": "typeOfModel", "sh:path": { - "@id": "ai:limitation" + "@id": "ai:typeOfModel" } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "ai:PresenceType" }, "sh:maxCount": 1, - "sh:name": "energyConsumption", + "sh:name": "autonomyType", "sh:path": { - "@id": "ai:energyConsumption" + "@id": "ai:autonomyType" } }, { @@ -232,60 +232,60 @@ "ns0:term_status": "Stable", "sh:property": [ { - "sh:datatype": { - "@id": "core:DateTime" + "sh:class": { + "@id": "core:Hash" }, - "sh:maxCount": 1, - "sh:name": "buildEndTime", + "sh:name": "configSourceDigest", "sh:path": { - "@id": "build:buildEndTime" + "@id": "build:configSourceDigest" } }, { "sh:datatype": { - "@id": "core:DateTime" + "@id": "xsd:anyURI" }, - "sh:maxCount": 1, - "sh:name": "buildStartTime", + "sh:name": "configSourceUri", "sh:path": { - "@id": "build:buildStartTime" + "@id": "build:configSourceUri" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:name": "configSourceEntrypoint", + "sh:maxCount": 1, + "sh:name": "buildId", "sh:path": { - "@id": "build:configSourceEntrypoint" + "@id": "build:buildId" } }, { "sh:class": { - "@id": "core:Hash" + "@id": "core:DictionaryEntry" }, - "sh:name": "configSourceDigest", + "sh:name": "parameters", "sh:path": { - "@id": "build:configSourceDigest" + "@id": "build:parameters" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "buildId", + "sh:name": "buildEndTime", "sh:path": { - "@id": "build:buildId" + "@id": "build:buildEndTime" } }, { - "sh:class": { - "@id": "core:DictionaryEntry" + "sh:datatype": { + "@id": "core:DateTime" }, - "sh:name": "parameters", + "sh:maxCount": 1, + "sh:name": "buildStartTime", "sh:path": { - "@id": "build:parameters" + "@id": "build:buildStartTime" } }, { @@ -310,11 +310,11 @@ }, { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:string" }, - "sh:name": "configSourceUri", + "sh:name": "configSourceEntrypoint", "sh:path": { - "@id": "build:configSourceUri" + "@id": "build:configSourceEntrypoint" } } ] @@ -333,11 +333,12 @@ "sh:property": [ { "sh:datatype": { - "@id": "core:MediaType" + "@id": "xsd:string" }, - "sh:name": "contentType", + "sh:maxCount": 1, + "sh:name": "statement", "sh:path": { - "@id": "core:contentType" + "@id": "core:statement" } }, { @@ -353,12 +354,11 @@ }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "core:MediaType" }, - "sh:maxCount": 1, - "sh:name": "statement", + "sh:name": "contentType", "sh:path": { - "@id": "core:statement" + "@id": "core:contentType" } }, { @@ -1427,15 +1427,6 @@ } } }, - { - "@id": "core:spdxId", - "@type": "owl:DatatypeProperty", - "rdfs:comment": "SpdxId uniquely identifies an Element which may thereby be referenced by other Elements.\nThese references may be internal or external.\nWhile there may be several versions of the same Element, each one needs to be able to be referred to uniquely\nso that relationships between Elements can be clearly articulated.", - "rdfs:range": { - "@id": "xsd:anyURI" - }, - "ns0:term_status": "Stable" - }, { "@id": "https://spdx.org/rdf/Dataset/ConfidentialityLevelType/Amber", "@type": [ @@ -1488,11 +1479,12 @@ }, { "sh:class": { - "@id": "core:DictionaryEntry" + "@id": "dataset:ConfidentialityLevelType" }, - "sh:name": "sensor", + "sh:maxCount": 1, + "sh:name": "confidentialityLevel", "sh:path": { - "@id": "dataset:sensor" + "@id": "dataset:confidentialityLevel" } }, { @@ -1500,20 +1492,19 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "datasetType", + "sh:name": "dataCollectionProcess", "sh:path": { - "@id": "dataset:datasetType" + "@id": "dataset:dataCollectionProcess" } }, { - "sh:class": { - "@id": "dataset:ConfidentialityLevelType" + "sh:datatype": { + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "confidentialityLevel", + "sh:name": "datasetUpdateMechanism", "sh:path": { - "@id": "dataset:confidentialityLevel" + "@id": "dataset:datasetUpdateMechanism" } }, { @@ -1527,60 +1518,60 @@ }, { "sh:datatype": { - "@id": "dataset:PresenceType" + "@id": "xsd:nonNegativeInteger" }, "sh:maxCount": 1, - "sh:name": "sensitivePersonalInformation", + "sh:name": "datasetSize", "sh:path": { - "@id": "dataset:sensitivePersonalInformation" + "@id": "dataset:datasetSize" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:name": "dataPreprocessing", + "sh:maxCount": 1, + "sh:name": "intendedUse", "sh:path": { - "@id": "dataset:dataPreprocessing" + "@id": "dataset:intendedUse" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "dataset:PresenceType" }, - "sh:name": "anonymizationMethodUsed", + "sh:maxCount": 1, + "sh:name": "sensitivePersonalInformation", "sh:path": { - "@id": "dataset:anonymizationMethodUsed" + "@id": "dataset:sensitivePersonalInformation" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:maxCount": 1, - "sh:name": "datasetNoise", + "sh:name": "dataPreprocessing", "sh:path": { - "@id": "dataset:datasetNoise" + "@id": "dataset:dataPreprocessing" } }, { "sh:datatype": { - "@id": "xsd:nonNegativeInteger" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "datasetSize", + "sh:name": "datasetNoise", "sh:path": { - "@id": "dataset:datasetSize" + "@id": "dataset:datasetNoise" } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "core:DictionaryEntry" }, - "sh:maxCount": 1, - "sh:name": "intendedUse", + "sh:name": "sensor", "sh:path": { - "@id": "dataset:intendedUse" + "@id": "dataset:sensor" } }, { @@ -1588,19 +1579,19 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "dataCollectionProcess", + "sh:minCount": 1, + "sh:name": "datasetType", "sh:path": { - "@id": "dataset:dataCollectionProcess" + "@id": "dataset:datasetType" } }, { "sh:datatype": { "@id": "xsd:string" }, - "sh:maxCount": 1, - "sh:name": "datasetUpdateMechanism", + "sh:name": "anonymizationMethodUsed", "sh:path": { - "@id": "dataset:datasetUpdateMechanism" + "@id": "dataset:anonymizationMethodUsed" } } ] @@ -1759,9 +1750,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "listVersionAdded", + "sh:name": "deprecatedVersion", "sh:path": { - "@id": "licensing:listVersionAdded" + "@id": "licensing:deprecatedVersion" } }, { @@ -1769,9 +1760,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "deprecatedVersion", + "sh:name": "listVersionAdded", "sh:path": { - "@id": "licensing:deprecatedVersion" + "@id": "licensing:listVersionAdded" } } ] @@ -1837,24 +1828,24 @@ "sh:property": [ { "sh:class": { - "@id": "licensing:LicenseAddition" + "@id": "licensing:License" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "subjectAddition", + "sh:name": "subjectLicense", "sh:path": { - "@id": "licensing:subjectAddition" + "@id": "licensing:subjectLicense" } }, { "sh:class": { - "@id": "licensing:License" + "@id": "licensing:LicenseAddition" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "subjectLicense", + "sh:name": "subjectAddition", "sh:path": { - "@id": "licensing:subjectLicense" + "@id": "licensing:subjectAddition" } } ] @@ -1873,23 +1864,23 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:decimal" }, "sh:maxCount": 1, - "sh:name": "severity", + "sh:minCount": 1, + "sh:name": "score", "sh:path": { - "@id": "security:severity" + "@id": "security:score" } }, { "sh:datatype": { - "@id": "xsd:decimal" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "score", + "sh:name": "severity", "sh:path": { - "@id": "security:score" + "@id": "security:severity" } }, { @@ -1918,12 +1909,13 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:decimal" }, "sh:maxCount": 1, - "sh:name": "severity", + "sh:minCount": 1, + "sh:name": "score", "sh:path": { - "@id": "security:severity" + "@id": "security:score" } }, { @@ -1938,13 +1930,12 @@ }, { "sh:datatype": { - "@id": "xsd:decimal" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "score", + "sh:name": "severity", "sh:path": { - "@id": "security:score" + "@id": "security:severity" } } ] @@ -2022,25 +2013,25 @@ } }, { - "sh:datatype": { - "@id": "xsd:boolean" + "sh:class": { + "@id": "security:ExploitCatalogType" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "exploited", + "sh:name": "catalogType", "sh:path": { - "@id": "security:exploited" + "@id": "security:catalogType" } }, { - "sh:class": { - "@id": "security:ExploitCatalogType" + "sh:datatype": { + "@id": "xsd:boolean" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "catalogType", + "sh:name": "exploited", "sh:path": { - "@id": "security:catalogType" + "@id": "security:exploited" } } ] @@ -2110,21 +2101,21 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:string" + "@id": "core:DateTime" }, - "sh:maxCount": 1, - "sh:name": "actionStatement", + "sh:name": "actionStatementTime", "sh:path": { - "@id": "security:actionStatement" + "@id": "security:actionStatementTime" } }, { "sh:datatype": { - "@id": "core:DateTime" + "@id": "xsd:string" }, - "sh:name": "actionStatementTime", + "sh:maxCount": 1, + "sh:name": "actionStatement", "sh:path": { - "@id": "security:actionStatementTime" + "@id": "security:actionStatement" } } ] @@ -2249,9 +2240,9 @@ "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "withdrawnTime", + "sh:name": "publishedTime", "sh:path": { - "@id": "security:withdrawnTime" + "@id": "security:publishedTime" } }, { @@ -2259,9 +2250,9 @@ "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "publishedTime", + "sh:name": "modifiedTime", "sh:path": { - "@id": "security:publishedTime" + "@id": "security:modifiedTime" } }, { @@ -2269,9 +2260,9 @@ "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "modifiedTime", + "sh:name": "withdrawnTime", "sh:path": { - "@id": "security:modifiedTime" + "@id": "security:withdrawnTime" } } ] @@ -2413,9 +2404,9 @@ "@id": "core:PositiveIntegerRange" }, "sh:maxCount": 1, - "sh:name": "lineRange", + "sh:name": "byteRange", "sh:path": { - "@id": "software:lineRange" + "@id": "software:byteRange" } }, { @@ -2423,9 +2414,9 @@ "@id": "core:PositiveIntegerRange" }, "sh:maxCount": 1, - "sh:name": "byteRange", + "sh:name": "lineRange", "sh:path": { - "@id": "software:byteRange" + "@id": "software:lineRange" } } ] @@ -2881,42 +2872,32 @@ }, "ns0:term_status": "Stable", "sh:property": [ - { - "sh:class": { - "@id": "core:Agent" - }, - "sh:name": "suppliedBy", - "sh:path": { - "@id": "core:suppliedBy" - } - }, { "sh:datatype": { "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "releaseTime", + "sh:name": "validUntilTime", "sh:path": { - "@id": "core:releaseTime" + "@id": "core:validUntilTime" } }, { - "sh:datatype": { - "@id": "core:DateTime" + "sh:class": { + "@id": "core:Agent" }, - "sh:maxCount": 1, - "sh:name": "validUntilTime", + "sh:name": "originatedBy", "sh:path": { - "@id": "core:validUntilTime" + "@id": "core:originatedBy" } }, { "sh:class": { "@id": "core:Agent" }, - "sh:name": "originatedBy", + "sh:name": "suppliedBy", "sh:path": { - "@id": "core:originatedBy" + "@id": "core:suppliedBy" } }, { @@ -2929,6 +2910,16 @@ "@id": "core:builtTime" } }, + { + "sh:datatype": { + "@id": "core:DateTime" + }, + "sh:maxCount": 1, + "sh:name": "releaseTime", + "sh:path": { + "@id": "core:releaseTime" + } + }, { "sh:datatype": { "@id": "xsd:string" @@ -2975,21 +2966,21 @@ }, { "sh:class": { - "@id": "core:NamespaceMap" + "@id": "core:Element" }, - "sh:name": "namespaces", + "sh:minCount": 1, + "sh:name": "rootElement", "sh:path": { - "@id": "core:namespaces" + "@id": "core:rootElement" } }, { "sh:class": { - "@id": "core:Element" + "@id": "core:NamespaceMap" }, - "sh:minCount": 1, - "sh:name": "rootElement", + "sh:name": "namespaces", "sh:path": { - "@id": "core:rootElement" + "@id": "core:namespaces" } }, { @@ -4030,29 +4021,29 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "comment", + "sh:minCount": 1, + "sh:name": "identifier", "sh:path": { - "@id": "core:comment" + "@id": "core:identifier" } }, { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:string" }, - "sh:name": "identifierLocator", + "sh:maxCount": 1, + "sh:name": "comment", "sh:path": { - "@id": "core:identifierLocator" + "@id": "core:comment" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:anyURI" }, - "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "identifier", + "sh:name": "identifierLocator", "sh:path": { - "@id": "core:identifier" + "@id": "core:identifierLocator" } }, { @@ -4088,42 +4079,42 @@ "ns0:term_status": "Stable", "sh:property": [ { - "sh:datatype": { - "@id": "core:MediaType" + "sh:class": { + "@id": "core:ExternalReferenceType" }, "sh:maxCount": 1, - "sh:name": "contentType", + "sh:name": "externalReferenceType", "sh:path": { - "@id": "core:contentType" + "@id": "core:externalReferenceType" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:anyURI" }, - "sh:maxCount": 1, - "sh:name": "comment", + "sh:name": "locator", "sh:path": { - "@id": "core:comment" + "@id": "core:locator" } }, { - "sh:class": { - "@id": "core:ExternalReferenceType" + "sh:datatype": { + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "externalReferenceType", + "sh:name": "comment", "sh:path": { - "@id": "core:externalReferenceType" + "@id": "core:comment" } }, { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "core:MediaType" }, - "sh:name": "locator", + "sh:maxCount": 1, + "sh:name": "contentType", "sh:path": { - "@id": "core:locator" + "@id": "core:contentType" } } ] @@ -4173,6 +4164,15 @@ "rdfs:comment": "TODO", "ns0:term_status": "Stable", "sh:property": [ + { + "sh:class": { + "@id": "core:NamespaceMap" + }, + "sh:name": "namespaces", + "sh:path": { + "@id": "core:namespaces" + } + }, { "sh:class": { "@id": "core:ExternalMap" @@ -4191,15 +4191,6 @@ "sh:path": { "@id": "core:creationInfo" } - }, - { - "sh:class": { - "@id": "core:NamespaceMap" - }, - "sh:name": "namespaces", - "sh:path": { - "@id": "core:namespaces" - } } ] }, @@ -4239,41 +4230,41 @@ "sh:class": { "@id": "core:Element" }, - "sh:name": "to", + "sh:maxCount": 1, + "sh:minCount": 1, + "sh:name": "from", "sh:path": { - "@id": "core:to" + "@id": "core:from" } }, { "sh:class": { - "@id": "core:RelationshipType" + "@id": "core:Element" }, - "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "relationshipType", + "sh:name": "to", "sh:path": { - "@id": "core:relationshipType" + "@id": "core:to" } }, { "sh:class": { - "@id": "core:Element" + "@id": "core:RelationshipCompleteness" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "from", + "sh:name": "completeness", "sh:path": { - "@id": "core:from" + "@id": "core:completeness" } }, { "sh:class": { - "@id": "core:RelationshipCompleteness" + "@id": "core:RelationshipType" }, "sh:maxCount": 1, - "sh:name": "completeness", + "sh:minCount": 1, + "sh:name": "relationshipType", "sh:path": { - "@id": "core:completeness" + "@id": "core:relationshipType" } } ] @@ -4462,22 +4453,22 @@ }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:anyURI" }, "sh:maxCount": 1, - "sh:name": "sourceInfo", + "sh:name": "packageUrl", "sh:path": { - "@id": "software:sourceInfo" + "@id": "software:packageUrl" } }, { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "packageUrl", + "sh:name": "sourceInfo", "sh:path": { - "@id": "software:packageUrl" + "@id": "software:sourceInfo" } }, { @@ -4540,16 +4531,6 @@ }, "ns0:term_status": "Stable", "sh:property": [ - { - "sh:datatype": { - "@id": "xsd:string" - }, - "sh:maxCount": 1, - "sh:name": "copyrightText", - "sh:path": { - "@id": "software:copyrightText" - } - }, { "sh:datatype": { "@id": "xsd:anyURI" @@ -4581,12 +4562,13 @@ } }, { - "sh:class": { - "@id": "software:SoftwarePurpose" + "sh:datatype": { + "@id": "xsd:string" }, - "sh:name": "additionalPurpose", + "sh:maxCount": 1, + "sh:name": "copyrightText", "sh:path": { - "@id": "software:additionalPurpose" + "@id": "software:copyrightText" } }, { @@ -4608,6 +4590,15 @@ "sh:path": { "@id": "software:concludedLicense" } + }, + { + "sh:class": { + "@id": "software:SoftwarePurpose" + }, + "sh:name": "additionalPurpose", + "sh:path": { + "@id": "software:additionalPurpose" + } } ] }, @@ -4637,12 +4628,12 @@ } }, { - "sh:datatype": { - "@id": "core:SemVer" + "sh:class": { + "@id": "core:Tool" }, - "sh:name": "specVersion", + "sh:name": "createdUsing", "sh:path": { - "@id": "core:specVersion" + "@id": "core:createdUsing" } }, { @@ -4656,40 +4647,40 @@ } }, { - "sh:class": { - "@id": "core:ProfileIdentifierType" + "sh:datatype": { + "@id": "core:DateTime" }, - "sh:minCount": 1, - "sh:name": "profile", + "sh:name": "created", "sh:path": { - "@id": "core:profile" + "@id": "core:created" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "core:SemVer" }, - "sh:name": "dataLicense", + "sh:name": "specVersion", "sh:path": { - "@id": "core:dataLicense" + "@id": "core:specVersion" } }, { - "sh:datatype": { - "@id": "core:DateTime" + "sh:class": { + "@id": "core:ProfileIdentifierType" }, - "sh:name": "created", + "sh:minCount": 1, + "sh:name": "profile", "sh:path": { - "@id": "core:created" + "@id": "core:profile" } }, { - "sh:class": { - "@id": "core:Tool" + "sh:datatype": { + "@id": "xsd:string" }, - "sh:name": "createdUsing", + "sh:name": "dataLicense", "sh:path": { - "@id": "core:createdUsing" + "@id": "core:dataLicense" } } ] @@ -4703,6 +4694,15 @@ "rdfs:comment": "An External Map is a map of Element identifiers that are used within a Document\nbut defined external to that Document.\nThe external map provides details about the externally-defined Element\nsuch as its provenance, where to retrieve it, and how to verify its integrity.", "ns0:term_status": "Stable", "sh:property": [ + { + "sh:class": { + "@id": "core:IntegrityMethod" + }, + "sh:name": "verifiedUsing", + "sh:path": { + "@id": "core:verifiedUsing" + } + }, { "sh:datatype": { "@id": "xsd:anyURI" @@ -4733,15 +4733,6 @@ "sh:path": { "@id": "core:externalId" } - }, - { - "sh:class": { - "@id": "core:IntegrityMethod" - }, - "sh:name": "verifiedUsing", - "sh:path": { - "@id": "core:verifiedUsing" - } } ] }, @@ -4775,24 +4766,24 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:string" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "namespace", + "sh:name": "prefix", "sh:path": { - "@id": "core:namespace" + "@id": "core:prefix" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:anyURI" }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "prefix", + "sh:name": "namespace", "sh:path": { - "@id": "core:prefix" + "@id": "core:namespace" } } ] @@ -4812,9 +4803,9 @@ }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "end", + "sh:name": "begin", "sh:path": { - "@id": "core:end" + "@id": "core:begin" } }, { @@ -4823,9 +4814,9 @@ }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "begin", + "sh:name": "end", "sh:path": { - "@id": "core:begin" + "@id": "core:end" } } ] @@ -4841,21 +4832,23 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:boolean" }, - "sh:name": "seeAlso", + "sh:maxCount": 1, + "sh:name": "isDeprecatedAdditionId", "sh:path": { - "@id": "licensing:seeAlso" + "@id": "licensing:isDeprecatedAdditionId" } }, { "sh:datatype": { - "@id": "xsd:boolean" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "isDeprecatedAdditionId", + "sh:minCount": 1, + "sh:name": "additionText", "sh:path": { - "@id": "licensing:isDeprecatedAdditionId" + "@id": "licensing:additionText" } }, { @@ -4864,19 +4857,18 @@ }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "additionName", + "sh:name": "additionId", "sh:path": { - "@id": "licensing:additionName" + "@id": "licensing:additionId" } }, { "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:anyURI" }, - "sh:maxCount": 1, - "sh:name": "additionComment", + "sh:name": "seeAlso", "sh:path": { - "@id": "licensing:additionComment" + "@id": "licensing:seeAlso" } }, { @@ -4884,10 +4876,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "additionId", + "sh:name": "obsoletedBy", "sh:path": { - "@id": "licensing:additionId" + "@id": "licensing:obsoletedBy" } }, { @@ -4895,9 +4886,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "obsoletedBy", + "sh:name": "standardAdditionTemplate", "sh:path": { - "@id": "licensing:obsoletedBy" + "@id": "licensing:standardAdditionTemplate" } }, { @@ -4906,9 +4897,9 @@ }, "sh:maxCount": 1, "sh:minCount": 1, - "sh:name": "additionText", + "sh:name": "additionName", "sh:path": { - "@id": "licensing:additionText" + "@id": "licensing:additionName" } }, { @@ -4916,9 +4907,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "standardAdditionTemplate", + "sh:name": "additionComment", "sh:path": { - "@id": "licensing:standardAdditionTemplate" + "@id": "licensing:additionComment" } } ] @@ -5004,21 +4995,22 @@ "sh:property": [ { "sh:datatype": { - "@id": "xsd:boolean" + "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "isOsiApproved", + "sh:name": "obsoletedBy", "sh:path": { - "@id": "licensing:isOsiApproved" + "@id": "licensing:obsoletedBy" } }, { "sh:datatype": { - "@id": "xsd:anyURI" + "@id": "xsd:string" }, - "sh:name": "seeAlso", + "sh:maxCount": 1, + "sh:name": "standardLicenseTemplate", "sh:path": { - "@id": "licensing:seeAlso" + "@id": "licensing:standardLicenseTemplate" } }, { @@ -5026,9 +5018,10 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "licenseComment", + "sh:minCount": 1, + "sh:name": "licenseText", "sh:path": { - "@id": "licensing:licenseComment" + "@id": "licensing:licenseText" } }, { @@ -5043,23 +5036,12 @@ }, { "sh:datatype": { - "@id": "xsd:string" - }, - "sh:maxCount": 1, - "sh:name": "standardLicenseHeader", - "sh:path": { - "@id": "licensing:standardLicenseHeader" - } - }, - { - "sh:datatype": { - "@id": "xsd:string" + "@id": "xsd:boolean" }, "sh:maxCount": 1, - "sh:minCount": 1, - "sh:name": "licenseText", + "sh:name": "isFsfLibre", "sh:path": { - "@id": "licensing:licenseText" + "@id": "licensing:isFsfLibre" } }, { @@ -5067,9 +5049,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "obsoletedBy", + "sh:name": "standardLicenseHeader", "sh:path": { - "@id": "licensing:obsoletedBy" + "@id": "licensing:standardLicenseHeader" } }, { @@ -5099,9 +5081,9 @@ "@id": "xsd:boolean" }, "sh:maxCount": 1, - "sh:name": "isFsfLibre", + "sh:name": "isOsiApproved", "sh:path": { - "@id": "licensing:isFsfLibre" + "@id": "licensing:isOsiApproved" } }, { @@ -5109,9 +5091,18 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "standardLicenseTemplate", + "sh:name": "licenseComment", "sh:path": { - "@id": "licensing:standardLicenseTemplate" + "@id": "licensing:licenseComment" + } + }, + { + "sh:datatype": { + "@id": "xsd:anyURI" + }, + "sh:name": "seeAlso", + "sh:path": { + "@id": "licensing:seeAlso" } } ] @@ -5151,49 +5142,49 @@ "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "publishedTime", + "sh:name": "withdrawnTime", "sh:path": { - "@id": "security:publishedTime" + "@id": "security:withdrawnTime" } }, { - "sh:datatype": { - "@id": "core:DateTime" + "sh:class": { + "@id": "core:Element" }, "sh:maxCount": 1, - "sh:name": "withdrawnTime", + "sh:name": "assessedElement", "sh:path": { - "@id": "security:withdrawnTime" + "@id": "security:assessedElement" } }, { - "sh:datatype": { - "@id": "core:DateTime" + "sh:class": { + "@id": "core:Agent" }, "sh:maxCount": 1, - "sh:name": "modifiedTime", + "sh:name": "suppliedBy", "sh:path": { - "@id": "security:modifiedTime" + "@id": "security:suppliedBy" } }, { - "sh:class": { - "@id": "core:Element" + "sh:datatype": { + "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "assessedElement", + "sh:name": "publishedTime", "sh:path": { - "@id": "security:assessedElement" + "@id": "security:publishedTime" } }, { - "sh:class": { - "@id": "core:Agent" + "sh:datatype": { + "@id": "core:DateTime" }, "sh:maxCount": 1, - "sh:name": "suppliedBy", + "sh:name": "modifiedTime", "sh:path": { - "@id": "security:suppliedBy" + "@id": "security:modifiedTime" } } ] @@ -5330,12 +5321,13 @@ "ns0:term_status": "Stable", "sh:property": [ { - "sh:class": { - "@id": "core:IntegrityMethod" + "sh:datatype": { + "@id": "xsd:string" }, - "sh:name": "verifiedUsing", + "sh:maxCount": 1, + "sh:name": "summary", "sh:path": { - "@id": "core:verifiedUsing" + "@id": "core:summary" } }, { @@ -5343,9 +5335,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "summary", + "sh:name": "description", "sh:path": { - "@id": "core:summary" + "@id": "core:description" } }, { @@ -5371,38 +5363,37 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "comment", + "sh:name": "name", "sh:path": { - "@id": "core:comment" + "@id": "core:name" } }, { "sh:class": { - "@id": "core:CreationInfo" + "@id": "core:ExternalReference" }, - "sh:maxCount": 1, - "sh:name": "creationInfo", + "sh:name": "externalReference", "sh:path": { - "@id": "core:creationInfo" + "@id": "core:externalReference" } }, { "sh:class": { - "@id": "core:ExternalReference" + "@id": "core:IntegrityMethod" }, - "sh:name": "externalReference", + "sh:name": "verifiedUsing", "sh:path": { - "@id": "core:externalReference" + "@id": "core:verifiedUsing" } }, { - "sh:datatype": { - "@id": "xsd:string" + "sh:class": { + "@id": "core:CreationInfo" }, "sh:maxCount": 1, - "sh:name": "name", + "sh:name": "creationInfo", "sh:path": { - "@id": "core:name" + "@id": "core:creationInfo" } }, { @@ -5410,9 +5401,9 @@ "@id": "xsd:string" }, "sh:maxCount": 1, - "sh:name": "description", + "sh:name": "comment", "sh:path": { - "@id": "core:description" + "@id": "core:comment" } } ] diff --git a/src/spdx_tools/spdx3/writer/json_ld/context.json b/src/spdx_tools/spdx3/writer/json_ld/context.json index b1015ce7f..fe165c445 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/context.json +++ b/src/spdx_tools/spdx3/writer/json_ld/context.json @@ -19,10 +19,6 @@ "Person": "core:Person", "SoftwareAgent": "core:SoftwareAgent", "SpdxDocument": "core:SpdxDocument", - "spdxId": { - "@id": "core:spdxId", - "@type": "xsd:anyURI" - }, "Dataset": "dataset:Dataset", "ConjunctiveLicenseSet": "licensing:ConjunctiveLicenseSet", "CustomLicense": "licensing:CustomLicense", diff --git a/src/spdx_tools/spdx3/writer/json_ld/model.ttl b/src/spdx_tools/spdx3/writer/json_ld/model.ttl index eaa3513ac..04b407217 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/model.ttl +++ b/src/spdx_tools/spdx3/writer/json_ld/model.ttl @@ -21,55 +21,55 @@ External property restriction on /Software/SoftwareArtifact/purpose: minCount: 1 External property restriction on /Core/Artifact/releaseTime: minCount: 1""" ; rdfs:subClassOf software:Package ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "informationAboutApplication" ; - sh:path ai:informationAboutApplication ], + sh:property [ sh:class core:DictionaryEntry ; + sh:name "metric" ; + sh:path ai:metric ], [ sh:datatype xsd:string ; - sh:name "modelDataPreprocessing" ; - sh:path ai:modelDataPreprocessing ], + sh:name "modelExplainability" ; + sh:path ai:modelExplainability ], [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "informationAboutTraining" ; - sh:path ai:informationAboutTraining ], + sh:name "domain" ; + sh:path ai:domain ], + [ sh:datatype xsd:string ; + sh:name "standardCompliance" ; + sh:path ai:standardCompliance ], [ sh:class core:DictionaryEntry ; sh:name "hyperparameter" ; sh:path ai:hyperparameter ], [ sh:datatype xsd:string ; - sh:name "modelExplainability" ; - sh:path ai:modelExplainability ], - [ sh:class core:DictionaryEntry ; - sh:name "metric" ; - sh:path ai:metric ], + sh:maxCount 1 ; + sh:name "energyConsumption" ; + sh:path ai:energyConsumption ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "limitation" ; + sh:path ai:limitation ], [ sh:class ai:SafetyRiskAssessmentType ; sh:maxCount 1 ; sh:name "safetyRiskAssessment" ; sh:path ai:safetyRiskAssessment ], [ sh:datatype xsd:string ; - sh:name "typeOfModel" ; - sh:path ai:typeOfModel ], - [ sh:datatype xsd:string ; - sh:name "standardCompliance" ; - sh:path ai:standardCompliance ], - [ sh:datatype xsd:string ; - sh:name "domain" ; - sh:path ai:domain ], - [ sh:class ai:PresenceType ; - sh:maxCount 1 ; - sh:name "autonomyType" ; - sh:path ai:autonomyType ], + sh:name "modelDataPreprocessing" ; + sh:path ai:modelDataPreprocessing ], [ sh:class ai:PresenceType ; sh:maxCount 1 ; sh:name "sensitivePersonalInformation" ; sh:path ai:sensitivePersonalInformation ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "limitation" ; - sh:path ai:limitation ], + sh:name "informationAboutTraining" ; + sh:path ai:informationAboutTraining ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "energyConsumption" ; - sh:path ai:energyConsumption ], + sh:name "informationAboutApplication" ; + sh:path ai:informationAboutApplication ], + [ sh:datatype xsd:string ; + sh:name "typeOfModel" ; + sh:path ai:typeOfModel ], + [ sh:class ai:PresenceType ; + sh:maxCount 1 ; + sh:name "autonomyType" ; + sh:path ai:autonomyType ], [ sh:class core:DictionaryEntry ; sh:name "metricDecisionThreshold" ; sh:path ai:metricDecisionThreshold ] . @@ -108,20 +108,12 @@ ExternalIdentifier of type "urlScheme" may be used to identify build logs. In th Note that buildStart and buildEnd are optional, and may be omitted to simplify creating reproducible builds.""" ; rdfs:subClassOf core:Element ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:DateTime ; - sh:maxCount 1 ; - sh:name "buildEndTime" ; - sh:path build:buildEndTime ], - [ sh:datatype core:DateTime ; - sh:maxCount 1 ; - sh:name "buildStartTime" ; - sh:path build:buildStartTime ], - [ sh:datatype xsd:string ; - sh:name "configSourceEntrypoint" ; - sh:path build:configSourceEntrypoint ], - [ sh:class core:Hash ; + sh:property [ sh:class core:Hash ; sh:name "configSourceDigest" ; sh:path build:configSourceDigest ], + [ sh:datatype xsd:anyURI ; + sh:name "configSourceUri" ; + sh:path build:configSourceUri ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "buildId" ; @@ -129,6 +121,14 @@ Note that buildStart and buildEnd are optional, and may be omitted to simplify c [ sh:class core:DictionaryEntry ; sh:name "parameters" ; sh:path build:parameters ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "buildEndTime" ; + sh:path build:buildEndTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "buildStartTime" ; + sh:path build:buildStartTime ], [ sh:class core:DictionaryEntry ; sh:name "environment" ; sh:path build:environment ], @@ -137,27 +137,27 @@ Note that buildStart and buildEnd are optional, and may be omitted to simplify c sh:minCount 1 ; sh:name "buildType" ; sh:path build:buildType ], - [ sh:datatype xsd:anyURI ; - sh:name "configSourceUri" ; - sh:path build:configSourceUri ] . + [ sh:datatype xsd:string ; + sh:name "configSourceEntrypoint" ; + sh:path build:configSourceEntrypoint ] . core:Annotation a owl:Class, sh:NodeShape ; rdfs:comment "An Annotation is an assertion made in relation to one or more elements." ; rdfs:subClassOf core:Element ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:MediaType ; - sh:name "contentType" ; - sh:path core:contentType ], + sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "statement" ; + sh:path core:statement ], [ sh:class core:Element ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "subject" ; sh:path core:subject ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "statement" ; - sh:path core:statement ], + [ sh:datatype core:MediaType ; + sh:name "contentType" ; + sh:path core:contentType ], [ sh:class core:AnnotationType ; sh:maxCount 1 ; sh:minCount 1 ; @@ -619,14 +619,6 @@ External property restriction on /Core/Element/name: minCount: 1""" ; sh:name "name" ; sh:path core:name ] . -core:spdxId a owl:DatatypeProperty ; - rdfs:comment """SpdxId uniquely identifies an Element which may thereby be referenced by other Elements. -These references may be internal or external. -While there may be several versions of the same Element, each one needs to be able to be referred to uniquely -so that relationships between Elements can be clearly articulated.""" ; - rdfs:range xsd:anyURI ; - ns0:term_status "Stable" . - a owl:NamedIndividual, dataset:ConfidentialityLevelType . @@ -653,21 +645,29 @@ External property restriction on /Core/Artifact/builtTime: minCount: 1""" ; sh:maxCount 1 ; sh:name "datasetAvailability" ; sh:path dataset:datasetAvailability ], - [ sh:class core:DictionaryEntry ; - sh:name "sensor" ; - sh:path dataset:sensor ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "datasetType" ; - sh:path dataset:datasetType ], [ sh:class dataset:ConfidentialityLevelType ; sh:maxCount 1 ; sh:name "confidentialityLevel" ; sh:path dataset:confidentialityLevel ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "dataCollectionProcess" ; + sh:path dataset:dataCollectionProcess ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "datasetUpdateMechanism" ; + sh:path dataset:datasetUpdateMechanism ], [ sh:datatype xsd:string ; sh:name "knownBias" ; sh:path dataset:knownBias ], + [ sh:datatype xsd:nonNegativeInteger ; + sh:maxCount 1 ; + sh:name "datasetSize" ; + sh:path dataset:datasetSize ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "intendedUse" ; + sh:path dataset:intendedUse ], [ sh:datatype dataset:PresenceType ; sh:maxCount 1 ; sh:name "sensitivePersonalInformation" ; @@ -675,29 +675,21 @@ External property restriction on /Core/Artifact/builtTime: minCount: 1""" ; [ sh:datatype xsd:string ; sh:name "dataPreprocessing" ; sh:path dataset:dataPreprocessing ], - [ sh:datatype xsd:string ; - sh:name "anonymizationMethodUsed" ; - sh:path dataset:anonymizationMethodUsed ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "datasetNoise" ; sh:path dataset:datasetNoise ], - [ sh:datatype xsd:nonNegativeInteger ; - sh:maxCount 1 ; - sh:name "datasetSize" ; - sh:path dataset:datasetSize ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "intendedUse" ; - sh:path dataset:intendedUse ], + [ sh:class core:DictionaryEntry ; + sh:name "sensor" ; + sh:path dataset:sensor ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "dataCollectionProcess" ; - sh:path dataset:dataCollectionProcess ], + sh:minCount 1 ; + sh:name "datasetType" ; + sh:path dataset:datasetType ], [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "datasetUpdateMechanism" ; - sh:path dataset:datasetUpdateMechanism ] . + sh:name "anonymizationMethodUsed" ; + sh:path dataset:anonymizationMethodUsed ] . a owl:NamedIndividual, dataset:DatasetAvailabilityType . @@ -795,12 +787,12 @@ https://spdx.org/licenses/exceptions-index.html.""" ; ns0:term_status "Stable" ; sh:property [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "listVersionAdded" ; - sh:path licensing:listVersionAdded ], + sh:name "deprecatedVersion" ; + sh:path licensing:deprecatedVersion ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "deprecatedVersion" ; - sh:path licensing:deprecatedVersion ] . + sh:name "listVersionAdded" ; + sh:path licensing:listVersionAdded ] . licensing:NoAssertionLicense a owl:Class, sh:NodeShape ; @@ -856,16 +848,16 @@ Exceptions List (ListedLicenseException) or may be other additional text Syntax by the `WITH` operator.""" ; rdfs:subClassOf licensing:AnyLicenseInfo ; ns0:term_status "Stable" ; - sh:property [ sh:class licensing:LicenseAddition ; + sh:property [ sh:class licensing:License ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "subjectAddition" ; - sh:path licensing:subjectAddition ], - [ sh:class licensing:License ; + sh:name "subjectLicense" ; + sh:path licensing:subjectLicense ], + [ sh:class licensing:LicenseAddition ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "subjectLicense" ; - sh:path licensing:subjectLicense ] . + sh:name "subjectAddition" ; + sh:path licensing:subjectAddition ] . security:CvssV2VulnAssessmentRelationship a owl:Class, sh:NodeShape ; @@ -921,15 +913,15 @@ security:CvssV2VulnAssessmentRelationship a owl:Class, ```""" ; rdfs:subClassOf security:VulnAssessmentRelationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "severity" ; - sh:path security:severity ], - [ sh:datatype xsd:decimal ; + sh:property [ sh:datatype xsd:decimal ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "score" ; sh:path security:score ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "severity" ; + sh:path security:severity ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "vector" ; @@ -992,19 +984,19 @@ Vulnerability Scoring System (CVSS) as defined on ```""" ; rdfs:subClassOf security:VulnAssessmentRelationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; + sh:property [ sh:datatype xsd:decimal ; sh:maxCount 1 ; - sh:name "severity" ; - sh:path security:severity ], + sh:minCount 1 ; + sh:name "score" ; + sh:path security:score ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "vector" ; sh:path security:vector ], - [ sh:datatype xsd:decimal ; + [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "score" ; - sh:path security:score ] . + sh:name "severity" ; + sh:path security:severity ] . security:EpssVulnAssessmentRelationship a owl:Class, sh:NodeShape ; @@ -1083,16 +1075,16 @@ Catalog (KEV) sh:minCount 1 ; sh:name "locator" ; sh:path security:locator ], - [ sh:datatype xsd:boolean ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "exploited" ; - sh:path security:exploited ], [ sh:class security:ExploitCatalogType ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "catalogType" ; - sh:path security:catalogType ] . + sh:path security:catalogType ], + [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "exploited" ; + sh:path security:exploited ] . a owl:NamedIndividual, security:SsvcDecisionType . @@ -1171,13 +1163,13 @@ to the affects relationship type. ```""" ; rdfs:subClassOf security:VexVulnAssessmentRelationship ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; + sh:property [ sh:datatype core:DateTime ; + sh:name "actionStatementTime" ; + sh:path security:actionStatementTime ], + [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "actionStatement" ; - sh:path security:actionStatement ], - [ sh:datatype core:DateTime ; - sh:name "actionStatementTime" ; - sh:path security:actionStatementTime ] . + sh:path security:actionStatement ] . security:VexFixedVulnAssessmentRelationship a owl:Class, sh:NodeShape ; @@ -1392,17 +1384,17 @@ security:Vulnerability a owl:Class, rdfs:subClassOf core:Element ; ns0:term_status "Stable" ; sh:property [ sh:datatype core:DateTime ; - sh:maxCount 1 ; - sh:name "withdrawnTime" ; - sh:path security:withdrawnTime ], - [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "publishedTime" ; sh:path security:publishedTime ], [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "modifiedTime" ; - sh:path security:modifiedTime ] . + sh:path security:modifiedTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "withdrawnTime" ; + sh:path security:withdrawnTime ] . a owl:NamedIndividual, software:DependencyConditionalityType . @@ -1470,12 +1462,12 @@ may have been originally created under another license or copied from a place wi ns0:term_status "Stable" ; sh:property [ sh:class core:PositiveIntegerRange ; sh:maxCount 1 ; - sh:name "lineRange" ; - sh:path software:lineRange ], + sh:name "byteRange" ; + sh:path software:byteRange ], [ sh:class core:PositiveIntegerRange ; sh:maxCount 1 ; - sh:name "byteRange" ; - sh:path software:byteRange ] . + sh:name "lineRange" ; + sh:path software:lineRange ] . a owl:NamedIndividual, software:SoftwareDependencyLinkType . @@ -1738,24 +1730,24 @@ core:Artifact a owl:Class, such as an electronic file, a software package, a device or an element of data.""" ; rdfs:subClassOf core:Element ; ns0:term_status "Stable" ; - sh:property [ sh:class core:Agent ; - sh:name "suppliedBy" ; - sh:path core:suppliedBy ], - [ sh:datatype core:DateTime ; - sh:maxCount 1 ; - sh:name "releaseTime" ; - sh:path core:releaseTime ], - [ sh:datatype core:DateTime ; + sh:property [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "validUntilTime" ; sh:path core:validUntilTime ], [ sh:class core:Agent ; sh:name "originatedBy" ; sh:path core:originatedBy ], + [ sh:class core:Agent ; + sh:name "suppliedBy" ; + sh:path core:suppliedBy ], [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "builtTime" ; sh:path core:builtTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "releaseTime" ; + sh:path core:releaseTime ], [ sh:datatype xsd:string ; sh:name "standard" ; sh:path core:standard ] . @@ -1778,13 +1770,13 @@ core:ElementCollection a owl:Class, sh:property [ sh:class core:ExternalMap ; sh:name "imports" ; sh:path core:imports ], - [ sh:class core:NamespaceMap ; - sh:name "namespaces" ; - sh:path core:namespaces ], [ sh:class core:Element ; sh:minCount 1 ; sh:name "rootElement" ; sh:path core:rootElement ], + [ sh:class core:NamespaceMap ; + sh:name "namespaces" ; + sh:path core:namespaces ], [ sh:class core:Element ; sh:minCount 1 ; sh:name "element" ; @@ -2673,17 +2665,17 @@ core:ExternalIdentifier a owl:Class, that uniquely identifies an Element.""" ; ns0:term_status "Stable" ; sh:property [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "identifier" ; + sh:path core:identifier ], + [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "comment" ; sh:path core:comment ], [ sh:datatype xsd:anyURI ; sh:name "identifierLocator" ; sh:path core:identifierLocator ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "identifier" ; - sh:path core:identifier ], [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:name "issuingAuthority" ; @@ -2699,21 +2691,21 @@ core:ExternalReference a owl:Class, rdfs:comment """An External Reference points to a resource outside the scope of the SPDX-3.0 content that provides additional characteristics of an Element.""" ; ns0:term_status "Stable" ; - sh:property [ sh:datatype core:MediaType ; + sh:property [ sh:class core:ExternalReferenceType ; sh:maxCount 1 ; - sh:name "contentType" ; - sh:path core:contentType ], + sh:name "externalReferenceType" ; + sh:path core:externalReferenceType ], + [ sh:datatype xsd:anyURI ; + sh:name "locator" ; + sh:path core:locator ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "comment" ; sh:path core:comment ], - [ sh:class core:ExternalReferenceType ; + [ sh:datatype core:MediaType ; sh:maxCount 1 ; - sh:name "externalReferenceType" ; - sh:path core:externalReferenceType ], - [ sh:datatype xsd:anyURI ; - sh:name "locator" ; - sh:path core:locator ] . + sh:name "contentType" ; + sh:path core:contentType ] . core:Hash a owl:Class, sh:NodeShape ; @@ -2740,16 +2732,16 @@ core:Payload a owl:Class, sh:NodeShape ; rdfs:comment "TODO" ; ns0:term_status "Stable" ; - sh:property [ sh:class core:ExternalMap ; + sh:property [ sh:class core:NamespaceMap ; + sh:name "namespaces" ; + sh:path core:namespaces ], + [ sh:class core:ExternalMap ; sh:name "imports" ; sh:path core:imports ], [ sh:class core:CreationInfo ; sh:maxCount 1 ; sh:name "creationInfo" ; - sh:path core:creationInfo ], - [ sh:class core:NamespaceMap ; - sh:name "namespaces" ; - sh:path core:namespaces ] . + sh:path core:creationInfo ] . core:Relationship a owl:Class, sh:NodeShape ; @@ -2765,23 +2757,23 @@ that one Element is related to one or more other Elements in some way.""" ; sh:maxCount 1 ; sh:name "startTime" ; sh:path core:startTime ], - [ sh:class core:Element ; - sh:name "to" ; - sh:path core:to ], - [ sh:class core:RelationshipType ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "relationshipType" ; - sh:path core:relationshipType ], [ sh:class core:Element ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "from" ; sh:path core:from ], + [ sh:class core:Element ; + sh:name "to" ; + sh:path core:to ], [ sh:class core:RelationshipCompleteness ; sh:maxCount 1 ; sh:name "completeness" ; - sh:path core:completeness ] . + sh:path core:completeness ], + [ sh:class core:RelationshipType ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "relationshipType" ; + sh:path core:relationshipType ] . core:SemVer a owl:Class, sh:NodeShape ; @@ -2924,14 +2916,14 @@ External property restriction on /Core/Element/name: minCount: 1""" ; sh:maxCount 1 ; sh:name "packageVersion" ; sh:path software:packageVersion ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "sourceInfo" ; - sh:path software:sourceInfo ], [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:name "packageUrl" ; sh:path software:packageUrl ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "sourceInfo" ; + sh:path software:sourceInfo ], [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:name "downloadLocation" ; @@ -2965,11 +2957,7 @@ software:SoftwareArtifact a owl:Class, such as a package, a file, or a snippet.""" ; rdfs:subClassOf core:Artifact ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "copyrightText" ; - sh:path software:copyrightText ], - [ sh:datatype xsd:anyURI ; + sh:property [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:name "contentIdentifier" ; sh:path software:contentIdentifier ], @@ -2981,9 +2969,10 @@ such as a package, a file, or a snippet.""" ; sh:maxCount 1 ; sh:name "declaredLicense" ; sh:path software:declaredLicense ], - [ sh:class software:SoftwarePurpose ; - sh:name "additionalPurpose" ; - sh:path software:additionalPurpose ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "copyrightText" ; + sh:path software:copyrightText ], [ sh:class software:SoftwarePurpose ; sh:maxCount 1 ; sh:name "primaryPurpose" ; @@ -2991,7 +2980,10 @@ such as a package, a file, or a snippet.""" ; [ sh:class licensing:LicenseField ; sh:maxCount 1 ; sh:name "concludedLicense" ; - sh:path software:concludedLicense ] . + sh:path software:concludedLicense ], + [ sh:class software:SoftwarePurpose ; + sh:name "additionalPurpose" ; + sh:path software:additionalPurpose ] . core:AnnotationType a owl:Class ; rdfs:comment "AnnotationType specifies the type of an annotation." ; @@ -3007,26 +2999,26 @@ The dateTime created is often the date of last change (e.g., a git commit date), sh:maxCount 1 ; sh:name "comment" ; sh:path core:comment ], - [ sh:datatype core:SemVer ; - sh:name "specVersion" ; - sh:path core:specVersion ], + [ sh:class core:Tool ; + sh:name "createdUsing" ; + sh:path core:createdUsing ], [ sh:class core:Agent ; sh:minCount 1 ; sh:name "createdBy" ; sh:path core:createdBy ], + [ sh:datatype core:DateTime ; + sh:name "created" ; + sh:path core:created ], + [ sh:datatype core:SemVer ; + sh:name "specVersion" ; + sh:path core:specVersion ], [ sh:class core:ProfileIdentifierType ; sh:minCount 1 ; sh:name "profile" ; sh:path core:profile ], [ sh:datatype xsd:string ; sh:name "dataLicense" ; - sh:path core:dataLicense ], - [ sh:datatype core:DateTime ; - sh:name "created" ; - sh:path core:created ], - [ sh:class core:Tool ; - sh:name "createdUsing" ; - sh:path core:createdUsing ] . + sh:path core:dataLicense ] . core:ExternalMap a owl:Class, sh:NodeShape ; @@ -3035,7 +3027,10 @@ but defined external to that Document. The external map provides details about the externally-defined Element such as its provenance, where to retrieve it, and how to verify its integrity.""" ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:anyURI ; + sh:property [ sh:class core:IntegrityMethod ; + sh:name "verifiedUsing" ; + sh:path core:verifiedUsing ], + [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:name "locationHint" ; sh:path core:locationHint ], @@ -3047,10 +3042,7 @@ such as its provenance, where to retrieve it, and how to verify its integrity."" sh:maxCount 1 ; sh:minCount 1 ; sh:name "externalId" ; - sh:path core:externalId ], - [ sh:class core:IntegrityMethod ; - sh:name "verifiedUsing" ; - sh:path core:verifiedUsing ] . + sh:path core:externalId ] . core:IntegrityMethod a owl:Class, sh:NodeShape ; @@ -3070,16 +3062,16 @@ core:NamespaceMap a owl:Class, shorter identifiers ("prefixes") instead of URIs to provide a more human-readable and smaller serialized representation of the Elements.""" ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:anyURI ; + sh:property [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "namespace" ; - sh:path core:namespace ], - [ sh:datatype xsd:string ; + sh:name "prefix" ; + sh:path core:prefix ], + [ sh:datatype xsd:anyURI ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "prefix" ; - sh:path core:prefix ] . + sh:name "namespace" ; + sh:path core:namespace ] . core:PositiveIntegerRange a owl:Class, sh:NodeShape ; @@ -3089,13 +3081,13 @@ core:PositiveIntegerRange a owl:Class, sh:property [ sh:datatype xsd:positiveInteger ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "end" ; - sh:path core:end ], + sh:name "begin" ; + sh:path core:begin ], [ sh:datatype xsd:positiveInteger ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "begin" ; - sh:path core:begin ] . + sh:name "end" ; + sh:path core:end ] . licensing:LicenseAddition a owl:Class, sh:NodeShape ; @@ -3107,40 +3099,40 @@ It may be an exception which is listed on the SPDX Exceptions List (ListedLicenseException), or may be any other additional text (as an exception or otherwise) which is defined by an SPDX data creator (CustomLicenseAddition).""" ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:anyURI ; - sh:name "seeAlso" ; - sh:path licensing:seeAlso ], - [ sh:datatype xsd:boolean ; + sh:property [ sh:datatype xsd:boolean ; sh:maxCount 1 ; sh:name "isDeprecatedAdditionId" ; sh:path licensing:isDeprecatedAdditionId ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "additionName" ; - sh:path licensing:additionName ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "additionComment" ; - sh:path licensing:additionComment ], + sh:name "additionText" ; + sh:path licensing:additionText ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:minCount 1 ; sh:name "additionId" ; sh:path licensing:additionId ], + [ sh:datatype xsd:anyURI ; + sh:name "seeAlso" ; + sh:path licensing:seeAlso ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "obsoletedBy" ; sh:path licensing:obsoletedBy ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "standardAdditionTemplate" ; + sh:path licensing:standardAdditionTemplate ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:minCount 1 ; - sh:name "additionText" ; - sh:path licensing:additionText ], + sh:name "additionName" ; + sh:path licensing:additionName ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "standardAdditionTemplate" ; - sh:path licensing:standardAdditionTemplate ] . + sh:name "additionComment" ; + sh:path licensing:additionComment ] . security:ExploitCatalogType a owl:Class ; rdfs:comment "ExploitCatalogType specifies the type of exploit catalog that a vulnerability is listed in." ; @@ -3205,34 +3197,31 @@ licensing:License a owl:Class, (ListedLicense) or defined by an SPDX data creator (CustomLicense).""" ; rdfs:subClassOf licensing:AnyLicenseInfo ; ns0:term_status "Stable" ; - sh:property [ sh:datatype xsd:boolean ; + sh:property [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "isOsiApproved" ; - sh:path licensing:isOsiApproved ], - [ sh:datatype xsd:anyURI ; - sh:name "seeAlso" ; - sh:path licensing:seeAlso ], + sh:name "obsoletedBy" ; + sh:path licensing:obsoletedBy ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "licenseComment" ; - sh:path licensing:licenseComment ], + sh:name "standardLicenseTemplate" ; + sh:path licensing:standardLicenseTemplate ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:name "licenseText" ; + sh:path licensing:licenseText ], [ sh:datatype xsd:boolean ; sh:maxCount 1 ; sh:name "isDeprecatedLicenseId" ; sh:path licensing:isDeprecatedLicenseId ], + [ sh:datatype xsd:boolean ; + sh:maxCount 1 ; + sh:name "isFsfLibre" ; + sh:path licensing:isFsfLibre ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "standardLicenseHeader" ; sh:path licensing:standardLicenseHeader ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:minCount 1 ; - sh:name "licenseText" ; - sh:path licensing:licenseText ], - [ sh:datatype xsd:string ; - sh:maxCount 1 ; - sh:name "obsoletedBy" ; - sh:path licensing:obsoletedBy ], [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:minCount 1 ; @@ -3245,12 +3234,15 @@ licensing:License a owl:Class, sh:path licensing:licenseName ], [ sh:datatype xsd:boolean ; sh:maxCount 1 ; - sh:name "isFsfLibre" ; - sh:path licensing:isFsfLibre ], + sh:name "isOsiApproved" ; + sh:path licensing:isOsiApproved ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "standardLicenseTemplate" ; - sh:path licensing:standardLicenseTemplate ] . + sh:name "licenseComment" ; + sh:path licensing:licenseComment ], + [ sh:datatype xsd:anyURI ; + sh:name "seeAlso" ; + sh:path licensing:seeAlso ] . ai:SafetyRiskAssessmentType a owl:Class ; rdfs:comment """Lists the different safety risk type values that can be used to describe the safety risk of AI software @@ -3273,17 +3265,9 @@ External property restriction on /Core/Relationship/to: minCount: 1""" ; rdfs:subClassOf core:Relationship ; ns0:term_status "Stable" ; sh:property [ sh:datatype core:DateTime ; - sh:maxCount 1 ; - sh:name "publishedTime" ; - sh:path security:publishedTime ], - [ sh:datatype core:DateTime ; sh:maxCount 1 ; sh:name "withdrawnTime" ; sh:path security:withdrawnTime ], - [ sh:datatype core:DateTime ; - sh:maxCount 1 ; - sh:name "modifiedTime" ; - sh:path security:modifiedTime ], [ sh:class core:Element ; sh:maxCount 1 ; sh:name "assessedElement" ; @@ -3291,7 +3275,15 @@ External property restriction on /Core/Relationship/to: minCount: 1""" ; [ sh:class core:Agent ; sh:maxCount 1 ; sh:name "suppliedBy" ; - sh:path security:suppliedBy ] . + sh:path security:suppliedBy ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "publishedTime" ; + sh:path security:publishedTime ], + [ sh:datatype core:DateTime ; + sh:maxCount 1 ; + sh:name "modifiedTime" ; + sh:path security:modifiedTime ] . software:SoftwareDependencyLinkType a owl:Class ; rdfs:comment "TODO" ; @@ -3380,13 +3372,14 @@ unifying, and interoperable foundation for all explicit and inter-relatable content objects.""" ; rdfs:subClassOf core:Payload ; ns0:term_status "Stable" ; - sh:property [ sh:class core:IntegrityMethod ; - sh:name "verifiedUsing" ; - sh:path core:verifiedUsing ], - [ sh:datatype xsd:string ; + sh:property [ sh:datatype xsd:string ; sh:maxCount 1 ; sh:name "summary" ; sh:path core:summary ], + [ sh:datatype xsd:string ; + sh:maxCount 1 ; + sh:name "description" ; + sh:path core:description ], [ sh:datatype core:Extension ; sh:name "extension" ; sh:path core:extension ], @@ -3395,23 +3388,22 @@ and inter-relatable content objects.""" ; sh:path core:externalIdentifier ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "comment" ; - sh:path core:comment ], - [ sh:class core:CreationInfo ; - sh:maxCount 1 ; - sh:name "creationInfo" ; - sh:path core:creationInfo ], + sh:name "name" ; + sh:path core:name ], [ sh:class core:ExternalReference ; sh:name "externalReference" ; sh:path core:externalReference ], - [ sh:datatype xsd:string ; + [ sh:class core:IntegrityMethod ; + sh:name "verifiedUsing" ; + sh:path core:verifiedUsing ], + [ sh:class core:CreationInfo ; sh:maxCount 1 ; - sh:name "name" ; - sh:path core:name ], + sh:name "creationInfo" ; + sh:path core:creationInfo ], [ sh:datatype xsd:string ; sh:maxCount 1 ; - sh:name "description" ; - sh:path core:description ] . + sh:name "comment" ; + sh:path core:comment ] . core:ExternalReferenceType a owl:Class ; rdfs:comment "ExteralReferenceType specifies the type of an external reference." ; From d37f8ae6d6920ca170dc4dcce141490ee8870e18 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 30 May 2023 09:29:07 +0200 Subject: [PATCH 257/354] If in doubt, prefer core properties in jsonld context Signed-off-by: Holger Frydrych --- src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py | 3 +-- src/spdx_tools/spdx3/writer/json_ld/context.json | 4 ++-- src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py | 5 +++++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py index f1f1b77ae..07613bb6b 100644 --- a/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py +++ b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py @@ -3,9 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from typing import Optional -import owlrl from pyshacl import validate -from rdflib import Graph, RDF +from rdflib import Graph def validate_against_shacl_from_file( diff --git a/src/spdx_tools/spdx3/writer/json_ld/context.json b/src/spdx_tools/spdx3/writer/json_ld/context.json index fe165c445..94cb2b5e6 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/context.json +++ b/src/spdx_tools/spdx3/writer/json_ld/context.json @@ -274,7 +274,7 @@ "@type": "xsd:anyURI" }, "locator": { - "@id": "security:locator", + "@id": "core:locator", "@type": "xsd:anyURI" }, "namespace": { @@ -351,7 +351,7 @@ "@type": "xsd:string" }, "suppliedBy": { - "@id": "security:suppliedBy", + "@id": "core:suppliedBy", "@type": "@id" }, "to": { diff --git a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py index 2a55b62d8..2d8fe6e7c 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py +++ b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py @@ -62,6 +62,11 @@ def convert_spdx_owl_to_jsonld_context(spdx_owl: str = "SPDX_OWL.json"): elif node_type in ["owl:DatatypeProperty", "owl:ObjectProperty"]: name = node["@id"].split(":")[-1] type_id = node["rdfs:range"]["@id"] + + if name in context_dict and context_dict[name]["@id"].startswith('core'): + # if in doubt, prioritize core properties + continue + if name in PROPERTIES_WITH_ENUM_RANGE: if name == "profile": # FIXME: since the allowed values for the profile enum collide with From c76a09892b9a1314db8128c569e8829c335acf54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 31 May 2023 15:54:09 +0200 Subject: [PATCH 258/354] fix tests and formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../spdx3/bump_from_spdx2/snippet.py | 2 +- .../spdx3/writer/json_ld/owl_to_context.py | 2 +- tests/spdx3/bump/test_file_bump.py | 2 +- .../bump/test_license_expression_bump.py | 13 +++++++------ tests/spdx3/bump/test_package_bump.py | 4 ++-- tests/spdx3/bump/test_relationship_bump.py | 19 +++++++++++-------- tests/spdx3/bump/test_snippet_bump.py | 2 +- tests/spdx3/model/software/test_snippet.py | 9 +++++---- .../writer/json_ld/test_json_ld_writer.py | 3 ++- 9 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index af7f48d17..221c96926 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Tuple, Optional +from typing import List, Optional, Tuple from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion diff --git a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py index 2d8fe6e7c..f6bc7c35a 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py +++ b/src/spdx_tools/spdx3/writer/json_ld/owl_to_context.py @@ -63,7 +63,7 @@ def convert_spdx_owl_to_jsonld_context(spdx_owl: str = "SPDX_OWL.json"): name = node["@id"].split(":")[-1] type_id = node["rdfs:range"]["@id"] - if name in context_dict and context_dict[name]["@id"].startswith('core'): + if name in context_dict and context_dict[name]["@id"].startswith("core"): # if in doubt, prioritize core properties continue diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index a21487f52..ca7dafa5c 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -27,7 +27,7 @@ def test_bump_file(creation_info): assert file.spdx_id == expected_new_file_id assert file.verified_using == [integrity_method] assert file.concluded_license == ConjunctiveLicenseSet( - [ListedLicense("MIT", "MIT", ""), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "")] + [ListedLicense("MIT", "MIT", "blank"), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "blank")] ) assert file.copyright_text == spdx2_file.copyright_text assert file.attribution_text == spdx2_file.attribution_texts[0] diff --git a/tests/spdx3/bump/test_license_expression_bump.py b/tests/spdx3/bump/test_license_expression_bump.py index 3e6fbcc6f..6f3b8aa20 100644 --- a/tests/spdx3/bump/test_license_expression_bump.py +++ b/tests/spdx3/bump/test_license_expression_bump.py @@ -40,8 +40,8 @@ def test_license_expression_or_none_or_no_assertion(element, expected_class): @pytest.mark.parametrize( "license_expression, extracted_licensing_info, expected_element", [ - (get_spdx_licensing().parse("MIT"), [], ListedLicense("MIT", "MIT", "")), - (get_spdx_licensing().parse("LGPL-2.0"), [], ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "")), + (get_spdx_licensing().parse("MIT"), [], ListedLicense("MIT", "MIT", "blank")), + (get_spdx_licensing().parse("LGPL-2.0"), [], ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "blank")), ( get_spdx_licensing().parse("LicenseRef-1"), [extracted_licensing_info_fixture()], @@ -51,7 +51,7 @@ def test_license_expression_or_none_or_no_assertion(element, expected_class): get_spdx_licensing().parse("MIT AND LGPL-2.0"), [], ConjunctiveLicenseSet( - [ListedLicense("MIT", "MIT", ""), ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "")] + [ListedLicense("MIT", "MIT", "blank"), ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "blank")] ), ), ( @@ -60,7 +60,7 @@ def test_license_expression_or_none_or_no_assertion(element, expected_class): DisjunctiveLicenseSet( [ CustomLicense("LicenseRef-1", "licenseName", "extractedText"), - ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", ""), + ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "blank"), ] ), ), @@ -68,7 +68,8 @@ def test_license_expression_or_none_or_no_assertion(element, expected_class): get_spdx_licensing().parse("LGPL-2.0 WITH 389-exception"), [], WithAdditionOperator( - ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", ""), ListedLicenseException("389-exception", "", "") + ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "blank"), + ListedLicenseException("389-exception", "", ""), ), ), ( @@ -90,7 +91,7 @@ def test_license_expression_or_none_or_no_assertion(element, expected_class): ], ConjunctiveLicenseSet( [ - ListedLicense("MIT", "MIT", ""), + ListedLicense("MIT", "MIT", "blank"), WithAdditionOperator( CustomLicense("LicenseRef-1", "licenseName", "extractedText"), CustomLicenseAddition("custom-exception", "exceptionName", "This is a custom exception"), diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 8b17598fa..e0ccfe7c3 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -69,10 +69,10 @@ def test_bump_package(creation_info, originator, expected_originator, supplier, assert package.copyright_text == spdx2_package.copyright_text assert package.attribution_text == spdx2_package.attribution_texts[0] assert package.concluded_license == ConjunctiveLicenseSet( - [ListedLicense("MIT", "MIT", ""), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "")] + [ListedLicense("MIT", "MIT", "blank"), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "blank")] ) assert package.declared_license == ConjunctiveLicenseSet( - [ListedLicense("MIT", "MIT", ""), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "")] + [ListedLicense("MIT", "MIT", "blank"), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "blank")] ) diff --git a/tests/spdx3/bump/test_relationship_bump.py b/tests/spdx3/bump/test_relationship_bump.py index 15f82415d..e865a22c2 100644 --- a/tests/spdx3/bump/test_relationship_bump.py +++ b/tests/spdx3/bump/test_relationship_bump.py @@ -19,9 +19,9 @@ def test_relationship_bump(creation_info): assert relationship == Relationship( f"{document_namespace}#SPDXRef-Relationship-1", - spdx2_relationship.spdx_element_id, + f"{document_namespace}#{spdx2_relationship.spdx_element_id}", RelationshipType.DESCRIBES, - [spdx2_relationship.related_spdx_element_id], + [f"{document_namespace}#{spdx2_relationship.related_spdx_element_id}"], creation_info=creation_info, comment=spdx2_relationship.comment, ) @@ -39,9 +39,12 @@ def test_relationships_bump(creation_info): assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-1") == Relationship( f"{document_namespace}#SPDXRef-Relationship-1", - relationships[0].spdx_element_id, + f"{document_namespace}#{relationships[0].spdx_element_id}", RelationshipType.DESCRIBES, - [relationships[0].related_spdx_element_id, relationships[1].related_spdx_element_id], + [ + f"{document_namespace}#{relationships[0].related_spdx_element_id}", + f"{document_namespace}#{relationships[1].related_spdx_element_id}", + ], creation_info=creation_info, ) @@ -63,7 +66,7 @@ def test_relationships_bump_with_setting_completeness(creation_info): assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-0") == Relationship( f"{document_namespace}#SPDXRef-Relationship-0", - relationships[0].spdx_element_id, + f"{document_namespace}#{relationships[0].spdx_element_id}", RelationshipType.DESCRIBES, [], creation_info=creation_info, @@ -72,15 +75,15 @@ def test_relationships_bump_with_setting_completeness(creation_info): ) assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-1") == Relationship( f"{document_namespace}#SPDXRef-Relationship-1", - relationships[1].spdx_element_id, + f"{document_namespace}#{relationships[1].spdx_element_id}", RelationshipType.DESCRIBES, - [relationships[1].related_spdx_element_id], + [f"{document_namespace}#{relationships[1].related_spdx_element_id}"], creation_info=creation_info, comment=relationships[1].comment, ) assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-2") == Relationship( f"{document_namespace}#SPDXRef-Relationship-2", - relationships[2].spdx_element_id, + f"{document_namespace}#{relationships[2].spdx_element_id}", RelationshipType.SPECIFICATION_FOR, [], creation_info=creation_info, diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index da0dd265f..6ee2c4237 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -26,5 +26,5 @@ def test_bump_snippet(creation_info): assert snippet.copyright_text == spdx2_snippet.copyright_text assert snippet.attribution_text == spdx2_snippet.attribution_texts[0] assert snippet.concluded_license == ConjunctiveLicenseSet( - [ListedLicense("MIT", "MIT", ""), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "")] + [ListedLicense("MIT", "MIT", "blank"), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "blank")] ) diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index 042493562..ccad95950 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -5,6 +5,7 @@ import pytest +from spdx_tools.spdx3.model.positive_integer_range import PositiveIntegerRange from spdx_tools.spdx3.model.software import Snippet, SoftwarePurpose @@ -15,16 +16,16 @@ def test_correct_initialization(creation_info): creation_info=creation_info, content_identifier="https://content.identifier", purpose=[SoftwarePurpose.SOURCE], - byte_range=(3, 4), - line_range=(346, 456), + byte_range=PositiveIntegerRange(3, 4), + line_range=PositiveIntegerRange(346, 456), ) assert snippet.spdx_id == "SPDXRef-Snippet" assert snippet.creation_info == creation_info assert snippet.content_identifier == "https://content.identifier" assert snippet.purpose == [SoftwarePurpose.SOURCE] - assert snippet.byte_range == (3, 4) - assert snippet.line_range == (346, 456) + assert snippet.byte_range == PositiveIntegerRange(3, 4) + assert snippet.line_range == PositiveIntegerRange(346, 456) @mock.patch("spdx_tools.spdx3.model.software.Snippet", autospec=True) diff --git a/tests/spdx3/writer/json_ld/test_json_ld_writer.py b/tests/spdx3/writer/json_ld/test_json_ld_writer.py index 1670844db..f46469b1f 100644 --- a/tests/spdx3/writer/json_ld/test_json_ld_writer.py +++ b/tests/spdx3/writer/json_ld/test_json_ld_writer.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +import os from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document from spdx_tools.spdx3.payload import Payload @@ -14,4 +15,4 @@ def test_json_writer(): payload: Payload = bump_spdx_document(spdx2_document) # this currently generates an actual file to look at, this should be changed to a temp file later - write_payload(payload, "../../../SPDX3_jsonld_test") + write_payload(payload, os.path.join(os.path.dirname(__file__), "../../../SPDX3_jsonld_test")) From 6771cad5a463347b207a5cb0003cf04e67c9266c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 31 May 2023 16:25:05 +0200 Subject: [PATCH 259/354] add spdx2 document comment to spdx3 document instead of creation info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py index 106c92169..30532b463 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py @@ -33,7 +33,6 @@ def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload 0, "part of licensing profile, " "https://github.com/spdx/spdx-3-model/issues/131", ) - document_comment = spdx2_creation_info.document_comment creation_info = CreationInfo( spec_version=Version("3.0.0"), created=spdx2_creation_info.created, @@ -41,7 +40,6 @@ def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload created_using=[], profile=[ProfileIdentifier.CORE, ProfileIdentifier.SOFTWARE, ProfileIdentifier.LICENSING], data_license=spdx2_creation_info.data_license, - comment=spdx2_creation_info.document_comment, ) # due to creators having a creation_info themselves which inherits from the document's one, @@ -71,7 +69,7 @@ def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload spdx_id=spdx_id, creation_info=creation_info, name=spdx2_creation_info.name, - comment=document_comment, + comment=spdx2_creation_info.document_comment, element=[], root_element=[spdx_id], imports=imports, From 453af7ffa5e70b5129f4d760a574ac9405a7a212 Mon Sep 17 00:00:00 2001 From: HarshvMahawar Date: Thu, 1 Jun 2023 11:45:46 +0530 Subject: [PATCH 260/354] Add fixture dict. for ai_package profile Signed-off-by: HarshvMahawar --- tests/spdx3/fixtures.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 1817e444b..29a2d6e5b 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -33,6 +33,7 @@ SpdxDocument, Tool, ) +from spdx_tools.spdx3.model.ai.ai_package import AIPackage, SafetyRiskAssessmentType from spdx_tools.spdx3.model.dataset.dataset import ConfidentialityLevelType, Dataset, DatasetAvailabilityType from spdx_tools.spdx3.model.licensing import ( CustomLicense, @@ -316,6 +317,24 @@ def namespace_map_fixture( "relationship_type": RelationshipType.FIXED_IN, } +AIPACKAGE_DICT = { + "energy_consumption": "energyConsumption", + "standard_compliance": ["standardCompliance"], + "limitation": "aIPackageLimitation", + "type_of_model": ["typeOfModel"], + "information_about_training": "informationAboutTraining", + "information_about_application": "informationAboutApplication", + "hyperparameter": {"aIPackageHypParaKey": "aIPackageHypParaValue"}, + "model_data_preprocessing": ["aImodelDataPreprocessing"], + "model_explainability": ["aImodelExplainability"], + "sensitive_personal_information": True, + "metric_decision_threshold": {"metricDecisionThresholdKey": "metricDecisionThresholdValue"}, + "metric": {"aIMetricKey": "aIMetricValue"}, + "domain": ["aIDomain"], + "autonomy_type": True, + "safety_risk_assessment": SafetyRiskAssessmentType.LOW, +} + ARTIFACT_DICT = { "originated_by": ["https://spdx.test/tools-python/originatedBy"], "supplied_by": ["https://spdx.test/tools-python/suppliedBy"], @@ -443,6 +462,7 @@ def namespace_map_fixture( VEX_UNDER_INVESTIGATION_VULN_ASSESSMENT_RELATIONSHIP_DICT, ], Vulnerability: [ELEMENT_DICT, VULNERABILITY_DICT], + AIPackage: [AIPACKAGE_DICT, PACKAGE_DICT, ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT], File: [ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT, FILE_DICT], Package: [ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT, PACKAGE_DICT], Snippet: [ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT, SNIPPET_DICT], From 913e45b3205de0e7f8a53a00df00b7b0983c8f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 1 Jun 2023 08:39:26 +0200 Subject: [PATCH 261/354] [issue-680] debug writer: account for creation info being optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/writer/console/element_writer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx3/writer/console/element_writer.py b/src/spdx_tools/spdx3/writer/console/element_writer.py index 239b87174..c790de6bd 100644 --- a/src/spdx_tools/spdx3/writer/console/element_writer.py +++ b/src/spdx_tools/spdx3/writer/console/element_writer.py @@ -15,7 +15,8 @@ def write_element_properties(element: Element, text_output: TextIO): write_value("SPDXID", element.spdx_id, text_output) write_value("name", element.name, text_output) - write_creation_info(element.creation_info, text_output, True) + if element.creation_info: + write_creation_info(element.creation_info, text_output, True) write_value("summary", element.summary, text_output) write_value("description", element.description, text_output) write_value("comment", element.comment, text_output) From a193df1d534febd2ad667cae100ad512b86cdedb Mon Sep 17 00:00:00 2001 From: William Armiros <54150514+willarmiros@users.noreply.github.com> Date: Thu, 1 Jun 2023 09:29:42 -0700 Subject: [PATCH 262/354] fix dataset sensor property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: William Armiros Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/model/dataset/dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py index 8080a8dfe..e6da96eb5 100644 --- a/src/spdx_tools/spdx3/model/dataset/dataset.py +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -94,7 +94,7 @@ def __init__( supplied_by = [] if supplied_by is None else supplied_by standard = [] if standard is None else standard data_preprocessing = [] if data_preprocessing is None else data_preprocessing - sensors = {} if sensor is None else sensor + sensor = {} if sensor is None else sensor known_bias = [] if known_bias is None else known_bias anonymization_method_used = [] if anonymization_method_used is None else anonymization_method_used check_types_and_set_values(self, locals()) From 2ca0eb7d93d05321a9eea941c76b69dd59643050 Mon Sep 17 00:00:00 2001 From: William Armiros Date: Thu, 1 Jun 2023 10:46:51 -0700 Subject: [PATCH 263/354] corrected dataset header in writer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: William Armiros Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py b/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py index 9871d251d..363ef71fb 100644 --- a/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py +++ b/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py @@ -9,7 +9,7 @@ def write_dataset(dataset: Dataset, text_output: TextIO): - text_output.write("## AI Package\n") + text_output.write("## Dataset\n") write_package(dataset, text_output, False) for property_name in Dataset.__annotations__.keys(): From 6acf1f0ab0e7f6923c71dee37a7f509ed9504ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 5 Jun 2023 11:01:11 +0200 Subject: [PATCH 264/354] [issue-673] adapt tests after replacing typeguard with beartype in SPDX3 prototype MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx3/__init__.py | 0 tests/spdx3/bump/__init__.py | 0 tests/spdx3/bump/test_package_bump.py | 23 ++++++++++------------ tests/spdx3/model/ai/test_ai_package.py | 22 --------------------- tests/spdx3/model/dataset/test_dataset.py | 23 ---------------------- tests/spdx3/model/software/test_snippet.py | 5 ++--- 6 files changed, 12 insertions(+), 61 deletions(-) create mode 100644 tests/spdx3/__init__.py create mode 100644 tests/spdx3/bump/__init__.py diff --git a/tests/spdx3/__init__.py b/tests/spdx3/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/bump/__init__.py b/tests/spdx3/bump/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index e0ccfe7c3..e199b2995 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from unittest import TestCase, mock +from unittest import TestCase import pytest @@ -13,6 +13,7 @@ from spdx_tools.spdx.model import SpdxNoAssertion from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory from spdx_tools.spdx.model.package import Package as Spdx2_Package +from tests.spdx3.fixtures import creation_info_fixture from tests.spdx.fixtures import actor_fixture, package_fixture @@ -29,8 +30,7 @@ (SpdxNoAssertion(), [], SpdxNoAssertion(), []), ], ) -@mock.patch("spdx_tools.spdx3.model.CreationInfo") -def test_bump_package(creation_info, originator, expected_originator, supplier, expected_supplier): +def test_bump_package(originator, expected_originator, supplier, expected_supplier): payload = Payload() document_namespace = "https://doc.namespace" spdx2_package: Spdx2_Package = package_fixture( @@ -45,7 +45,7 @@ def test_bump_package(creation_info, originator, expected_originator, supplier, ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_info, document_namespace, [], [], []) + bump_package(spdx2_package, payload, creation_info_fixture(), document_namespace, [], [], []) package = payload.get_element(expected_new_package_id) assert isinstance(package, Package) @@ -76,8 +76,7 @@ def test_bump_package(creation_info, originator, expected_originator, supplier, ) -@mock.patch("spdx_tools.spdx3.model.CreationInfo") -def test_bump_of_single_purl_without_comment(creation_info): +def test_bump_of_single_purl_without_comment(): payload = Payload() document_namespace = "https://doc.namespace" spdx2_package: Spdx2_Package = package_fixture( @@ -87,7 +86,7 @@ def test_bump_of_single_purl_without_comment(creation_info): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_info, document_namespace, [], [], []) + bump_package(spdx2_package, payload, creation_info_fixture(), document_namespace, [], [], []) package = payload.get_element(expected_new_package_id) assert package.package_url == "purl_locator" @@ -95,8 +94,7 @@ def test_bump_of_single_purl_without_comment(creation_info): assert package.external_identifier == [] -@mock.patch("spdx_tools.spdx3.model.CreationInfo") -def test_bump_of_single_purl_with_comment(creation_info): +def test_bump_of_single_purl_with_comment(): payload = Payload() document_namespace = "https://doc.namespace" spdx2_package: Spdx2_Package = package_fixture( @@ -106,7 +104,7 @@ def test_bump_of_single_purl_with_comment(creation_info): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_info, document_namespace, [], [], []) + bump_package(spdx2_package, payload, creation_info_fixture(), document_namespace, [], [], []) package = payload.get_element(expected_new_package_id) assert package.package_url is None @@ -116,8 +114,7 @@ def test_bump_of_single_purl_with_comment(creation_info): ] -@mock.patch("spdx_tools.spdx3.model.CreationInfo") -def test_bump_of_multiple_purls(creation_info): +def test_bump_of_multiple_purls(): payload = Payload() document_namespace = "https://doc.namespace" spdx2_package: Spdx2_Package = package_fixture( @@ -128,7 +125,7 @@ def test_bump_of_multiple_purls(creation_info): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_info, document_namespace, [], [], []) + bump_package(spdx2_package, payload, creation_info_fixture(), document_namespace, [], [], []) package = payload.get_element(expected_new_package_id) assert package.package_url is None diff --git a/tests/spdx3/model/ai/test_ai_package.py b/tests/spdx3/model/ai/test_ai_package.py index 52b2bf8ce..0990d5056 100644 --- a/tests/spdx3/model/ai/test_ai_package.py +++ b/tests/spdx3/model/ai/test_ai_package.py @@ -4,8 +4,6 @@ from datetime import datetime from unittest import mock -import pytest - from spdx_tools.spdx3.model.ai import AIPackage from spdx_tools.spdx3.model.ai.ai_package import SafetyRiskAssessmentType from spdx_tools.spdx3.model.software import SoftwarePurpose @@ -59,23 +57,3 @@ def test_correct_initialization(creation_info): assert ai_package.domain == ["domain"] assert ai_package.autonomy_type assert ai_package.safety_risk_assessment == SafetyRiskAssessmentType.HIGH - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_invalid_initialization(creation_info): - with pytest.raises(TypeError) as err: - AIPackage( - "some_spdx_id", - "AI Package name", - ["https://namespace.test#supplier"], - "https://download.test", - "1.2:rc2", - [SoftwarePurpose.SOURCE], - datetime(12, 5, 23, 11), - creation_info, - metric={"metric1": "value", "metric2": 250}, - ) - - assert len(err.value.args[0]) == 1 - for error in err.value.args[0]: - assert error.startswith("SetterError AIPackage:") diff --git a/tests/spdx3/model/dataset/test_dataset.py b/tests/spdx3/model/dataset/test_dataset.py index 47ccc9e20..46a9002da 100644 --- a/tests/spdx3/model/dataset/test_dataset.py +++ b/tests/spdx3/model/dataset/test_dataset.py @@ -4,8 +4,6 @@ from datetime import datetime from unittest import mock -import pytest - from spdx_tools.spdx3.model.dataset import ConfidentialityLevelType, Dataset, DatasetAvailabilityType from spdx_tools.spdx3.model.software import SoftwarePurpose @@ -54,24 +52,3 @@ def test_correct_initialization(creation_info): assert dataset.confidentiality_level == ConfidentialityLevelType.RED assert dataset.dataset_update_mechanism == "update mechanism" assert dataset.dataset_availability == DatasetAvailabilityType.QUERY - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_invalid_initialization(creation_info): - with pytest.raises(TypeError) as err: - Dataset( - "some_spdx_id", - "Dataset name", - ["https://namespace.test#originator"], - "https://download.test", - [SoftwarePurpose.DATA], - datetime(10, 5, 23, 11), - datetime(11, 5, 24, 12), - "training data", - creation_info=creation_info, - sensor={"sensor1": "value", "sensor2": 250}, - ) - - assert len(err.value.args[0]) == 1 - for error in err.value.args[0]: - assert error.startswith("SetterError Dataset:") diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py index ccad95950..6aa6e4c1b 100644 --- a/tests/spdx3/model/software/test_snippet.py +++ b/tests/spdx3/model/software/test_snippet.py @@ -9,7 +9,7 @@ from spdx_tools.spdx3.model.software import Snippet, SoftwarePurpose -@mock.patch("spdx_tools.spdx3.model.software.Snippet", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) def test_correct_initialization(creation_info): snippet = Snippet( "SPDXRef-Snippet", @@ -21,14 +21,13 @@ def test_correct_initialization(creation_info): ) assert snippet.spdx_id == "SPDXRef-Snippet" - assert snippet.creation_info == creation_info assert snippet.content_identifier == "https://content.identifier" assert snippet.purpose == [SoftwarePurpose.SOURCE] assert snippet.byte_range == PositiveIntegerRange(3, 4) assert snippet.line_range == PositiveIntegerRange(346, 456) -@mock.patch("spdx_tools.spdx3.model.software.Snippet", autospec=True) +@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) def test_invalid_initialization(creation_info): with pytest.raises(TypeError) as err: Snippet(2, creation_info=creation_info, originated_by=34, byte_range="34:45") From 33278db34cc11b7bcb3e71db93e6ca2f08094f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 5 Jun 2023 11:48:57 +0200 Subject: [PATCH 265/354] [issue-432] use software fixtures in tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx3/fixtures.py | 44 ++++++++++-- tests/spdx3/model/software/__init__.py | 0 tests/spdx3/model/software/test_file.py | 45 ------------ tests/spdx3/model/software/test_package.py | 70 ------------------- tests/spdx3/model/software/test_sbom.py | 34 --------- tests/spdx3/model/software/test_snippet.py | 37 ---------- .../test_software_dependency_relationship.py | 59 ---------------- .../test_element_and_licensing_subclasses.py | 6 ++ 8 files changed, 44 insertions(+), 251 deletions(-) delete mode 100644 tests/spdx3/model/software/__init__.py delete mode 100644 tests/spdx3/model/software/test_file.py delete mode 100644 tests/spdx3/model/software/test_package.py delete mode 100644 tests/spdx3/model/software/test_sbom.py delete mode 100644 tests/spdx3/model/software/test_snippet.py delete mode 100644 tests/spdx3/model/software/test_software_dependency_relationship.py diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 29a2d6e5b..9ed15f275 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -38,10 +38,10 @@ from spdx_tools.spdx3.model.licensing import ( CustomLicense, CustomLicenseAddition, - LicenseField, ListedLicense, ListedLicenseException, ) +from spdx_tools.spdx3.model.positive_integer_range import PositiveIntegerRange from spdx_tools.spdx3.model.security import ( CvssV2VulnAssessmentRelationship, CvssV3VulnAssessmentRelationship, @@ -164,6 +164,39 @@ def namespace_map_fixture( return NamespaceMap(prefix=prefix, namespace=namespace) +def listed_license_fixture( + license_id="https://spdx.test/tools-python/license_id", + license_name="license name", + license_text="license text", + license_comment="license comment", + see_also=None, + is_osi_approved=True, + is_fsf_libre=True, + standard_license_header="license header", + standard_license_template="license template", + is_deprecated_license_id=True, + obsoleted_by="https://spdx.test/tools-python/obsoleted_by_license_id", + list_version_added="2.1", + deprecated_version="2.2", +): + see_also = ["https://see.also/license"] if see_also is None else see_also + return ListedLicense( + license_id=license_id, + license_name=license_name, + license_text=license_text, + license_comment=license_comment, + see_also=see_also, + is_osi_approved=is_osi_approved, + is_fsf_libre=is_fsf_libre, + standard_license_header=standard_license_header, + standard_license_template=standard_license_template, + is_deprecated_license_id=is_deprecated_license_id, + obsoleted_by=obsoleted_by, + list_version_added=list_version_added, + deprecated_version=deprecated_version, + ) + + ELEMENT_DICT = { "spdx_id": "https://spdx.test/tools-python/element_fixture", "creation_info": creation_info_fixture(), @@ -346,9 +379,9 @@ def namespace_map_fixture( SOFTWARE_ARTIFACT_DICT = { "content_identifier": "https://spdx.test/tools-python/contentIdentifier", - "purpose": SoftwarePurpose.OTHER, - "concluded_license": LicenseField, - "declared_license": LicenseField, + "purpose": [SoftwarePurpose.OTHER], + "concluded_license": listed_license_fixture(), + "declared_license": listed_license_fixture(), "copyright_text": "copyrightText", "attribution_text": "attributionText", } @@ -363,7 +396,7 @@ def namespace_map_fixture( "source_info": "sourceInfo", } -SNIPPET_DICT = {"byte_range": (1024, 2048), "line_range": (1, 4)} +SNIPPET_DICT = {"byte_range": PositiveIntegerRange(1024, 2048), "line_range": PositiveIntegerRange(1, 4)} SOFTWARE_DEPENDENCY_RELATIONSHIP_DICT = { "software_linkage": SoftwareDependencyLinkType.OTHER, @@ -385,7 +418,6 @@ def namespace_map_fixture( "dataset_availability": DatasetAvailabilityType.QUERY, } - FIXTURE_DICTS = { Agent: [ELEMENT_DICT], Person: [ELEMENT_DICT], diff --git a/tests/spdx3/model/software/__init__.py b/tests/spdx3/model/software/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/spdx3/model/software/test_file.py b/tests/spdx3/model/software/test_file.py deleted file mode 100644 index c74861e75..000000000 --- a/tests/spdx3/model/software/test_file.py +++ /dev/null @@ -1,45 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from unittest import mock - -import pytest - -from spdx_tools.spdx3.model.software import File, SoftwarePurpose - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_correct_initialization(creation_info): - file = File( - "SPDXRef-File", - "Test file", - creation_info=creation_info, - verified_using=None, - content_identifier="https://any.uri", - purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE], - content_type="MediaType", - ) - - assert file.spdx_id == "SPDXRef-File" - assert file.creation_info == creation_info - assert file.name == "Test file" - assert file.content_identifier == "https://any.uri" - assert file.purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.FILE] - assert file.content_type == "MediaType" - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_invalid_initialization(creation_info): - with pytest.raises(TypeError) as err: - File( - 1, - "test file", - creation_info=creation_info, - content_identifier=3, - purpose=SoftwarePurpose.FILE, - content_type=SoftwarePurpose.ARCHIVE, - ) - - assert len(err.value.args[0]) == 4 - for error in err.value.args[0]: - assert error.startswith("SetterError File:") diff --git a/tests/spdx3/model/software/test_package.py b/tests/spdx3/model/software/test_package.py deleted file mode 100644 index 3e1814fcb..000000000 --- a/tests/spdx3/model/software/test_package.py +++ /dev/null @@ -1,70 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from datetime import datetime -from unittest import mock - -import pytest - -from spdx_tools.spdx3.model.software import Package, SoftwarePurpose - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_correct_initialization(creation_info): - package = Package( - "SPDXRef-Package", - "Test package", - creation_info=creation_info, - content_identifier="https://any.uri", - originated_by=["https://namespace.test#originator"], - supplied_by=["https://namespace.test#supplier"], - built_time=datetime(2022, 1, 1), - release_time=datetime(2022, 1, 2), - valid_until_time=datetime(2022, 1, 3), - standard=["ISO"], - purpose=[SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH], - package_version="1:23a_bc", - download_location="https://downloadlocation", - package_url="https://package.uri", - homepage="https://homepage", - source_info="some info", - ) - - assert package.spdx_id == "SPDXRef-Package" - assert package.creation_info == creation_info - assert package.name == "Test package" - assert package.content_identifier == "https://any.uri" - assert package.originated_by == ["https://namespace.test#originator"] - assert package.supplied_by == ["https://namespace.test#supplier"] - assert package.built_time == datetime(2022, 1, 1) - assert package.release_time == datetime(2022, 1, 2) - assert package.valid_until_time == datetime(2022, 1, 3) - assert package.standard == ["ISO"] - assert package.purpose == [SoftwarePurpose.ARCHIVE, SoftwarePurpose.PATCH] - assert package.package_version == "1:23a_bc" - assert package.download_location == "https://downloadlocation" - assert package.package_url == "https://package.uri" - assert package.homepage == "https://homepage" - assert package.source_info == "some info" - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_invalid_initialization(creation_info): - with pytest.raises(TypeError) as err: - Package( - "SPDXRef-Package", - "Test package", - creation_info=creation_info, - built_time="2022-03-04T00:00:00Z", - content_identifier=3, - purpose=SoftwarePurpose.FILE, - package_version=42, - download_location=4, - package_url=["uris"], - homepage=True, - source_info=["some info"], - ) - - assert len(err.value.args[0]) == 8 - for error in err.value.args[0]: - assert error.startswith("SetterError Package:") diff --git a/tests/spdx3/model/software/test_sbom.py b/tests/spdx3/model/software/test_sbom.py deleted file mode 100644 index 97e53a93e..000000000 --- a/tests/spdx3/model/software/test_sbom.py +++ /dev/null @@ -1,34 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from unittest import mock - -import pytest - -from spdx_tools.spdx3.model.software import Sbom, SBOMType - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_correct_initialization(creation_info): - sbom = Sbom( - "SPDXRef-Sbom", - creation_info=creation_info, - element=["spdx_id1", "spdx_id2"], - root_element=["spdx_id3"], - sbom_type=[SBOMType.DESIGN], - ) - - assert sbom.spdx_id == "SPDXRef-Sbom" - assert sbom.creation_info == creation_info - assert sbom.element == ["spdx_id1", "spdx_id2"] - assert sbom.root_element == ["spdx_id3"] - assert sbom.sbom_type == [SBOMType.DESIGN] - - -def test_invalid_initialization(): - with pytest.raises(TypeError) as err: - Sbom(2, creation_info={"creation_info": [3, 4, 5]}, element=[], root_element=[]) - - assert len(err.value.args[0]) == 2 - for error in err.value.args[0]: - assert error.startswith("SetterError Sbom:") diff --git a/tests/spdx3/model/software/test_snippet.py b/tests/spdx3/model/software/test_snippet.py deleted file mode 100644 index 6aa6e4c1b..000000000 --- a/tests/spdx3/model/software/test_snippet.py +++ /dev/null @@ -1,37 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from unittest import mock - -import pytest - -from spdx_tools.spdx3.model.positive_integer_range import PositiveIntegerRange -from spdx_tools.spdx3.model.software import Snippet, SoftwarePurpose - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_correct_initialization(creation_info): - snippet = Snippet( - "SPDXRef-Snippet", - creation_info=creation_info, - content_identifier="https://content.identifier", - purpose=[SoftwarePurpose.SOURCE], - byte_range=PositiveIntegerRange(3, 4), - line_range=PositiveIntegerRange(346, 456), - ) - - assert snippet.spdx_id == "SPDXRef-Snippet" - assert snippet.content_identifier == "https://content.identifier" - assert snippet.purpose == [SoftwarePurpose.SOURCE] - assert snippet.byte_range == PositiveIntegerRange(3, 4) - assert snippet.line_range == PositiveIntegerRange(346, 456) - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_invalid_initialization(creation_info): - with pytest.raises(TypeError) as err: - Snippet(2, creation_info=creation_info, originated_by=34, byte_range="34:45") - - assert len(err.value.args[0]) == 3 - for error in err.value.args[0]: - assert error.startswith("SetterError Snippet:") diff --git a/tests/spdx3/model/software/test_software_dependency_relationship.py b/tests/spdx3/model/software/test_software_dependency_relationship.py deleted file mode 100644 index bb495d1bc..000000000 --- a/tests/spdx3/model/software/test_software_dependency_relationship.py +++ /dev/null @@ -1,59 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from datetime import datetime -from unittest import mock - -import pytest - -from spdx_tools.spdx3.model import LifecycleScopeType, RelationshipCompleteness, RelationshipType -from spdx_tools.spdx3.model.software import ( - DependencyConditionalityType, - SoftwareDependencyLinkType, - SoftwareDependencyRelationship, -) - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_correct_initialization(creation_info): - relationship = SoftwareDependencyRelationship( - "SPDXRef-Relationship", - "spdx_id1", - RelationshipType.DESCRIBES, - ["spdx_id2", "spdx_id3"], - creation_info=creation_info, - completeness=RelationshipCompleteness.NOASSERTION, - start_time=datetime(11, 11, 11), - end_time=datetime(12, 12, 12), - scope=LifecycleScopeType.DESIGN, - software_linkage=SoftwareDependencyLinkType.STATIC, - conditionality=DependencyConditionalityType.PROVIDED, - ) - - assert relationship.spdx_id == "SPDXRef-Relationship" - assert relationship.creation_info == creation_info - assert relationship.from_element == "spdx_id1" - assert relationship.to == ["spdx_id2", "spdx_id3"] - assert relationship.relationship_type == RelationshipType.DESCRIBES - assert relationship.completeness == RelationshipCompleteness.NOASSERTION - assert relationship.start_time == datetime(11, 11, 11) - assert relationship.end_time == datetime(12, 12, 12) - assert relationship.scope == LifecycleScopeType.DESIGN - assert relationship.software_linkage == SoftwareDependencyLinkType.STATIC - assert relationship.conditionality == DependencyConditionalityType.PROVIDED - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_invalid_initialization(creation_info): - with pytest.raises(TypeError) as err: - SoftwareDependencyRelationship( - "SPDXRef-Relationship", - "spdx_id1", - RelationshipType.DESCRIBES, - to=42, - creation_info=creation_info, - ) - - assert len(err.value.args[0]) == 1 - for error in err.value.args[0]: - assert error.startswith("SetterError SoftwareDependencyRelationship:") diff --git a/tests/spdx3/model/test_element_and_licensing_subclasses.py b/tests/spdx3/model/test_element_and_licensing_subclasses.py index d9413bf7b..0fb225860 100644 --- a/tests/spdx3/model/test_element_and_licensing_subclasses.py +++ b/tests/spdx3/model/test_element_and_licensing_subclasses.py @@ -33,6 +33,7 @@ VexUnderInvestigationVulnAssessmentRelationship, Vulnerability, ) +from spdx_tools.spdx3.model.software import File, Package, Sbom, Snippet, SoftwareDependencyRelationship from tests.spdx3.fixtures import fixture_factory, get_fixture_dict from tests.spdx3.model.model_test_utils import InvalidTypeClass, get_property_names @@ -61,6 +62,11 @@ VexNotAffectedVulnAssessmentRelationship, VexUnderInvestigationVulnAssessmentRelationship, Vulnerability, + File, + Package, + Snippet, + Sbom, + SoftwareDependencyRelationship, ] From c192f8aaed44559a81d3535b0c055d180a95b2a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 5 Jun 2023 11:57:24 +0200 Subject: [PATCH 266/354] [issue-432] use Build, AIPackage and Dataset fixtures in tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx3/fixtures.py | 15 +++++ tests/spdx3/model/ai/__init__.py | 0 tests/spdx3/model/ai/test_ai_package.py | 59 ------------------- tests/spdx3/model/build/__init__.py | 0 tests/spdx3/model/build/test_build.py | 52 ---------------- tests/spdx3/model/dataset/__init__.py | 0 tests/spdx3/model/dataset/test_dataset.py | 54 ----------------- .../test_element_and_licensing_subclasses.py | 6 ++ 8 files changed, 21 insertions(+), 165 deletions(-) delete mode 100644 tests/spdx3/model/ai/__init__.py delete mode 100644 tests/spdx3/model/ai/test_ai_package.py delete mode 100644 tests/spdx3/model/build/__init__.py delete mode 100644 tests/spdx3/model/build/test_build.py delete mode 100644 tests/spdx3/model/dataset/__init__.py delete mode 100644 tests/spdx3/model/dataset/test_dataset.py diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 9ed15f275..64511a1eb 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -34,6 +34,7 @@ Tool, ) from spdx_tools.spdx3.model.ai.ai_package import AIPackage, SafetyRiskAssessmentType +from spdx_tools.spdx3.model.build import Build from spdx_tools.spdx3.model.dataset.dataset import ConfidentialityLevelType, Dataset, DatasetAvailabilityType from spdx_tools.spdx3.model.licensing import ( CustomLicense, @@ -404,6 +405,7 @@ def listed_license_fixture( } DATASET_DICT = { + "dataset_type": "DatasetType", "data_collection_process": "DatasetDataCollectionProcess", "intended_use": "DatasetIntendedUse", "dataset_size": 10, @@ -418,6 +420,18 @@ def listed_license_fixture( "dataset_availability": DatasetAvailabilityType.QUERY, } +BUILD_DICT = { + "build_type": "BuildType", + "build_id": "BuildId", + "config_source_entrypoint": ["ConfigSourceEntrypoint"], + "config_source_uri": ["ConfigSourceURI"], + "config_source_digest": [hash_fixture()], + "parameters": {"parameter": "value"}, + "build_start_time": datetime(2015, 4, 4), + "build_end_time": datetime(2015, 4, 5), + "environment": {"environment_param": "environment_value"}, +} + FIXTURE_DICTS = { Agent: [ELEMENT_DICT], Person: [ELEMENT_DICT], @@ -505,6 +519,7 @@ def listed_license_fixture( SOFTWARE_DEPENDENCY_RELATIONSHIP_DICT, ], Dataset: [ELEMENT_DICT, ARTIFACT_DICT, SOFTWARE_ARTIFACT_DICT, PACKAGE_DICT, DATASET_DICT], + Build: [ELEMENT_DICT, BUILD_DICT], } diff --git a/tests/spdx3/model/ai/__init__.py b/tests/spdx3/model/ai/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/spdx3/model/ai/test_ai_package.py b/tests/spdx3/model/ai/test_ai_package.py deleted file mode 100644 index 0990d5056..000000000 --- a/tests/spdx3/model/ai/test_ai_package.py +++ /dev/null @@ -1,59 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from datetime import datetime -from unittest import mock - -from spdx_tools.spdx3.model.ai import AIPackage -from spdx_tools.spdx3.model.ai.ai_package import SafetyRiskAssessmentType -from spdx_tools.spdx3.model.software import SoftwarePurpose - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_correct_initialization(creation_info): - ai_package = AIPackage( - "some_spdx_id", - "AI Package name", - ["https://namespace.test#supplier"], - "https://download.test", - "1.2:rc2", - [SoftwarePurpose.SOURCE], - datetime(12, 5, 23, 11), - creation_info=creation_info, - energy_consumption="energy consumption", - standard_compliance=["some standard"], - limitation="limitation", - type_of_model=["model type"], - information_about_training="training info", - information_about_application="app info", - hyperparameter={"param": "value"}, - model_data_preprocessing=["preprocessing steps"], - model_explainability=["mechanism"], - sensitive_personal_information=True, - metric_decision_threshold={"metric1": "threshold", "metric2": None}, - metric={"metric1": "value1", "metric2": None}, - domain=["domain"], - autonomy_type=True, - safety_risk_assessment=SafetyRiskAssessmentType.HIGH, - ) - - assert ai_package.supplied_by == ["https://namespace.test#supplier"] - assert ai_package.download_location == "https://download.test" - assert ai_package.package_version == "1.2:rc2" - assert ai_package.purpose == [SoftwarePurpose.SOURCE] - assert ai_package.release_time == datetime(12, 5, 23, 11) - assert ai_package.energy_consumption == "energy consumption" - assert ai_package.standard_compliance == ["some standard"] - assert ai_package.limitation == "limitation" - assert ai_package.type_of_model == ["model type"] - assert ai_package.information_about_training == "training info" - assert ai_package.information_about_application == "app info" - assert ai_package.hyperparameter == {"param": "value"} - assert ai_package.model_data_preprocessing == ["preprocessing steps"] - assert ai_package.model_explainability == ["mechanism"] - assert ai_package.sensitive_personal_information - assert ai_package.metric_decision_threshold == {"metric1": "threshold", "metric2": None} - assert ai_package.metric == {"metric1": "value1", "metric2": None} - assert ai_package.domain == ["domain"] - assert ai_package.autonomy_type - assert ai_package.safety_risk_assessment == SafetyRiskAssessmentType.HIGH diff --git a/tests/spdx3/model/build/__init__.py b/tests/spdx3/model/build/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/spdx3/model/build/test_build.py b/tests/spdx3/model/build/test_build.py deleted file mode 100644 index 6e8671b2f..000000000 --- a/tests/spdx3/model/build/test_build.py +++ /dev/null @@ -1,52 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from datetime import datetime -from unittest import mock - -import pytest - -from spdx_tools.spdx3.model import Hash, HashAlgorithm -from spdx_tools.spdx3.model.build import Build - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_correct_initialization(creation_info): - build = Build( - "some_spdx_id", - creation_info=creation_info, - build_type="build type", - build_id="build id", - config_source_entrypoint=["entrypoint"], - config_source_uri=["uri"], - config_source_digest=[Hash(HashAlgorithm.MD2, "abcdef")], - parameters={"param1": "value1"}, - build_start_time=datetime(2023, 1, 1), - build_end_time=datetime(2023, 2, 2), - environment={"param2": "value2"}, - ) - - assert build.build_type == "build type" - assert build.build_id == "build id" - assert build.config_source_entrypoint == ["entrypoint"] - assert build.config_source_uri == ["uri"] - assert build.config_source_digest == [Hash(HashAlgorithm.MD2, "abcdef")] - assert build.parameters == {"param1": "value1"} - assert build.build_start_time == datetime(2023, 1, 1) - assert build.build_end_time == datetime(2023, 2, 2) - assert build.environment == {"param2": "value2"} - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_invalid_initialization(creation_info): - with pytest.raises(TypeError) as err: - Build( - "some_spdx_id", - creation_info=creation_info, - build_type="build type", - config_source_digest=["hash_value"], - ) - - assert len(err.value.args[0]) == 1 - for error in err.value.args[0]: - assert error.startswith("SetterError Build:") diff --git a/tests/spdx3/model/dataset/__init__.py b/tests/spdx3/model/dataset/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/spdx3/model/dataset/test_dataset.py b/tests/spdx3/model/dataset/test_dataset.py deleted file mode 100644 index 46a9002da..000000000 --- a/tests/spdx3/model/dataset/test_dataset.py +++ /dev/null @@ -1,54 +0,0 @@ -# SPDX-FileCopyrightText: 2023 spdx contributors -# -# SPDX-License-Identifier: Apache-2.0 -from datetime import datetime -from unittest import mock - -from spdx_tools.spdx3.model.dataset import ConfidentialityLevelType, Dataset, DatasetAvailabilityType -from spdx_tools.spdx3.model.software import SoftwarePurpose - - -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_correct_initialization(creation_info): - dataset = Dataset( - "some_spdx_id", - "Dataset name", - ["https://namespace.test#originator"], - "https://download.test", - [SoftwarePurpose.DATA], - datetime(10, 5, 23, 11), - datetime(11, 5, 24, 12), - "training data", - creation_info=creation_info, - data_collection_process="data collection process", - intended_use="intended use", - dataset_size=420000, - dataset_noise="dataset noise", - data_preprocessing=["data preprocessing steps"], - sensor={"sensor1": "some value"}, - known_bias=["known biases"], - sensitive_personal_information=True, - anonymization_method_used=["anonymization method"], - confidentiality_level=ConfidentialityLevelType.RED, - dataset_update_mechanism="update mechanism", - dataset_availability=DatasetAvailabilityType.QUERY, - ) - - assert dataset.originated_by == ["https://namespace.test#originator"] - assert dataset.download_location == "https://download.test" - assert dataset.purpose == [SoftwarePurpose.DATA] - assert dataset.built_time == datetime(10, 5, 23, 11) - assert dataset.release_time == datetime(11, 5, 24, 12) - assert dataset.dataset_type == "training data" - assert dataset.data_collection_process == "data collection process" - assert dataset.intended_use == "intended use" - assert dataset.dataset_size == 420000 - assert dataset.dataset_noise == "dataset noise" - assert dataset.data_preprocessing == ["data preprocessing steps"] - assert dataset.sensor == {"sensor1": "some value"} - assert dataset.known_bias == ["known biases"] - assert dataset.sensitive_personal_information - assert dataset.anonymization_method_used == ["anonymization method"] - assert dataset.confidentiality_level == ConfidentialityLevelType.RED - assert dataset.dataset_update_mechanism == "update mechanism" - assert dataset.dataset_availability == DatasetAvailabilityType.QUERY diff --git a/tests/spdx3/model/test_element_and_licensing_subclasses.py b/tests/spdx3/model/test_element_and_licensing_subclasses.py index 0fb225860..0df9aa69f 100644 --- a/tests/spdx3/model/test_element_and_licensing_subclasses.py +++ b/tests/spdx3/model/test_element_and_licensing_subclasses.py @@ -15,6 +15,9 @@ SoftwareAgent, SpdxDocument, ) +from spdx_tools.spdx3.model.ai import AIPackage +from spdx_tools.spdx3.model.build import Build +from spdx_tools.spdx3.model.dataset import Dataset from spdx_tools.spdx3.model.licensing import ( CustomLicense, CustomLicenseAddition, @@ -67,6 +70,9 @@ Snippet, Sbom, SoftwareDependencyRelationship, + Dataset, + AIPackage, + Build, ] From f2d9291e16ab7478b6ee7a8e88dd73d4303721c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 5 Jun 2023 12:22:03 +0200 Subject: [PATCH 267/354] [issue-432] adapt license header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/common/typing/type_checks.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/spdx_tools/common/typing/type_checks.py b/src/spdx_tools/common/typing/type_checks.py index 38734de35..26659c47c 100644 --- a/src/spdx_tools/common/typing/type_checks.py +++ b/src/spdx_tools/common/typing/type_checks.py @@ -1,13 +1,6 @@ -# Copyright (c) 2022 spdx contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 from dataclasses import fields from typing import Any, Dict From 7881f7ebe74261142555da1027e1cd6ca1049268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 6 Jun 2023 08:48:02 +0200 Subject: [PATCH 268/354] include basic documentation on the SPDX 3 part of the library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- README.md | 23 +++++++++++++++++++++-- src/spdx_tools/spdx3/README.md | 1 - 2 files changed, 21 insertions(+), 3 deletions(-) delete mode 100644 src/spdx_tools/spdx3/README.md diff --git a/README.md b/README.md index c4415c675..8d534bc62 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,14 @@ This library implements SPDX parsers, convertors, validators and handlers in Pyt * visualize the structure of a SPDX document by creating an `AGraph`. Note: This is an optional feature and requires additional installation of optional dependencies -# Planned features +## Experimental support for SPDX 3.0 +* Create v3.0 elements and payloads +* Convert v2.2/v2.3 documents to v3.0 +* Serialize to JSON-LD + +See [Quickstart to SPDX 3.0](#quickstart-to-spdx-30) below. +The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: ea2e1446ae937c6722b3f599f95813f8747d54b4). -* up-to-date support of SPDX v3.0 as soon as it is released # Installation @@ -163,6 +168,20 @@ if not validation_messages: write_file(document, "new_spdx_document.rdf", validate=False) ``` +# Quickstart to SPDX 3.0 +In contrast to SPDX v2, all elements are now subclasses of the central `Element` class. +This includes packages, files, snippets, relationships, annotations, but also SBOMs, SpdxDocuments, and more. +For serialization purposes, all Elements that are to be serialized into the same file are collected in a `Payload`. +This is just a dictionary that maps each Element's SpdxId to itself. +Use the `write_payload()` functions to serialize a payload. +There currently are two options: +* The `spdx_tools.spdx3.writer.json_ld.json_ld_writer` module generates a JSON-LD file of the payload. +* The `spdx_tools.spdx3.writer.console.payload_writer` module prints a debug output to console. Note that this is not an official part of the SPDX specification and will probably be dropped as soon as a better standard emerges. + +You can convert an SPDX v2 document to v3 via the `spdx_tools.spdx3.bump_from_spdx2.spdx_document` module. +The `bump_spdx_document()` function will return a payload containing an `SpdxDocument` Element and one Element for each package, file, snippet, relationship, or annotation contained in the v2 document. + + # Dependencies * PyYAML: https://pypi.org/project/PyYAML/ for handling YAML. diff --git a/src/spdx_tools/spdx3/README.md b/src/spdx_tools/spdx3/README.md deleted file mode 100644 index 0f32aa1a9..000000000 --- a/src/spdx_tools/spdx3/README.md +++ /dev/null @@ -1 +0,0 @@ -This implementation is mainly based on the descriptive markdown files and the model.png in the repository https://github.com/spdx/spdx-3-model (latest commit: ea2e1446ae937c6722b3f599f95813f8747d54b4). From c9423f31cb2bcb61aad5cff268d655021e893e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 30 May 2023 17:23:11 +0200 Subject: [PATCH 269/354] [issue-677] README: point installation guide to the newest release, not current MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8d534bc62..828c62a4f 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,9 @@ The implementation is based on the descriptive markdown files in the repository # Installation As always you should work in a virtualenv (venv). You can install a local clone -of this repo with `yourenv/bin/pip install .` or install it from PyPI with -`yourenv/bin/pip install spdx-tools`. Note that on Windows it would be `Scripts` +of this repo with `yourenv/bin/pip install .` or install it from PyPI +(check for the [newest release](https://pypi.org/project/spdx-tools/#history) and install it like +`yourenv/bin/pip install spdx-tools==0.8.0a2`). Note that on Windows it would be `Scripts` instead of `bin`. # How to use From 78578503f8d718715b3444463098971f4029633b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 7 Jun 2023 10:10:32 +0200 Subject: [PATCH 270/354] [issue-688] replace typing with beartype.typing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this addresses warnings about possibly dropped typing support in some later python version Signed-off-by: Armin Tänzer --- src/spdx_tools/common/typing/constructor_type_errors.py | 2 +- src/spdx_tools/common/typing/type_checks.py | 3 ++- src/spdx_tools/spdx/clitools/pyspdxtools.py | 2 +- src/spdx_tools/spdx/document_utils.py | 3 ++- src/spdx_tools/spdx/graph_generation.py | 2 +- src/spdx_tools/spdx/jsonschema/annotation_converter.py | 2 +- src/spdx_tools/spdx/jsonschema/checksum_converter.py | 2 +- src/spdx_tools/spdx/jsonschema/converter.py | 3 ++- src/spdx_tools/spdx/jsonschema/creation_info_converter.py | 2 +- src/spdx_tools/spdx/jsonschema/document_converter.py | 2 +- .../spdx/jsonschema/external_document_ref_converter.py | 2 +- .../spdx/jsonschema/external_package_ref_converter.py | 2 +- .../spdx/jsonschema/extracted_licensing_info_converter.py | 2 +- src/spdx_tools/spdx/jsonschema/file_converter.py | 2 +- src/spdx_tools/spdx/jsonschema/optional_utils.py | 2 +- src/spdx_tools/spdx/jsonschema/package_converter.py | 2 +- .../spdx/jsonschema/package_verification_code_converter.py | 2 +- src/spdx_tools/spdx/jsonschema/relationship_converter.py | 2 +- src/spdx_tools/spdx/jsonschema/snippet_converter.py | 2 +- src/spdx_tools/spdx/model/actor.py | 3 ++- src/spdx_tools/spdx/model/document.py | 3 ++- src/spdx_tools/spdx/model/extracted_licensing_info.py | 3 ++- src/spdx_tools/spdx/model/file.py | 2 +- src/spdx_tools/spdx/model/package.py | 2 +- src/spdx_tools/spdx/model/relationship.py | 3 ++- src/spdx_tools/spdx/model/relationship_filters.py | 2 +- src/spdx_tools/spdx/model/snippet.py | 2 +- src/spdx_tools/spdx/parser/actor_parser.py | 3 ++- src/spdx_tools/spdx/parser/error.py | 2 +- src/spdx_tools/spdx/parser/json/json_parser.py | 3 ++- src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py | 3 ++- src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py | 2 +- .../spdx/parser/jsonlikedict/creation_info_parser.py | 3 ++- .../spdx/parser/jsonlikedict/dict_parsing_functions.py | 2 +- .../parser/jsonlikedict/extracted_licensing_info_parser.py | 2 +- src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py | 3 +-- .../spdx/parser/jsonlikedict/json_like_dict_parser.py | 2 +- .../spdx/parser/jsonlikedict/license_expression_parser.py | 3 +-- src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py | 2 +- src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py | 2 +- src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py | 2 +- src/spdx_tools/spdx/parser/logger.py | 2 +- src/spdx_tools/spdx/parser/parsing_functions.py | 2 +- src/spdx_tools/spdx/parser/rdf/creation_info_parser.py | 2 +- src/spdx_tools/spdx/parser/rdf/file_parser.py | 3 +-- src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py | 2 +- src/spdx_tools/spdx/parser/rdf/license_expression_parser.py | 3 +-- src/spdx_tools/spdx/parser/rdf/package_parser.py | 3 +-- src/spdx_tools/spdx/parser/rdf/rdf_parser.py | 3 +-- src/spdx_tools/spdx/parser/rdf/snippet_parser.py | 3 +-- src/spdx_tools/spdx/parser/tagvalue/helper_methods.py | 2 +- src/spdx_tools/spdx/parser/tagvalue/parser.py | 2 +- src/spdx_tools/spdx/parser/xml/xml_parser.py | 3 +-- src/spdx_tools/spdx/parser/yaml/yaml_parser.py | 3 +-- src/spdx_tools/spdx/spdx_element_utils.py | 2 +- src/spdx_tools/spdx/validation/actor_validator.py | 2 +- src/spdx_tools/spdx/validation/annotation_validator.py | 2 +- src/spdx_tools/spdx/validation/checksum_validator.py | 3 ++- src/spdx_tools/spdx/validation/creation_info_validator.py | 2 +- src/spdx_tools/spdx/validation/document_validator.py | 2 +- .../spdx/validation/external_document_ref_validator.py | 2 +- .../spdx/validation/external_package_ref_validator.py | 2 +- .../spdx/validation/extracted_licensing_info_validator.py | 3 ++- src/spdx_tools/spdx/validation/file_validator.py | 2 +- src/spdx_tools/spdx/validation/license_expression_validator.py | 3 +-- src/spdx_tools/spdx/validation/package_validator.py | 2 +- .../spdx/validation/package_verification_code_validator.py | 3 ++- src/spdx_tools/spdx/validation/relationship_validator.py | 2 +- src/spdx_tools/spdx/validation/snippet_validator.py | 2 +- src/spdx_tools/spdx/validation/spdx_id_validators.py | 3 ++- src/spdx_tools/spdx/validation/uri_validators.py | 2 +- src/spdx_tools/spdx/validation/validation_message.py | 3 ++- src/spdx_tools/spdx/writer/json/json_writer.py | 3 ++- src/spdx_tools/spdx/writer/rdf/annotation_writer.py | 3 +-- src/spdx_tools/spdx/writer/rdf/file_writer.py | 3 +-- src/spdx_tools/spdx/writer/rdf/license_expression_writer.py | 3 +-- src/spdx_tools/spdx/writer/rdf/package_writer.py | 3 +-- src/spdx_tools/spdx/writer/rdf/rdf_writer.py | 3 +-- src/spdx_tools/spdx/writer/rdf/relationship_writer.py | 3 +-- src/spdx_tools/spdx/writer/rdf/snippet_writer.py | 3 +-- src/spdx_tools/spdx/writer/rdf/writer_utils.py | 2 +- src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py | 2 +- src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py | 2 +- .../spdx/writer/tagvalue/extracted_licensing_info_writer.py | 2 +- src/spdx_tools/spdx/writer/tagvalue/file_writer.py | 2 +- src/spdx_tools/spdx/writer/tagvalue/package_writer.py | 2 +- src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py | 2 +- src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py | 2 +- src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py | 2 +- .../spdx/writer/tagvalue/tagvalue_writer_helper_functions.py | 3 +-- src/spdx_tools/spdx/writer/xml/xml_writer.py | 3 +-- src/spdx_tools/spdx/writer/yaml/yaml_writer.py | 3 +-- src/spdx_tools/spdx3/bump_from_spdx2/actor.py | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/bump_utils.py | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py | 3 +-- src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/file.py | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py | 3 +-- src/spdx_tools/spdx3/bump_from_spdx2/package.py | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/relationship.py | 3 ++- src/spdx_tools/spdx3/bump_from_spdx2/snippet.py | 2 +- src/spdx_tools/spdx3/clitools/pyspdxtools3.py | 2 +- src/spdx_tools/spdx3/model/agent.py | 2 +- src/spdx_tools/spdx3/model/ai/ai_package.py | 3 ++- src/spdx_tools/spdx3/model/annotation.py | 3 ++- src/spdx_tools/spdx3/model/artifact.py | 3 ++- src/spdx_tools/spdx3/model/bom.py | 2 +- src/spdx_tools/spdx3/model/build/build.py | 3 ++- src/spdx_tools/spdx3/model/bundle.py | 2 +- src/spdx_tools/spdx3/model/creation_info.py | 2 +- src/spdx_tools/spdx3/model/dataset/dataset.py | 3 ++- src/spdx_tools/spdx3/model/element.py | 3 ++- src/spdx_tools/spdx3/model/external_identifier.py | 3 ++- src/spdx_tools/spdx3/model/external_map.py | 3 ++- src/spdx_tools/spdx3/model/external_reference.py | 3 ++- src/spdx_tools/spdx3/model/hash.py | 3 ++- src/spdx_tools/spdx3/model/integrity_method.py | 3 ++- .../spdx3/model/licensing/conjunctive_license_set.py | 2 +- src/spdx_tools/spdx3/model/licensing/custom_license.py | 2 +- .../spdx3/model/licensing/custom_license_addition.py | 2 +- .../spdx3/model/licensing/disjunctive_license_set.py | 2 +- src/spdx_tools/spdx3/model/licensing/license.py | 3 ++- src/spdx_tools/spdx3/model/licensing/license_addition.py | 3 ++- src/spdx_tools/spdx3/model/licensing/listed_license.py | 2 +- .../spdx3/model/licensing/listed_license_exception.py | 2 +- src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py | 3 ++- src/spdx_tools/spdx3/model/namespace_map.py | 2 +- src/spdx_tools/spdx3/model/organization.py | 2 +- src/spdx_tools/spdx3/model/person.py | 2 +- src/spdx_tools/spdx3/model/relationship.py | 3 ++- .../model/security/cvss_v2_vuln_assessment_relationship.py | 3 ++- .../model/security/cvss_v3_vuln_assessment_relationship.py | 3 ++- .../spdx3/model/security/epss_vuln_assessment_relationship.py | 3 ++- .../security/exploit_catalog_vuln_assessment_relationship.py | 3 ++- .../spdx3/model/security/ssvc_vuln_assessment_relationship.py | 3 ++- .../security/vex_affected_vuln_assessment_relationship.py | 3 ++- .../model/security/vex_fixed_vuln_assessment_relationship.py | 3 ++- .../security/vex_not_affected_vuln_assessment_relationship.py | 3 ++- .../vex_under_investigation_vuln_assessment_relationship.py | 3 ++- .../spdx3/model/security/vex_vuln_assessment_relationship.py | 3 ++- .../spdx3/model/security/vuln_assessment_relationship.py | 3 ++- src/spdx_tools/spdx3/model/security/vulnerability.py | 3 ++- src/spdx_tools/spdx3/model/software/file.py | 3 ++- src/spdx_tools/spdx3/model/software/package.py | 3 ++- src/spdx_tools/spdx3/model/software/sbom.py | 3 ++- src/spdx_tools/spdx3/model/software/snippet.py | 3 ++- src/spdx_tools/spdx3/model/software/software_artifact.py | 3 ++- .../spdx3/model/software/software_dependency_relationship.py | 3 ++- src/spdx_tools/spdx3/model/software_agent.py | 2 +- src/spdx_tools/spdx3/model/spdx_collection.py | 3 ++- src/spdx_tools/spdx3/model/spdx_document.py | 2 +- src/spdx_tools/spdx3/model/tool.py | 2 +- src/spdx_tools/spdx3/payload.py | 2 +- src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py | 3 +-- src/spdx_tools/spdx3/writer/console/agent_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/annotation_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/artifact_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/bom_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/build/build_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/bundle_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/console.py | 3 ++- src/spdx_tools/spdx3/writer/console/creation_info_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/element_writer.py | 2 +- .../spdx3/writer/console/external_identifier_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/external_map_writer.py | 2 +- .../spdx3/writer/console/external_reference_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/hash_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/integrity_method_writer.py | 2 +- .../writer/console/lifecycle_scoped_relationship_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/namespace_map_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/payload_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/relationship_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/software/file_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/software/package_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/software/sbom_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/software/snippet_writer.py | 2 +- .../software/software_dependency_relationship_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/spdx_document_writer.py | 2 +- src/spdx_tools/spdx3/writer/console/tool_writer.py | 2 +- src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py | 2 +- 183 files changed, 236 insertions(+), 206 deletions(-) diff --git a/src/spdx_tools/common/typing/constructor_type_errors.py b/src/spdx_tools/common/typing/constructor_type_errors.py index 90c8d8402..e70f53329 100644 --- a/src/spdx_tools/common/typing/constructor_type_errors.py +++ b/src/spdx_tools/common/typing/constructor_type_errors.py @@ -1,4 +1,4 @@ -from typing import List +from beartype.typing import List class ConstructorTypeErrors(TypeError): diff --git a/src/spdx_tools/common/typing/type_checks.py b/src/spdx_tools/common/typing/type_checks.py index 26659c47c..d9dc9733a 100644 --- a/src/spdx_tools/common/typing/type_checks.py +++ b/src/spdx_tools/common/typing/type_checks.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from dataclasses import fields -from typing import Any, Dict + +from beartype.typing import Any, Dict from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors diff --git a/src/spdx_tools/spdx/clitools/pyspdxtools.py b/src/spdx_tools/spdx/clitools/pyspdxtools.py index 556033aee..8603b8401 100644 --- a/src/spdx_tools/spdx/clitools/pyspdxtools.py +++ b/src/spdx_tools/spdx/clitools/pyspdxtools.py @@ -14,9 +14,9 @@ # limitations under the License. import logging import sys -from typing import List import click +from beartype.typing import List from spdx_tools.spdx.graph_generation import export_graph_from_document from spdx_tools.spdx.model import Document diff --git a/src/spdx_tools/spdx/document_utils.py b/src/spdx_tools/spdx/document_utils.py index eb3612ab6..c0c0f5b27 100644 --- a/src/spdx_tools/spdx/document_utils.py +++ b/src/spdx_tools/spdx/document_utils.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from copy import deepcopy -from typing import Any, Dict, List, Union + +from beartype.typing import Any, Dict, List, Union from spdx_tools.spdx.model import Document, File, Package, Snippet diff --git a/src/spdx_tools/spdx/graph_generation.py b/src/spdx_tools/spdx/graph_generation.py index 1ef70a1c8..da4345d50 100644 --- a/src/spdx_tools/spdx/graph_generation.py +++ b/src/spdx_tools/spdx/graph_generation.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict, List, Union +from beartype.typing import Dict, List, Union from spdx_tools.spdx.model import File, Package, Snippet diff --git a/src/spdx_tools/spdx/jsonschema/annotation_converter.py b/src/spdx_tools/spdx/jsonschema/annotation_converter.py index 7fbedf51f..16645a216 100644 --- a/src/spdx_tools/spdx/jsonschema/annotation_converter.py +++ b/src/spdx_tools/spdx/jsonschema/annotation_converter.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Type +from beartype.typing import Any, Type from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string from spdx_tools.spdx.jsonschema.annotation_properties import AnnotationProperty diff --git a/src/spdx_tools/spdx/jsonschema/checksum_converter.py b/src/spdx_tools/spdx/jsonschema/checksum_converter.py index a1d2bb9fd..9ffb39b11 100644 --- a/src/spdx_tools/spdx/jsonschema/checksum_converter.py +++ b/src/spdx_tools/spdx/jsonschema/checksum_converter.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Type +from beartype.typing import Type from spdx_tools.spdx.jsonschema.checksum_properties import ChecksumProperty from spdx_tools.spdx.jsonschema.converter import TypedConverter diff --git a/src/spdx_tools/spdx/jsonschema/converter.py b/src/spdx_tools/spdx/jsonschema/converter.py index 4ec479623..55629f2ae 100644 --- a/src/spdx_tools/spdx/jsonschema/converter.py +++ b/src/spdx_tools/spdx/jsonschema/converter.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from abc import ABC, abstractmethod -from typing import Any, Dict, Generic, Type, TypeVar + +from beartype.typing import Any, Dict, Generic, Type, TypeVar from spdx_tools.spdx.casing_tools import snake_case_to_camel_case from spdx_tools.spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx_tools/spdx/jsonschema/creation_info_converter.py b/src/spdx_tools/spdx/jsonschema/creation_info_converter.py index 6e84bfe19..0a2ef875c 100644 --- a/src/spdx_tools/spdx/jsonschema/creation_info_converter.py +++ b/src/spdx_tools/spdx/jsonschema/creation_info_converter.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Type +from beartype.typing import Any, Type from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string from spdx_tools.spdx.jsonschema.converter import TypedConverter diff --git a/src/spdx_tools/spdx/jsonschema/document_converter.py b/src/spdx_tools/spdx/jsonschema/document_converter.py index 4d001c75c..a3c2e3699 100644 --- a/src/spdx_tools/spdx/jsonschema/document_converter.py +++ b/src/spdx_tools/spdx/jsonschema/document_converter.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Type +from beartype.typing import Any, Type from spdx_tools.spdx.document_utils import get_contained_spdx_element_ids from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter diff --git a/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py b/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py index c2e803662..f25bf56e3 100644 --- a/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py +++ b/src/spdx_tools/spdx/jsonschema/external_document_ref_converter.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Type +from beartype.typing import Any, Type from spdx_tools.spdx.jsonschema.checksum_converter import ChecksumConverter from spdx_tools.spdx.jsonschema.converter import TypedConverter diff --git a/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py b/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py index 36d528e26..732673c36 100644 --- a/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py +++ b/src/spdx_tools/spdx/jsonschema/external_package_ref_converter.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Type +from beartype.typing import Any, Type from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.external_package_ref_properties import ExternalPackageRefProperty diff --git a/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py b/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py index d7ada1c95..9bf0a8530 100644 --- a/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py +++ b/src/spdx_tools/spdx/jsonschema/extracted_licensing_info_converter.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Type +from beartype.typing import Any, Type from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.extracted_licensing_info_properties import ExtractedLicensingInfoProperty diff --git a/src/spdx_tools/spdx/jsonschema/file_converter.py b/src/spdx_tools/spdx/jsonschema/file_converter.py index 20173f606..7c8ae4ad1 100644 --- a/src/spdx_tools/spdx/jsonschema/file_converter.py +++ b/src/spdx_tools/spdx/jsonschema/file_converter.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Type +from beartype.typing import Any, Type from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter from spdx_tools.spdx.jsonschema.checksum_converter import ChecksumConverter diff --git a/src/spdx_tools/spdx/jsonschema/optional_utils.py b/src/spdx_tools/spdx/jsonschema/optional_utils.py index 4f9d74074..3d3f9e223 100644 --- a/src/spdx_tools/spdx/jsonschema/optional_utils.py +++ b/src/spdx_tools/spdx/jsonschema/optional_utils.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Callable, Optional, TypeVar +from beartype.typing import Callable, Optional, TypeVar T = TypeVar("T") S = TypeVar("S") diff --git a/src/spdx_tools/spdx/jsonschema/package_converter.py b/src/spdx_tools/spdx/jsonschema/package_converter.py index 279eeb473..074fc7a78 100644 --- a/src/spdx_tools/spdx/jsonschema/package_converter.py +++ b/src/spdx_tools/spdx/jsonschema/package_converter.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Type +from beartype.typing import Any, Type from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter diff --git a/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py b/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py index 4076bb151..b98396272 100644 --- a/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py +++ b/src/spdx_tools/spdx/jsonschema/package_verification_code_converter.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Type +from beartype.typing import Any, Type from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx_tools/spdx/jsonschema/relationship_converter.py b/src/spdx_tools/spdx/jsonschema/relationship_converter.py index 23b479e9e..78442d25b 100644 --- a/src/spdx_tools/spdx/jsonschema/relationship_converter.py +++ b/src/spdx_tools/spdx/jsonschema/relationship_converter.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Type +from beartype.typing import Any, Type from spdx_tools.spdx.jsonschema.converter import TypedConverter from spdx_tools.spdx.jsonschema.json_property import JsonProperty diff --git a/src/spdx_tools/spdx/jsonschema/snippet_converter.py b/src/spdx_tools/spdx/jsonschema/snippet_converter.py index d0736a943..a4e75c4fa 100644 --- a/src/spdx_tools/spdx/jsonschema/snippet_converter.py +++ b/src/spdx_tools/spdx/jsonschema/snippet_converter.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Dict, Tuple, Type +from beartype.typing import Any, Dict, Tuple, Type from spdx_tools.spdx.jsonschema.annotation_converter import AnnotationConverter from spdx_tools.spdx.jsonschema.converter import TypedConverter diff --git a/src/spdx_tools/spdx/model/actor.py b/src/spdx_tools/spdx/model/actor.py index aff462bfc..9aeb9e059 100644 --- a/src/spdx_tools/spdx/model/actor.py +++ b/src/spdx_tools/spdx/model/actor.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto -from typing import Optional + +from beartype.typing import Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx/model/document.py b/src/spdx_tools/spdx/model/document.py index ecfddc6a1..980c59ca5 100644 --- a/src/spdx_tools/spdx/model/document.py +++ b/src/spdx_tools/spdx/model/document.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from datetime import datetime -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx/model/extracted_licensing_info.py b/src/spdx_tools/spdx/model/extracted_licensing_info.py index 22df3ec19..e401dd7b6 100644 --- a/src/spdx_tools/spdx/model/extracted_licensing_info.py +++ b/src/spdx_tools/spdx/model/extracted_licensing_info.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from dataclasses import field -from typing import List, Optional, Union + +from beartype.typing import List, Optional, Union from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx/model/file.py b/src/spdx_tools/spdx/model/file.py index 1573f7475..27aae4ca3 100644 --- a/src/spdx_tools/spdx/model/file.py +++ b/src/spdx_tools/spdx/model/file.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from enum import Enum, auto -from typing import List, Optional, Union +from beartype.typing import List, Optional, Union from license_expression import LicenseExpression from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx_tools/spdx/model/package.py b/src/spdx_tools/spdx/model/package.py index 53bc5e9db..1cf89e607 100644 --- a/src/spdx_tools/spdx/model/package.py +++ b/src/spdx_tools/spdx/model/package.py @@ -4,8 +4,8 @@ from dataclasses import field from datetime import datetime from enum import Enum, auto -from typing import Dict, List, Optional, Union +from beartype.typing import Dict, List, Optional, Union from license_expression import LicenseExpression from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx_tools/spdx/model/relationship.py b/src/spdx_tools/spdx/model/relationship.py index 6005f7e2b..02b1326a9 100644 --- a/src/spdx_tools/spdx/model/relationship.py +++ b/src/spdx_tools/spdx/model/relationship.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto -from typing import Optional, Union + +from beartype.typing import Optional, Union from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx/model/relationship_filters.py b/src/spdx_tools/spdx/model/relationship_filters.py index be04b34b9..8858fb038 100644 --- a/src/spdx_tools/spdx/model/relationship_filters.py +++ b/src/spdx_tools/spdx/model/relationship_filters.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List from spdx_tools.spdx.model import Document, Package, Relationship, RelationshipType diff --git a/src/spdx_tools/spdx/model/snippet.py b/src/spdx_tools/spdx/model/snippet.py index 308c726cb..5a1669f4a 100644 --- a/src/spdx_tools/spdx/model/snippet.py +++ b/src/spdx_tools/spdx/model/snippet.py @@ -2,8 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from dataclasses import field -from typing import List, Optional, Tuple, Union +from beartype.typing import List, Optional, Tuple, Union from license_expression import LicenseExpression from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx_tools/spdx/parser/actor_parser.py b/src/spdx_tools/spdx/parser/actor_parser.py index 4d20f4629..734b41386 100644 --- a/src/spdx_tools/spdx/parser/actor_parser.py +++ b/src/spdx_tools/spdx/parser/actor_parser.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 import re -from typing import Match, Optional, Pattern + +from beartype.typing import Match, Optional, Pattern from spdx_tools.spdx.model import Actor, ActorType from spdx_tools.spdx.parser.error import SPDXParsingError diff --git a/src/spdx_tools/spdx/parser/error.py b/src/spdx_tools/spdx/parser/error.py index f3aaca7d0..1e58c1122 100644 --- a/src/spdx_tools/spdx/parser/error.py +++ b/src/spdx_tools/spdx/parser/error.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List class SPDXParsingError(Exception): diff --git a/src/spdx_tools/spdx/parser/json/json_parser.py b/src/spdx_tools/spdx/parser/json/json_parser.py index 0864caec6..9ca35fd85 100644 --- a/src/spdx_tools/spdx/parser/json/json_parser.py +++ b/src/spdx_tools/spdx/parser/json/json_parser.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 import json -from typing import Dict + +from beartype.typing import Dict from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py index 02e47a1b0..38ccac3ff 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/annotation_parser.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import Dict, List, Optional + +from beartype.typing import Dict, List, Optional from spdx_tools.spdx.datetime_conversions import datetime_from_str from spdx_tools.spdx.model import Actor, Annotation, AnnotationType diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py index de1eada17..5da8ff544 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/checksum_parser.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict, Optional +from beartype.typing import Dict, Optional from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import json_str_to_enum_name diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py index 1e7015c50..c530999f1 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/creation_info_parser.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import Dict, List, Optional + +from beartype.typing import Dict, List, Optional from spdx_tools.spdx.datetime_conversions import datetime_from_str from spdx_tools.spdx.model import Actor, Checksum, CreationInfo, ExternalDocumentRef, Version diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py b/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py index c5076d2bf..0733317d1 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/dict_parsing_functions.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Callable, Dict, List, Optional +from beartype.typing import Any, Callable, Dict, List, Optional from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py index 8a75de24d..c0646084f 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/extracted_licensing_info_parser.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict, List, Optional, Union +from beartype.typing import Dict, List, Optional, Union from spdx_tools.spdx.model import ExtractedLicensingInfo, SpdxNoAssertion from spdx_tools.spdx.parser.jsonlikedict.dict_parsing_functions import parse_field_or_no_assertion diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py index 53a9078db..77138ab40 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/file_parser.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict, List, Optional, Union - +from beartype.typing import Dict, List, Optional, Union from license_expression import LicenseExpression from spdx_tools.spdx.model import Checksum, File, FileType, SpdxNoAssertion, SpdxNone diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py index 9465c0c76..31a41559a 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/json_like_dict_parser.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict +from beartype.typing import Dict from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.error import SPDXParsingError diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py index de0b36cab..a7c242df2 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/license_expression_parser.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Union - +from beartype.typing import Union from license_expression import ExpressionError, LicenseExpression, Licensing from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py index fb4924a63..b395abd39 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/package_parser.py @@ -2,8 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import Dict, List, Optional, Union +from beartype.typing import Dict, List, Optional, Union from license_expression import LicenseExpression from spdx_tools.spdx.datetime_conversions import datetime_from_str diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py index 5ffc5c6e6..432dd38dc 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict, List, Optional +from beartype.typing import Dict, List, Optional from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors from spdx_tools.spdx.model import Relationship, RelationshipType diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py index 4f501608f..f00779407 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/snippet_parser.py @@ -2,8 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto -from typing import Dict, List, Optional, Tuple, Union +from beartype.typing import Dict, List, Optional, Tuple, Union from license_expression import LicenseExpression from spdx_tools.spdx.model import Snippet, SpdxNoAssertion, SpdxNone diff --git a/src/spdx_tools/spdx/parser/logger.py b/src/spdx_tools/spdx/parser/logger.py index 8a90453d8..343de7398 100644 --- a/src/spdx_tools/spdx/parser/logger.py +++ b/src/spdx_tools/spdx/parser/logger.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List class Logger: diff --git a/src/spdx_tools/spdx/parser/parsing_functions.py b/src/spdx_tools/spdx/parser/parsing_functions.py index f0e371d91..47f73951d 100644 --- a/src/spdx_tools/spdx/parser/parsing_functions.py +++ b/src/spdx_tools/spdx/parser/parsing_functions.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Dict +from beartype.typing import Any, Dict from spdx_tools.common.typing.constructor_type_errors import ConstructorTypeErrors from spdx_tools.spdx.parser.error import SPDXParsingError diff --git a/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py b/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py index 36376b128..7c70e0242 100644 --- a/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/creation_info_parser.py @@ -3,9 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 import logging import sys -from typing import Tuple from urllib.parse import urldefrag +from beartype.typing import Tuple from rdflib import RDF, RDFS, Graph, Namespace from rdflib.exceptions import UniquenessError from rdflib.term import URIRef diff --git a/src/spdx_tools/spdx/parser/rdf/file_parser.py b/src/spdx_tools/spdx/parser/rdf/file_parser.py index 83e61b4a5..22323d09c 100644 --- a/src/spdx_tools/spdx/parser/rdf/file_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/file_parser.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Union - +from beartype.typing import Union from rdflib import RDFS, BNode, Graph, URIRef from spdx_tools.spdx.model import File, FileType diff --git a/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py b/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py index 257367595..5e2b8e099 100644 --- a/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py +++ b/src/spdx_tools/spdx/parser/rdf/graph_parsing_functions.py @@ -2,8 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from enum import Enum -from typing import Any, Callable, Optional, Tuple, Type, Union +from beartype.typing import Any, Callable, Optional, Tuple, Type, Union from rdflib import RDF, Graph, URIRef from rdflib.exceptions import UniquenessError from rdflib.namespace import NamespaceManager diff --git a/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py b/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py index a55096976..64cc36755 100644 --- a/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Optional, Union - +from beartype.typing import Optional, Union from license_expression import LicenseExpression, get_spdx_licensing from rdflib import RDF, Graph from rdflib.term import BNode, Identifier, Node, URIRef diff --git a/src/spdx_tools/spdx/parser/rdf/package_parser.py b/src/spdx_tools/spdx/parser/rdf/package_parser.py index a0de0e904..668377162 100644 --- a/src/spdx_tools/spdx/parser/rdf/package_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/package_parser.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Optional, Union - +from beartype.typing import Optional, Union from rdflib import DOAP, RDFS, Graph, URIRef from rdflib.term import BNode diff --git a/src/spdx_tools/spdx/parser/rdf/rdf_parser.py b/src/spdx_tools/spdx/parser/rdf/rdf_parser.py index d6406f3f0..3856f8d59 100644 --- a/src/spdx_tools/spdx/parser/rdf/rdf_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/rdf_parser.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Dict - +from beartype.typing import Any, Dict from rdflib import RDF, Graph from spdx_tools.spdx.model import Document, RelationshipType diff --git a/src/spdx_tools/spdx/parser/rdf/snippet_parser.py b/src/spdx_tools/spdx/parser/rdf/snippet_parser.py index e59076654..d09671f60 100644 --- a/src/spdx_tools/spdx/parser/rdf/snippet_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/snippet_parser.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict, Optional, Tuple, Union - +from beartype.typing import Dict, Optional, Tuple, Union from rdflib import RDF, RDFS, Graph from rdflib.exceptions import UniquenessError from rdflib.term import BNode, Node, URIRef diff --git a/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py b/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py index d8cfef77a..ea528a434 100644 --- a/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py +++ b/src/spdx_tools/spdx/parser/tagvalue/helper_methods.py @@ -2,8 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 import re -from typing import Any, Callable, Dict, Optional +from beartype.typing import Any, Callable, Dict, Optional from ply.yacc import YaccProduction from spdx_tools.spdx.casing_tools import camel_case_to_snake_case diff --git a/src/spdx_tools/spdx/parser/tagvalue/parser.py b/src/spdx_tools/spdx/parser/tagvalue/parser.py index 623226b8f..ec843ccb9 100644 --- a/src/spdx_tools/spdx/parser/tagvalue/parser.py +++ b/src/spdx_tools/spdx/parser/tagvalue/parser.py @@ -12,8 +12,8 @@ # limitations under the License. import re -from typing import Any, Dict, List +from beartype.typing import Any, Dict, List from license_expression import get_spdx_licensing from ply import yacc from ply.yacc import LRParser diff --git a/src/spdx_tools/spdx/parser/xml/xml_parser.py b/src/spdx_tools/spdx/parser/xml/xml_parser.py index 4dd8c3aa2..f0cd77025 100644 --- a/src/spdx_tools/spdx/parser/xml/xml_parser.py +++ b/src/spdx_tools/spdx/parser/xml/xml_parser.py @@ -1,9 +1,8 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Any, Dict - import xmltodict +from beartype.typing import Any, Dict from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.error import SPDXParsingError diff --git a/src/spdx_tools/spdx/parser/yaml/yaml_parser.py b/src/spdx_tools/spdx/parser/yaml/yaml_parser.py index 021858137..1a7349eb8 100644 --- a/src/spdx_tools/spdx/parser/yaml/yaml_parser.py +++ b/src/spdx_tools/spdx/parser/yaml/yaml_parser.py @@ -1,9 +1,8 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict - import yaml +from beartype.typing import Dict from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser diff --git a/src/spdx_tools/spdx/spdx_element_utils.py b/src/spdx_tools/spdx/spdx_element_utils.py index 94d45ba44..49b466144 100644 --- a/src/spdx_tools/spdx/spdx_element_utils.py +++ b/src/spdx_tools/spdx/spdx_element_utils.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Union +from beartype.typing import List, Union from spdx_tools.spdx.model import ExternalDocumentRef, File, Package, Snippet diff --git a/src/spdx_tools/spdx/validation/actor_validator.py b/src/spdx_tools/spdx/validation/actor_validator.py index 313f7d3e1..3ae5f8656 100644 --- a/src/spdx_tools/spdx/validation/actor_validator.py +++ b/src/spdx_tools/spdx/validation/actor_validator.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List from spdx_tools.spdx.model import Actor, ActorType from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage diff --git a/src/spdx_tools/spdx/validation/annotation_validator.py b/src/spdx_tools/spdx/validation/annotation_validator.py index dbfa1bed2..3fec188c7 100644 --- a/src/spdx_tools/spdx/validation/annotation_validator.py +++ b/src/spdx_tools/spdx/validation/annotation_validator.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List from spdx_tools.spdx.model import Annotation, Document from spdx_tools.spdx.validation.actor_validator import validate_actor diff --git a/src/spdx_tools/spdx/validation/checksum_validator.py b/src/spdx_tools/spdx/validation/checksum_validator.py index 67df436ca..2a9d055c8 100644 --- a/src/spdx_tools/spdx/validation/checksum_validator.py +++ b/src/spdx_tools/spdx/validation/checksum_validator.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 import re -from typing import Dict, List + +from beartype.typing import Dict, List from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage diff --git a/src/spdx_tools/spdx/validation/creation_info_validator.py b/src/spdx_tools/spdx/validation/creation_info_validator.py index 55bac981d..79490c77c 100644 --- a/src/spdx_tools/spdx/validation/creation_info_validator.py +++ b/src/spdx_tools/spdx/validation/creation_info_validator.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID from spdx_tools.spdx.model import CreationInfo diff --git a/src/spdx_tools/spdx/validation/document_validator.py b/src/spdx_tools/spdx/validation/document_validator.py index 41e5c7d9b..b6fba74b8 100644 --- a/src/spdx_tools/spdx/validation/document_validator.py +++ b/src/spdx_tools/spdx/validation/document_validator.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List from spdx_tools.spdx.model import Document, RelationshipType from spdx_tools.spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target diff --git a/src/spdx_tools/spdx/validation/external_document_ref_validator.py b/src/spdx_tools/spdx/validation/external_document_ref_validator.py index 1dd7da0c3..52f50a665 100644 --- a/src/spdx_tools/spdx/validation/external_document_ref_validator.py +++ b/src/spdx_tools/spdx/validation/external_document_ref_validator.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List from spdx_tools.spdx.model import ExternalDocumentRef from spdx_tools.spdx.validation.checksum_validator import validate_checksum diff --git a/src/spdx_tools/spdx/validation/external_package_ref_validator.py b/src/spdx_tools/spdx/validation/external_package_ref_validator.py index e785891fb..7dd316354 100644 --- a/src/spdx_tools/spdx/validation/external_package_ref_validator.py +++ b/src/spdx_tools/spdx/validation/external_package_ref_validator.py @@ -2,9 +2,9 @@ # # SPDX-License-Identifier: Apache-2.0 import re -from typing import Dict, List import uritools +from beartype.typing import Dict, List from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory from spdx_tools.spdx.model.package import CATEGORY_TO_EXTERNAL_PACKAGE_REF_TYPES diff --git a/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py b/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py index 86df9ca77..6cca07576 100644 --- a/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py +++ b/src/spdx_tools/spdx/validation/extracted_licensing_info_validator.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 import re -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.spdx.model import ExtractedLicensingInfo from spdx_tools.spdx.validation.uri_validators import validate_url diff --git a/src/spdx_tools/spdx/validation/file_validator.py b/src/spdx_tools/spdx/validation/file_validator.py index 77cf6a5d1..a14efd4c4 100644 --- a/src/spdx_tools/spdx/validation/file_validator.py +++ b/src/spdx_tools/spdx/validation/file_validator.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.spdx.model import ChecksumAlgorithm, Document, File from spdx_tools.spdx.validation.checksum_validator import validate_checksums diff --git a/src/spdx_tools/spdx/validation/license_expression_validator.py b/src/spdx_tools/spdx/validation/license_expression_validator.py index e9b52ca7a..bce5c9eb3 100644 --- a/src/spdx_tools/spdx/validation/license_expression_validator.py +++ b/src/spdx_tools/spdx/validation/license_expression_validator.py @@ -2,8 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional, Union - +from beartype.typing import List, Optional, Union from license_expression import ExpressionError, ExpressionParseError, LicenseExpression, get_spdx_licensing from spdx_tools.spdx.model import Document, SpdxNoAssertion, SpdxNone diff --git a/src/spdx_tools/spdx/validation/package_validator.py b/src/spdx_tools/spdx/validation/package_validator.py index dc41dcf4c..4307fc8ef 100644 --- a/src/spdx_tools/spdx/validation/package_validator.py +++ b/src/spdx_tools/spdx/validation/package_validator.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.spdx.model import Document, Package, Relationship, RelationshipType from spdx_tools.spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target diff --git a/src/spdx_tools/spdx/validation/package_verification_code_validator.py b/src/spdx_tools/spdx/validation/package_verification_code_validator.py index fb79135ba..55dd1bb35 100644 --- a/src/spdx_tools/spdx/validation/package_verification_code_validator.py +++ b/src/spdx_tools/spdx/validation/package_verification_code_validator.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 import re -from typing import List + +from beartype.typing import List from spdx_tools.spdx.model import PackageVerificationCode from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage diff --git a/src/spdx_tools/spdx/validation/relationship_validator.py b/src/spdx_tools/spdx/validation/relationship_validator.py index 1f9430683..1c194ac99 100644 --- a/src/spdx_tools/spdx/validation/relationship_validator.py +++ b/src/spdx_tools/spdx/validation/relationship_validator.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List from spdx_tools.spdx.model import Document, Relationship, RelationshipType, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.validation.spdx_id_validators import validate_spdx_id diff --git a/src/spdx_tools/spdx/validation/snippet_validator.py b/src/spdx_tools/spdx/validation/snippet_validator.py index aab0e606d..8c1aed9c5 100644 --- a/src/spdx_tools/spdx/validation/snippet_validator.py +++ b/src/spdx_tools/spdx/validation/snippet_validator.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.spdx.model import Document, Snippet from spdx_tools.spdx.validation.license_expression_validator import ( diff --git a/src/spdx_tools/spdx/validation/spdx_id_validators.py b/src/spdx_tools/spdx/validation/spdx_id_validators.py index 0d78900a6..6441236a9 100644 --- a/src/spdx_tools/spdx/validation/spdx_id_validators.py +++ b/src/spdx_tools/spdx/validation/spdx_id_validators.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 import re -from typing import List + +from beartype.typing import List from spdx_tools.spdx.document_utils import get_contained_spdx_element_ids from spdx_tools.spdx.model import Document, File diff --git a/src/spdx_tools/spdx/validation/uri_validators.py b/src/spdx_tools/spdx/validation/uri_validators.py index 5b30f6b7d..d9c23f97a 100644 --- a/src/spdx_tools/spdx/validation/uri_validators.py +++ b/src/spdx_tools/spdx/validation/uri_validators.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 import re -from typing import List +from beartype.typing import List from uritools import isabsuri, urisplit url_pattern = ( diff --git a/src/spdx_tools/spdx/validation/validation_message.py b/src/spdx_tools/spdx/validation/validation_message.py index 7b4178703..2ef1ba241 100644 --- a/src/spdx_tools/spdx/validation/validation_message.py +++ b/src/spdx_tools/spdx/validation/validation_message.py @@ -4,7 +4,8 @@ from dataclasses import dataclass from enum import Enum, auto -from typing import Any, Optional + +from beartype.typing import Any, Optional class SpdxElementType(Enum): diff --git a/src/spdx_tools/spdx/writer/json/json_writer.py b/src/spdx_tools/spdx/writer/json/json_writer.py index 0b939c039..a644bd889 100644 --- a/src/spdx_tools/spdx/writer/json/json_writer.py +++ b/src/spdx_tools/spdx/writer/json/json_writer.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 import json -from typing import List + +from beartype.typing import List from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter diff --git a/src/spdx_tools/spdx/writer/rdf/annotation_writer.py b/src/spdx_tools/spdx/writer/rdf/annotation_writer.py index dd51b47e6..e973eeb0d 100644 --- a/src/spdx_tools/spdx/writer/rdf/annotation_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/annotation_writer.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict - +from beartype.typing import Dict from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef from spdx_tools.spdx.casing_tools import snake_case_to_camel_case diff --git a/src/spdx_tools/spdx/writer/rdf/file_writer.py b/src/spdx_tools/spdx/writer/rdf/file_writer.py index 649a1e6e0..679be8d22 100644 --- a/src/spdx_tools/spdx/writer/rdf/file_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/file_writer.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict - +from beartype.typing import Dict from rdflib import RDF, RDFS, Graph, Literal, URIRef from spdx_tools.spdx.casing_tools import snake_case_to_camel_case diff --git a/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py b/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py index b6acfe1ad..1057f6efd 100644 --- a/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Union - +from beartype.typing import List, Union from boolean import Expression from license_expression import ( AND, diff --git a/src/spdx_tools/spdx/writer/rdf/package_writer.py b/src/spdx_tools/spdx/writer/rdf/package_writer.py index 90d21c145..2137d0dbd 100644 --- a/src/spdx_tools/spdx/writer/rdf/package_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/package_writer.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict - +from beartype.typing import Dict from rdflib import DOAP, RDF, RDFS, XSD, BNode, Graph, Literal, URIRef from spdx_tools.spdx.casing_tools import snake_case_to_camel_case diff --git a/src/spdx_tools/spdx/writer/rdf/rdf_writer.py b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py index 360337abc..7c85613ec 100644 --- a/src/spdx_tools/spdx/writer/rdf/rdf_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict, List - +from beartype.typing import Dict, List from rdflib import DOAP, Graph from rdflib.compare import to_isomorphic diff --git a/src/spdx_tools/spdx/writer/rdf/relationship_writer.py b/src/spdx_tools/spdx/writer/rdf/relationship_writer.py index 82b5b59d5..6d49431af 100644 --- a/src/spdx_tools/spdx/writer/rdf/relationship_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/relationship_writer.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict - +from beartype.typing import Dict from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef from spdx_tools.spdx.casing_tools import snake_case_to_camel_case diff --git a/src/spdx_tools/spdx/writer/rdf/snippet_writer.py b/src/spdx_tools/spdx/writer/rdf/snippet_writer.py index f45759c9b..0b8cd4e95 100644 --- a/src/spdx_tools/spdx/writer/rdf/snippet_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/snippet_writer.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict, Optional, Tuple - +from beartype.typing import Dict, Optional, Tuple from rdflib import RDF, RDFS, BNode, Graph, Literal, URIRef from spdx_tools.spdx.model import Snippet diff --git a/src/spdx_tools/spdx/writer/rdf/writer_utils.py b/src/spdx_tools/spdx/writer/rdf/writer_utils.py index 9bca3f470..fb27aa18b 100644 --- a/src/spdx_tools/spdx/writer/rdf/writer_utils.py +++ b/src/spdx_tools/spdx/writer/rdf/writer_utils.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 import logging from datetime import datetime -from typing import Any, Dict, Optional +from beartype.typing import Any, Dict, Optional from rdflib import Graph, Literal from rdflib.term import Node diff --git a/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py b/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py index 0be7663c4..5c9bd85ee 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string from spdx_tools.spdx.model import Annotation diff --git a/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py b/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py index 9e87b0925..6987702d5 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string from spdx_tools.spdx.model import CreationInfo diff --git a/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py b/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py index 89734c8c8..356722859 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx.model import ExtractedLicensingInfo from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value diff --git a/src/spdx_tools/spdx/writer/tagvalue/file_writer.py b/src/spdx_tools/spdx/writer/tagvalue/file_writer.py index 8848d9aae..d3f3d85e3 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/file_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/file_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx.model import File from spdx_tools.spdx.writer.tagvalue.checksum_writer import write_checksum_to_tag_value diff --git a/src/spdx_tools/spdx/writer/tagvalue/package_writer.py b/src/spdx_tools/spdx/writer/tagvalue/package_writer.py index d690773e0..8ba0f8f0e 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/package_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/package_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx.datetime_conversions import datetime_to_iso_string from spdx_tools.spdx.model import Package, PackageVerificationCode diff --git a/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py b/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py index a46f0c7cc..a9cb9b754 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx.model import Relationship from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_text_value, write_value diff --git a/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py b/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py index de8ce16d4..f5cd2e84d 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx.model import Snippet from spdx_tools.spdx.writer.tagvalue.tagvalue_writer_helper_functions import write_range, write_text_value, write_value diff --git a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py index 37a54cae3..d82a1213e 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import List, TextIO +from beartype.typing import List, TextIO from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.model import Document diff --git a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py index 2e638f943..458d76711 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py @@ -8,8 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, Callable, Dict, List, Optional, TextIO, Tuple, Union - +from beartype.typing import Any, Callable, Dict, List, Optional, TextIO, Tuple, Union from license_expression import LicenseExpression from spdx_tools.spdx.model import ( diff --git a/src/spdx_tools/spdx/writer/xml/xml_writer.py b/src/spdx_tools/spdx/writer/xml/xml_writer.py index 73070b123..70484da4b 100644 --- a/src/spdx_tools/spdx/writer/xml/xml_writer.py +++ b/src/spdx_tools/spdx/writer/xml/xml_writer.py @@ -1,9 +1,8 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List - import xmltodict +from beartype.typing import List from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter diff --git a/src/spdx_tools/spdx/writer/yaml/yaml_writer.py b/src/spdx_tools/spdx/writer/yaml/yaml_writer.py index 4c354a157..5211fd3de 100644 --- a/src/spdx_tools/spdx/writer/yaml/yaml_writer.py +++ b/src/spdx_tools/spdx/writer/yaml/yaml_writer.py @@ -1,9 +1,8 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List - import yaml +from beartype.typing import List from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/actor.py b/src/spdx_tools/spdx3/bump_from_spdx2/actor.py index 6a84af7a1..3fac60412 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/actor.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/actor.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalIdentifierType, Organization, Person, Tool from spdx_tools.spdx3.payload import Payload diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/bump_utils.py b/src/spdx_tools/spdx3/bump_from_spdx2/bump_utils.py index e45b05909..f4b6a4bf9 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/bump_utils.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/bump_utils.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Optional, Union +from beartype.typing import Optional, Union from spdx_tools.spdx.model.spdx_no_assertion import SpdxNoAssertion from spdx_tools.spdx.model.spdx_none import SpdxNone diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py index 30532b463..17a957c4f 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List - +from beartype.typing import List from semantic_version import Version from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py b/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py index 1e496aa16..41360ffa4 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/external_document_ref.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Tuple +from beartype.typing import List, Tuple from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum from spdx_tools.spdx3.model import ExternalMap, Hash, NamespaceMap diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/file.py b/src/spdx_tools/spdx3/bump_from_spdx2/file.py index 93f8495a7..c1f8226aa 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/file.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/file.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py b/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py index 6b65b6642..ddd04ecdd 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Union - +from beartype.typing import List, Union from license_expression import ( AND, OR, diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index 814e1f849..bd0a07d11 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional, Union +from beartype.typing import List, Optional, Union from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py index d406713e6..ee5d35418 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 import logging import sys -from typing import Dict, List, Optional, Tuple, Union + +from beartype.typing import Dict, List, Optional, Tuple, Union from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import ( diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index 221c96926..7810357a5 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional, Tuple +from beartype.typing import List, Optional, Tuple from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion diff --git a/src/spdx_tools/spdx3/clitools/pyspdxtools3.py b/src/spdx_tools/spdx3/clitools/pyspdxtools3.py index 3a9b45a7a..9dd21a5d1 100644 --- a/src/spdx_tools/spdx3/clitools/pyspdxtools3.py +++ b/src/spdx_tools/spdx3/clitools/pyspdxtools3.py @@ -2,9 +2,9 @@ # # SPDX-License-Identifier: Apache-2.0 import sys -from typing import List import click +from beartype.typing import List from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document from spdx_tools.spdx3.payload import Payload diff --git a/src/spdx_tools/spdx3/model/agent.py b/src/spdx_tools/spdx3/model/agent.py index 438b9de89..0470ed304 100644 --- a/src/spdx_tools/spdx3/model/agent.py +++ b/src/spdx_tools/spdx3/model/agent.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/ai/ai_package.py b/src/spdx_tools/spdx3/model/ai/ai_package.py index 03a698768..9d5dd4114 100644 --- a/src/spdx_tools/spdx3/model/ai/ai_package.py +++ b/src/spdx_tools/spdx3/model/ai/ai_package.py @@ -4,7 +4,8 @@ from dataclasses import field from datetime import datetime from enum import Enum, auto -from typing import Dict, List, Optional + +from beartype.typing import Dict, List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/annotation.py b/src/spdx_tools/spdx3/model/annotation.py index 14bc40d9e..9a016cfe8 100644 --- a/src/spdx_tools/spdx3/model/annotation.py +++ b/src/spdx_tools/spdx3/model/annotation.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from enum import Enum, auto -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/artifact.py b/src/spdx_tools/spdx3/model/artifact.py index bb88fea41..0fccec89c 100644 --- a/src/spdx_tools/spdx3/model/artifact.py +++ b/src/spdx_tools/spdx3/model/artifact.py @@ -4,7 +4,8 @@ from abc import abstractmethod from dataclasses import field from datetime import datetime -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.spdx3.model import Element diff --git a/src/spdx_tools/spdx3/model/bom.py b/src/spdx_tools/spdx3/model/bom.py index 2772eb54d..332d31652 100644 --- a/src/spdx_tools/spdx3/model/bom.py +++ b/src/spdx_tools/spdx3/model/bom.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/build/build.py b/src/spdx_tools/spdx3/model/build/build.py index 3294c95ea..8d784e819 100644 --- a/src/spdx_tools/spdx3/model/build/build.py +++ b/src/spdx_tools/spdx3/model/build/build.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from datetime import datetime -from typing import Dict, List, Optional + +from beartype.typing import Dict, List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/bundle.py b/src/spdx_tools/spdx3/model/bundle.py index 04ead471e..c90352308 100644 --- a/src/spdx_tools/spdx3/model/bundle.py +++ b/src/spdx_tools/spdx3/model/bundle.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/creation_info.py b/src/spdx_tools/spdx3/model/creation_info.py index 40f02abea..615a30445 100644 --- a/src/spdx_tools/spdx3/model/creation_info.py +++ b/src/spdx_tools/spdx3/model/creation_info.py @@ -2,8 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import List, Optional +from beartype.typing import List, Optional from semantic_version import Version from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py index e6da96eb5..774a3bef2 100644 --- a/src/spdx_tools/spdx3/model/dataset/dataset.py +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -4,7 +4,8 @@ from dataclasses import field from datetime import datetime from enum import Enum, auto -from typing import Dict, List, Optional + +from beartype.typing import Dict, List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/element.py b/src/spdx_tools/spdx3/model/element.py index 3b75dcf8a..f5ec4790e 100644 --- a/src/spdx_tools/spdx3/model/element.py +++ b/src/spdx_tools/spdx3/model/element.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from abc import ABC, abstractmethod from dataclasses import field -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalReference, IntegrityMethod diff --git a/src/spdx_tools/spdx3/model/external_identifier.py b/src/spdx_tools/spdx3/model/external_identifier.py index e44d63d89..a7ae2a8d2 100644 --- a/src/spdx_tools/spdx3/model/external_identifier.py +++ b/src/spdx_tools/spdx3/model/external_identifier.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from enum import Enum, auto -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/external_map.py b/src/spdx_tools/spdx3/model/external_map.py index 91ec7dd2c..ab88a49e2 100644 --- a/src/spdx_tools/spdx3/model/external_map.py +++ b/src/spdx_tools/spdx3/model/external_map.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from dataclasses import field -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/external_reference.py b/src/spdx_tools/spdx3/model/external_reference.py index 127253595..5e29aa583 100644 --- a/src/spdx_tools/spdx3/model/external_reference.py +++ b/src/spdx_tools/spdx3/model/external_reference.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from enum import Enum, auto -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/hash.py b/src/spdx_tools/spdx3/model/hash.py index 611c04393..42ef4ff4d 100644 --- a/src/spdx_tools/spdx3/model/hash.py +++ b/src/spdx_tools/spdx3/model/hash.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from enum import Enum, auto -from typing import Optional + +from beartype.typing import Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/integrity_method.py b/src/spdx_tools/spdx3/model/integrity_method.py index aac00ab11..17fefef16 100644 --- a/src/spdx_tools/spdx3/model/integrity_method.py +++ b/src/spdx_tools/spdx3/model/integrity_method.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from abc import ABC, abstractmethod -from typing import Optional + +from beartype.typing import Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/licensing/conjunctive_license_set.py b/src/spdx_tools/spdx3/model/licensing/conjunctive_license_set.py index e8e4f5611..fe5605761 100644 --- a/src/spdx_tools/spdx3/model/licensing/conjunctive_license_set.py +++ b/src/spdx_tools/spdx3/model/licensing/conjunctive_license_set.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/licensing/custom_license.py b/src/spdx_tools/spdx3/model/licensing/custom_license.py index 773081f8d..4617a18db 100644 --- a/src/spdx_tools/spdx3/model/licensing/custom_license.py +++ b/src/spdx_tools/spdx3/model/licensing/custom_license.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/licensing/custom_license_addition.py b/src/spdx_tools/spdx3/model/licensing/custom_license_addition.py index 707a28883..b50d27770 100644 --- a/src/spdx_tools/spdx3/model/licensing/custom_license_addition.py +++ b/src/spdx_tools/spdx3/model/licensing/custom_license_addition.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/licensing/disjunctive_license_set.py b/src/spdx_tools/spdx3/model/licensing/disjunctive_license_set.py index 00d63aee7..a5ac3bdc8 100644 --- a/src/spdx_tools/spdx3/model/licensing/disjunctive_license_set.py +++ b/src/spdx_tools/spdx3/model/licensing/disjunctive_license_set.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List +from beartype.typing import List from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/licensing/license.py b/src/spdx_tools/spdx3/model/licensing/license.py index 3d1c87822..e2fd625ff 100644 --- a/src/spdx_tools/spdx3/model/licensing/license.py +++ b/src/spdx_tools/spdx3/model/licensing/license.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod from dataclasses import field -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.spdx3.model.licensing.any_license_info import AnyLicenseInfo diff --git a/src/spdx_tools/spdx3/model/licensing/license_addition.py b/src/spdx_tools/spdx3/model/licensing/license_addition.py index cb7e7d755..e3669b5cb 100644 --- a/src/spdx_tools/spdx3/model/licensing/license_addition.py +++ b/src/spdx_tools/spdx3/model/licensing/license_addition.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from abc import ABC, abstractmethod from dataclasses import field -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties diff --git a/src/spdx_tools/spdx3/model/licensing/listed_license.py b/src/spdx_tools/spdx3/model/licensing/listed_license.py index e438ac4a0..2c0b02b3d 100644 --- a/src/spdx_tools/spdx3/model/licensing/listed_license.py +++ b/src/spdx_tools/spdx3/model/licensing/listed_license.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/licensing/listed_license_exception.py b/src/spdx_tools/spdx3/model/licensing/listed_license_exception.py index 56ddaa897..799fcedae 100644 --- a/src/spdx_tools/spdx3/model/licensing/listed_license_exception.py +++ b/src/spdx_tools/spdx3/model/licensing/listed_license_exception.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py index eccc913e9..f5181a616 100644 --- a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py +++ b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from enum import Enum, auto -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/namespace_map.py b/src/spdx_tools/spdx3/model/namespace_map.py index e87f62810..88ad49bf8 100644 --- a/src/spdx_tools/spdx3/model/namespace_map.py +++ b/src/spdx_tools/spdx3/model/namespace_map.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Optional +from beartype.typing import Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/organization.py b/src/spdx_tools/spdx3/model/organization.py index 399079560..f896b2b33 100644 --- a/src/spdx_tools/spdx3/model/organization.py +++ b/src/spdx_tools/spdx3/model/organization.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/person.py b/src/spdx_tools/spdx3/model/person.py index 266992cdf..b06e263db 100644 --- a/src/spdx_tools/spdx3/model/person.py +++ b/src/spdx_tools/spdx3/model/person.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index 9a207add4..04550b419 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -4,7 +4,8 @@ from dataclasses import field from datetime import datetime from enum import Enum, auto -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py index 2b58d6385..f480e961b 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py index cf3b104e0..fb30a215c 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py index 820e7fe52..cde6445d6 100644 --- a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py index fdbd8a337..6ed309047 100644 --- a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from enum import Enum, auto -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py index 9341eb6d3..e72f6c30f 100644 --- a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from enum import Enum, auto -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py index 152ba6c62..014190770 100644 --- a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from datetime import datetime -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py index bddf492dd..79a495bb9 100644 --- a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py index 9ddb8d10c..659ea747f 100644 --- a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from enum import Enum, auto -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py index 29edc5074..a24db0156 100644 --- a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py index 342ff3fd4..8b5c0fc68 100644 --- a/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_vuln_assessment_relationship.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod -from typing import Optional + +from beartype.typing import Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.spdx3.model.security.vuln_assessment_relationship import VulnAssessmentRelationship diff --git a/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py index b97dd0c91..f20303743 100644 --- a/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vuln_assessment_relationship.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod from datetime import datetime -from typing import Optional + +from beartype.typing import Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.spdx3.model import Relationship diff --git a/src/spdx_tools/spdx3/model/security/vulnerability.py b/src/spdx_tools/spdx3/model/security/vulnerability.py index bae08afe3..1daa006a6 100644 --- a/src/spdx_tools/spdx3/model/security/vulnerability.py +++ b/src/spdx_tools/spdx3/model/security/vulnerability.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py index 22918fda2..0651aaadf 100644 --- a/src/spdx_tools/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py index 0becb4f02..2b20ba398 100644 --- a/src/spdx_tools/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/software/sbom.py b/src/spdx_tools/spdx3/model/software/sbom.py index c720bc198..ff702953f 100644 --- a/src/spdx_tools/spdx3/model/software/sbom.py +++ b/src/spdx_tools/spdx3/model/software/sbom.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from dataclasses import field from enum import Enum, auto -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py index b3d955a20..4dc5ac6e3 100644 --- a/src/spdx_tools/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/software/software_artifact.py b/src/spdx_tools/spdx3/model/software/software_artifact.py index d3dd2f9e6..582c71613 100644 --- a/src/spdx_tools/spdx3/model/software/software_artifact.py +++ b/src/spdx_tools/spdx3/model/software/software_artifact.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.spdx3.model import Artifact diff --git a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py index 08cfc3d2c..1ce96aeb7 100644 --- a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py +++ b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from enum import Enum, auto -from typing import List, Optional + +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/software_agent.py b/src/spdx_tools/spdx3/model/software_agent.py index 1b5c7292a..50fb57540 100644 --- a/src/spdx_tools/spdx3/model/software_agent.py +++ b/src/spdx_tools/spdx3/model/software_agent.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/spdx_collection.py b/src/spdx_tools/spdx3/model/spdx_collection.py index fcb05966f..65c28951a 100644 --- a/src/spdx_tools/spdx3/model/spdx_collection.py +++ b/src/spdx_tools/spdx3/model/spdx_collection.py @@ -3,7 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod from dataclasses import field -from typing import List + +from beartype.typing import List from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.spdx3.model import Element, ExternalMap, NamespaceMap diff --git a/src/spdx_tools/spdx3/model/spdx_document.py b/src/spdx_tools/spdx3/model/spdx_document.py index effc46f23..43fcb3d6b 100644 --- a/src/spdx_tools/spdx3/model/spdx_document.py +++ b/src/spdx_tools/spdx3/model/spdx_document.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/tool.py b/src/spdx_tools/spdx3/model/tool.py index 40efc4514..bc8447c1f 100644 --- a/src/spdx_tools/spdx3/model/tool.py +++ b/src/spdx_tools/spdx3/model/tool.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import List, Optional +from beartype.typing import List, Optional from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/payload.py b/src/spdx_tools/spdx3/payload.py index 911709a24..17bc78c91 100644 --- a/src/spdx_tools/spdx3/payload.py +++ b/src/spdx_tools/spdx3/payload.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Dict +from beartype.typing import Dict from spdx_tools.spdx3.model import Element diff --git a/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py index 07613bb6b..e7b3c8776 100644 --- a/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py +++ b/src/spdx_tools/spdx3/validation/json_ld/shacl_validation.py @@ -1,8 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import Optional - +from beartype.typing import Optional from pyshacl import validate from rdflib import Graph diff --git a/src/spdx_tools/spdx3/writer/console/agent_writer.py b/src/spdx_tools/spdx3/writer/console/agent_writer.py index cd46ff703..a1c12a9e0 100644 --- a/src/spdx_tools/spdx3/writer/console/agent_writer.py +++ b/src/spdx_tools/spdx3/writer/console/agent_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import Agent, Organization, Person, SoftwareAgent from spdx_tools.spdx3.writer.console.element_writer import write_element_properties diff --git a/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py b/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py index 0cebdf4f4..025ae613a 100644 --- a/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py +++ b/src/spdx_tools/spdx3/writer/console/ai/ai_package_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model.ai import AIPackage from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/annotation_writer.py b/src/spdx_tools/spdx3/writer/console/annotation_writer.py index 8f5ce6c1d..3261a69bd 100644 --- a/src/spdx_tools/spdx3/writer/console/annotation_writer.py +++ b/src/spdx_tools/spdx3/writer/console/annotation_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import Annotation from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/artifact_writer.py b/src/spdx_tools/spdx3/writer/console/artifact_writer.py index 13467f289..f55d29e05 100644 --- a/src/spdx_tools/spdx3/writer/console/artifact_writer.py +++ b/src/spdx_tools/spdx3/writer/console/artifact_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import Artifact from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/bom_writer.py b/src/spdx_tools/spdx3/writer/console/bom_writer.py index c6e0f71ec..04fcb283d 100644 --- a/src/spdx_tools/spdx3/writer/console/bom_writer.py +++ b/src/spdx_tools/spdx3/writer/console/bom_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import Bom from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle diff --git a/src/spdx_tools/spdx3/writer/console/build/build_writer.py b/src/spdx_tools/spdx3/writer/console/build/build_writer.py index 77c3d47f7..3edc9c6fb 100644 --- a/src/spdx_tools/spdx3/writer/console/build/build_writer.py +++ b/src/spdx_tools/spdx3/writer/console/build/build_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model.build import Build from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/bundle_writer.py b/src/spdx_tools/spdx3/writer/console/bundle_writer.py index 2a7fc8d78..5930db5ee 100644 --- a/src/spdx_tools/spdx3/writer/console/bundle_writer.py +++ b/src/spdx_tools/spdx3/writer/console/bundle_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import Bundle from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/console.py b/src/spdx_tools/spdx3/writer/console/console.py index 30bf024da..a2ec81ed5 100644 --- a/src/spdx_tools/spdx3/writer/console/console.py +++ b/src/spdx_tools/spdx3/writer/console/console.py @@ -2,7 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 from enum import Enum -from typing import Optional, TextIO, Union + +from beartype.typing import Optional, TextIO, Union def write_value(tag: str, value: Optional[Union[bool, str, dict, list, Enum]], out: TextIO, indent: bool = False): diff --git a/src/spdx_tools/spdx3/writer/console/creation_info_writer.py b/src/spdx_tools/spdx3/writer/console/creation_info_writer.py index 3f357f677..c91e6781d 100644 --- a/src/spdx_tools/spdx3/writer/console/creation_info_writer.py +++ b/src/spdx_tools/spdx3/writer/console/creation_info_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import CreationInfo from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py b/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py index 363ef71fb..91131240a 100644 --- a/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py +++ b/src/spdx_tools/spdx3/writer/console/dataset/dataset_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model.dataset import Dataset from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/element_writer.py b/src/spdx_tools/spdx3/writer/console/element_writer.py index c790de6bd..6614279f1 100644 --- a/src/spdx_tools/spdx3/writer/console/element_writer.py +++ b/src/spdx_tools/spdx3/writer/console/element_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import Element from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py b/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py index 90327b9e9..40f2d0e97 100644 --- a/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py +++ b/src/spdx_tools/spdx3/writer/console/external_identifier_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import ExternalIdentifier from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/external_map_writer.py b/src/spdx_tools/spdx3/writer/console/external_map_writer.py index 1b53a1024..41f59dc5d 100644 --- a/src/spdx_tools/spdx3/writer/console/external_map_writer.py +++ b/src/spdx_tools/spdx3/writer/console/external_map_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import ExternalMap from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/external_reference_writer.py b/src/spdx_tools/spdx3/writer/console/external_reference_writer.py index 7deb0b620..fa6cc79eb 100644 --- a/src/spdx_tools/spdx3/writer/console/external_reference_writer.py +++ b/src/spdx_tools/spdx3/writer/console/external_reference_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import ExternalReference from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/hash_writer.py b/src/spdx_tools/spdx3/writer/console/hash_writer.py index b3a722daa..970a49b56 100644 --- a/src/spdx_tools/spdx3/writer/console/hash_writer.py +++ b/src/spdx_tools/spdx3/writer/console/hash_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import Hash from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py b/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py index 2e3d4dfe5..df233c997 100644 --- a/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py +++ b/src/spdx_tools/spdx3/writer/console/integrity_method_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import IntegrityMethod from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/lifecycle_scoped_relationship_writer.py b/src/spdx_tools/spdx3/writer/console/lifecycle_scoped_relationship_writer.py index e71ab6b9f..5710ae6e8 100644 --- a/src/spdx_tools/spdx3/writer/console/lifecycle_scoped_relationship_writer.py +++ b/src/spdx_tools/spdx3/writer/console/lifecycle_scoped_relationship_writer.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import LifecycleScopedRelationship from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py b/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py index 8eeed3efe..d83ccb05a 100644 --- a/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py +++ b/src/spdx_tools/spdx3/writer/console/namespace_map_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import NamespaceMap from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/payload_writer.py b/src/spdx_tools/spdx3/writer/console/payload_writer.py index 95ea3f21a..34532f364 100644 --- a/src/spdx_tools/spdx3/writer/console/payload_writer.py +++ b/src/spdx_tools/spdx3/writer/console/payload_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import ( Annotation, diff --git a/src/spdx_tools/spdx3/writer/console/relationship_writer.py b/src/spdx_tools/spdx3/writer/console/relationship_writer.py index c30f89a63..1a8b16a3e 100644 --- a/src/spdx_tools/spdx3/writer/console/relationship_writer.py +++ b/src/spdx_tools/spdx3/writer/console/relationship_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import Relationship from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/software/file_writer.py b/src/spdx_tools/spdx3/writer/console/software/file_writer.py index d76ca46b6..ec631f024 100644 --- a/src/spdx_tools/spdx3/writer/console/software/file_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/file_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model.software import File from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties diff --git a/src/spdx_tools/spdx3/writer/console/software/package_writer.py b/src/spdx_tools/spdx3/writer/console/software/package_writer.py index 83905de55..1f66f989b 100644 --- a/src/spdx_tools/spdx3/writer/console/software/package_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/package_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model.software import Package from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties diff --git a/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py b/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py index 039d55cc2..2e34a6b00 100644 --- a/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/sbom_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model.software import Sbom from spdx_tools.spdx3.writer.console.bom_writer import write_bom diff --git a/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py b/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py index 19b7c6a27..b0ea7bbc7 100644 --- a/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/snippet_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model.software import Snippet from spdx_tools.spdx3.writer.console.artifact_writer import write_artifact_properties diff --git a/src/spdx_tools/spdx3/writer/console/software/software_dependency_relationship_writer.py b/src/spdx_tools/spdx3/writer/console/software/software_dependency_relationship_writer.py index e05599525..8064c76a1 100644 --- a/src/spdx_tools/spdx3/writer/console/software/software_dependency_relationship_writer.py +++ b/src/spdx_tools/spdx3/writer/console/software/software_dependency_relationship_writer.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model.software import SoftwareDependencyRelationship from spdx_tools.spdx3.writer.console.console import write_value diff --git a/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py b/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py index 242cae7bb..7654329b2 100644 --- a/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py +++ b/src/spdx_tools/spdx3/writer/console/spdx_collection_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import ElementCollection from spdx_tools.spdx3.writer.console.element_writer import write_element_properties diff --git a/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py b/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py index 15f3e57f7..8c2cdf649 100644 --- a/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py +++ b/src/spdx_tools/spdx3/writer/console/spdx_document_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import SpdxDocument from spdx_tools.spdx3.writer.console.bundle_writer import write_bundle diff --git a/src/spdx_tools/spdx3/writer/console/tool_writer.py b/src/spdx_tools/spdx3/writer/console/tool_writer.py index 35824a778..23eeb6a1a 100644 --- a/src/spdx_tools/spdx3/writer/console/tool_writer.py +++ b/src/spdx_tools/spdx3/writer/console/tool_writer.py @@ -8,7 +8,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import TextIO +from beartype.typing import TextIO from spdx_tools.spdx3.model import Tool from spdx_tools.spdx3.writer.console.element_writer import write_element_properties diff --git a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py index ff6f9f1a6..865053b71 100644 --- a/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py +++ b/src/spdx_tools/spdx3/writer/json_ld/json_ld_converter.py @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 from datetime import datetime from enum import Enum -from typing import Any, List +from beartype.typing import Any, List from semantic_version import Version from spdx_tools.spdx3.model.creation_info import CreationInfo From f481c16d23df644749d5c4c4cd3c044e467ec671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 12 Jun 2023 09:04:46 +0200 Subject: [PATCH 271/354] [issue-692] add test for the example code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- tests/spdx/examples/__init__.py | 0 .../test_spdx2_document_from_scratch.py | 149 ++++++++++++++++++ 2 files changed, 149 insertions(+) create mode 100644 tests/spdx/examples/__init__.py create mode 100644 tests/spdx/examples/test_spdx2_document_from_scratch.py diff --git a/tests/spdx/examples/__init__.py b/tests/spdx/examples/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/spdx/examples/test_spdx2_document_from_scratch.py b/tests/spdx/examples/test_spdx2_document_from_scratch.py new file mode 100644 index 000000000..538610bb6 --- /dev/null +++ b/tests/spdx/examples/test_spdx2_document_from_scratch.py @@ -0,0 +1,149 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import logging +from datetime import datetime +from typing import List + +from license_expression import get_spdx_licensing + +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Checksum, + ChecksumAlgorithm, + CreationInfo, + Document, + ExternalPackageRef, + ExternalPackageRefCategory, + File, + FileType, + Package, + PackagePurpose, + PackageVerificationCode, + Relationship, + RelationshipType, +) +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage + +# This example shows how to use the spdx-tools to create an SPDX document from scratch, +# validate it and write it to a file. + + +def test_spdx2_document_from_scratch(): + # First up, we need general information about the creation of the document, summarised by the CreationInfo class. + creation_info = CreationInfo( + spdx_version="SPDX-2.3", + spdx_id="SPDXRef-DOCUMENT", + name="document name", + data_license="CC0-1.0", + document_namespace="https://some.namespace", + creators=[Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com")], + created=datetime(2022, 1, 1), + ) + + # creation_info is the only required property of the Document class (have a look there!), + # the rest are optional lists. + # So, we are set up to create a new document instance. + document = Document(creation_info) + + # The document currently does not describe anything. Let's create a package that we can add to it. + # The Package class has quite a few properties (have a look there!), + # but only name, spdx_id and download_location are mandatory in SPDX v2.3. + package = Package( + name="package name", + spdx_id="SPDXRef-Package", + download_location="https://download.com", + version="2.2.1", + file_name="./foo.bar", + supplier=Actor(ActorType.PERSON, "Jane Doe", "jane.doe@example.com"), + originator=Actor(ActorType.ORGANIZATION, "some organization", "contact@example.com"), + files_analyzed=True, + verification_code=PackageVerificationCode( + value="d6a770ba38583ed4bb4525bd96e50461655d2758", excluded_files=["./some.file"] + ), + checksums=[ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), + Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), + ], + license_concluded=get_spdx_licensing().parse("GPL-2.0-only OR MIT"), + license_info_from_files=[get_spdx_licensing().parse("GPL-2.0-only"), get_spdx_licensing().parse("MIT")], + license_declared=get_spdx_licensing().parse("GPL-2.0-only AND MIT"), + license_comment="license comment", + copyright_text="Copyright 2022 Jane Doe", + description="package description", + attribution_texts=["package attribution"], + primary_package_purpose=PackagePurpose.LIBRARY, + release_date=datetime(2015, 1, 1), + external_references=[ + ExternalPackageRef( + category=ExternalPackageRefCategory.OTHER, + reference_type="http://reference.type", + locator="reference/locator", + comment="external reference comment", + ) + ], + ) + + # Now that we have a package defined, we can add it to the document's package property. + document.packages = [package] + + # A DESCRIBES relationship asserts that the document indeed describes the package. + describes_relationship = Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package") + document.relationships = [describes_relationship] + + # Let's add two files. Have a look at the file class for all possible properties a file can have. + file1 = File( + name="./package/file1.py", + spdx_id="SPDXRef-File1", + file_types=[FileType.SOURCE], + checksums=[ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), + Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), + ], + license_concluded=get_spdx_licensing().parse("MIT"), + license_info_in_file=[get_spdx_licensing().parse("MIT")], + copyright_text="Copyright 2022 Jane Doe", + ) + file2 = File( + name="./package/file2.py", + spdx_id="SPDXRef-File2", + checksums=[ + Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2759"), + ], + license_concluded=get_spdx_licensing().parse("GPL-2.0-only"), + ) + + # Assuming the package contains those two files, we create two CONTAINS relationships. + contains_relationship1 = Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File1") + contains_relationship2 = Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File2") + + # This library uses run-time type checks when assigning properties. + # Because in-place alterations like .append() circumvent these checks, we don't use them here. + document.relationships += [contains_relationship1, contains_relationship2] + document.files += [file1, file2] + + # We now have created a document with basic creation information, describing a package that contains two files. + # You can also add Annotations, Snippets and ExtractedLicensingInfo + # to the document in an analogous manner to the above. + # Have a look at their respective classes if you are unsure about their properties. + assert len(document.packages) == 1 + assert len(document.files) == 2 + assert len(document.relationships) == 3 + assert len(document.snippets) == 0 + assert len(document.annotations) == 0 + assert len(document.extracted_licensing_info) == 0 + + # This library provides comprehensive validation against the SPDX specification. + # Note that details of the validation depend on the SPDX version of the document. + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) + + # You can have a look at each entry's message and context (like spdx_id, parent_id, full_element) + # which will help you pinpoint the location of the invalidity. + for message in validation_messages: + logging.warning(message.validation_message) + logging.warning(message.context) + + # If the document is valid, validation_messages will be empty. + assert validation_messages == [] From bc78c2b07b8bb08dc115a9aedfd29aacf3bd387a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 14 Jun 2023 08:55:09 +0200 Subject: [PATCH 272/354] [issue-426] update model: decision and justification type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to 7ecb523ea152ed40c09ff6451b47ceefad148164 Signed-off-by: Armin Tänzer --- README.md | 2 +- .../spdx3/model/security/ssvc_vuln_assessment_relationship.py | 4 ++-- .../security/vex_not_affected_vuln_assessment_relationship.py | 4 ++-- tests/spdx3/fixtures.py | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 828c62a4f..73da3ea27 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ additional installation of optional dependencies * Serialize to JSON-LD See [Quickstart to SPDX 3.0](#quickstart-to-spdx-30) below. -The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: ea2e1446ae937c6722b3f599f95813f8747d54b4). +The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 7ecb523ea152ed40c09ff6451b47ceefad148164). # Installation diff --git a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py index e72f6c30f..22105e379 100644 --- a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py @@ -28,7 +28,7 @@ class SsvcDecisionType(Enum): @dataclass_with_properties class SsvcVulnAssessmentRelationship(VulnAssessmentRelationship): - decision: SsvcDecisionType = None + decision_type: SsvcDecisionType = None def __init__( self, @@ -36,7 +36,7 @@ def __init__( from_element: str, relationship_type: RelationshipType, to: List[str], - decision: SsvcDecisionType, + decision_type: SsvcDecisionType, creation_info: Optional[CreationInfo] = None, name: Optional[str] = None, summary: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py index 659ea747f..ea4f5674c 100644 --- a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py @@ -29,7 +29,7 @@ class VexJustificationType(Enum): @dataclass_with_properties class VexNotAffectedVulnAssessmentRelationship(VexVulnAssessmentRelationship): - justification: Optional[VexJustificationType] = None + justification_type: Optional[VexJustificationType] = None impact_statement: Optional[str] = None impact_statement_time: Optional[datetime] = None @@ -58,7 +58,7 @@ def __init__( withdrawn_time: Optional[datetime] = None, vex_version: Optional[str] = None, status_notes: Optional[str] = None, - justification: Optional[VexJustificationType] = None, + justification_type: Optional[VexJustificationType] = None, impact_statement: Optional[str] = None, impact_statement_time: Optional[datetime] = None, ): diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 64511a1eb..937a4226f 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -314,7 +314,7 @@ def listed_license_fixture( } SSVC_VULN_ASSESSMENT_RELATIONSHIP_DICT = { - "decision": SsvcDecisionType.ACT, + "decision_type": SsvcDecisionType.ACT, "relationship_type": RelationshipType.HAS_SSVC_ASSESSMENT_FOR, } @@ -337,7 +337,7 @@ def listed_license_fixture( } VEX_NOT_AFFECTED_VULN_ASSESSMENT_RELATIONSHIP_DICT = { - "justification": VexJustificationType.COMPONENT_NOT_PRESENT, + "justification_type": VexJustificationType.COMPONENT_NOT_PRESENT, "impact_statement": "Not using this vulnerable part of this library.", "impact_statement_time": datetime(2015, 10, 15), "relationship_type": RelationshipType.DOES_NOT_AFFECT, From 72296337e098bb4ac24efb20e2d39059783ea077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 14 Jun 2023 09:01:24 +0200 Subject: [PATCH 273/354] [issue-426] update model: ExternalIdentifier and Relationship types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to cb39f85bed80d432acd2c177fb6480efb8fc73ae Signed-off-by: Armin Tänzer --- README.md | 2 +- .../spdx3/model/external_identifier.py | 2 + src/spdx_tools/spdx3/model/relationship.py | 42 +++++++++---------- tests/spdx3/fixtures.py | 10 ++--- 4 files changed, 27 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 73da3ea27..12ca43cbe 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ additional installation of optional dependencies * Serialize to JSON-LD See [Quickstart to SPDX 3.0](#quickstart-to-spdx-30) below. -The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 7ecb523ea152ed40c09ff6451b47ceefad148164). +The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: cb39f85bed80d432acd2c177fb6480efb8fc73ae). # Installation diff --git a/src/spdx_tools/spdx3/model/external_identifier.py b/src/spdx_tools/spdx3/model/external_identifier.py index a7ae2a8d2..ee458151e 100644 --- a/src/spdx_tools/spdx3/model/external_identifier.py +++ b/src/spdx_tools/spdx3/model/external_identifier.py @@ -13,9 +13,11 @@ class ExternalIdentifierType(Enum): CPE22 = auto() CPE23 = auto() + CVE = auto() EMAIL = auto() GITOID = auto() PURL = auto() + SECURITY_OTHER = auto() SWHID = auto() SWID = auto() URL_SCHEME = auto() diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index 04550b419..85c29700d 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -13,12 +13,20 @@ class RelationshipType(Enum): + AFFECTS = auto() AMENDS = auto() ANCESTOR = auto() AVAILABLE_FROM = auto() + BUILD_CONFIG_OF = auto() BUILD_DEPENDENCY = auto() + BUILD_HOST_OF = auto() + BUILD_INPUT_OF = auto() + BUILD_INVOKED_BY = auto() + BUILD_ON_BEHALF_OF = auto() + BUILD_OUTPUT_OF = auto() BUILD_TOOL = auto() CONTAINS = auto() + COORDINATED_BY = auto() COPY = auto() DATA_FILE = auto() DEPENDENCY_MANIFEST = auto() @@ -29,13 +37,20 @@ class RelationshipType(Enum): DEV_TOOL = auto() DISTRIBUTION_ARTIFACT = auto() DOCUMENTATION = auto() + DOES_NOT_AFFECT = auto() DYNAMIC_LINK = auto() EXAMPLE = auto() EXPANDED_FROM_ARCHIVE = auto() + EXPLOIT_CREATED_BY = auto() FILE_ADDED = auto() FILE_DELETED = auto() FILE_MODIFIED = auto() + FIXED_BY = auto() + FIXED_IN = auto() + FOUND_BY = auto() GENERATES = auto() + HAS_ASSESSMENT_FOR = auto() + HAS_ASSOCIATED_VULNERABILITY = auto() METAFILE = auto() OPTIONAL_COMPONENT = auto() OPTIONAL_DEPENDENCY = auto() @@ -44,6 +59,9 @@ class RelationshipType(Enum): PATCH = auto() PREREQUISITE = auto() PROVIDED_DEPENDENCY = auto() + PUBLISHED_BY = auto() + REPORTED_BY = auto() + REPUBLISHED_BY = auto() REQUIREMENT_FOR = auto() RUNTIME_DEPENDENCY = auto() SPECIFICATION_FOR = auto() @@ -52,30 +70,8 @@ class RelationshipType(Enum): TEST_CASE = auto() TEST_DEPENDENCY = auto() TEST_TOOL = auto() - VARIANT = auto() - BUILD_INPUT_OF = auto() - BUILD_OUTPUT_OF = auto() - BUILD_CONFIG_OF = auto() - BUILD_INVOKED_BY = auto() - BUILD_ON_BEHALF_OF = auto() - BUILD_HOST_OF = auto() - HAS_ASSOCIATED_VULNERABILITY = auto() - COORDINATED_BY = auto() - HAS_CVSS_V2_ASSESSMENT_FOR = auto() - HAS_CVSS_V3_ASSESSMENT_FOR = auto() - HAS_EPSS_ASSESSMENT_FOR = auto() - HAS_EXPLOIT_CATALOG_ASSESSMENT_FOR = auto() - HAS_SSVC_ASSESSMENT_FOR = auto() - EXPLOIT_CREATED_BY = auto() - FIXED_BY = auto() - FOUND_BY = auto() - PUBLISHED_BY = auto() - REPORTED_BY = auto() - REPUBLISHED_BY = auto() - AFFECTS = auto() - DOES_NOT_AFFECT = auto() - FIXED_IN = auto() UNDER_INVESTIGATION_FOR = auto() + VARIANT = auto() class RelationshipCompleteness(Enum): diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 937a4226f..175ab2e1f 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -297,32 +297,32 @@ def listed_license_fixture( "score": "4.3", "severity": "low", "vector": "(AV:N/AC:M/Au:N/C:P/I:N/A:N)", - "relationship_type": RelationshipType.HAS_CVSS_V2_ASSESSMENT_FOR, + "relationship_type": RelationshipType.HAS_ASSESSMENT_FOR, } CVSS_V3_VULN_ASSESSMENT_RELATIONSHIP_DICT = { "score": "6.8", "severity": "medium", "vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N", - "relationship_type": RelationshipType.HAS_CVSS_V3_ASSESSMENT_FOR, + "relationship_type": RelationshipType.HAS_ASSESSMENT_FOR, } EPSS_VULN_ASSESSMENT_RELATIONSHIP_DICT = { "probability": 80, "severity": "high", - "relationship_type": RelationshipType.HAS_EPSS_ASSESSMENT_FOR, + "relationship_type": RelationshipType.HAS_ASSESSMENT_FOR, } SSVC_VULN_ASSESSMENT_RELATIONSHIP_DICT = { "decision_type": SsvcDecisionType.ACT, - "relationship_type": RelationshipType.HAS_SSVC_ASSESSMENT_FOR, + "relationship_type": RelationshipType.HAS_ASSESSMENT_FOR, } EXPLOIT_CATALOG_VULN_ASSESSMENT_RELATIONSHIP_DICT = { "catalog_type": ExploitCatalogType.KEV, "exploited": True, "locator": "https://www.cisa.gov/known-exploited-vulnerabilities-catalog", - "relationship_type": RelationshipType.HAS_EXPLOIT_CATALOG_ASSESSMENT_FOR, + "relationship_type": RelationshipType.HAS_ASSESSMENT_FOR, } VEX_VULN_ASSESSMENT_RELATIONSHIP_DICT = { From c708c9329ea5a0ed155c81f09319fb0b71c31d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 14 Jun 2023 09:03:15 +0200 Subject: [PATCH 274/354] [issue-426] update model: NamespaceMap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to a5e7cebcd2c7094f89fb7416be16803d67716402 Signed-off-by: Armin Tänzer --- README.md | 2 +- src/spdx_tools/spdx3/model/namespace_map.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 12ca43cbe..54ea26b9e 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ additional installation of optional dependencies * Serialize to JSON-LD See [Quickstart to SPDX 3.0](#quickstart-to-spdx-30) below. -The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: cb39f85bed80d432acd2c177fb6480efb8fc73ae). +The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: a5e7cebcd2c7094f89fb7416be16803d67716402). # Installation diff --git a/src/spdx_tools/spdx3/model/namespace_map.py b/src/spdx_tools/spdx3/model/namespace_map.py index 88ad49bf8..68ad7c694 100644 --- a/src/spdx_tools/spdx3/model/namespace_map.py +++ b/src/spdx_tools/spdx3/model/namespace_map.py @@ -9,8 +9,8 @@ @dataclass_with_properties class NamespaceMap: - prefix: Optional[str] = None - namespace: Optional[str] = None # anyURI + prefix: str + namespace: str # anyURI - def __init__(self, prefix: Optional[str] = None, namespace: Optional[str] = None): + def __init__(self, prefix: str, namespace: str): check_types_and_set_values(self, locals()) From 8935a9ccd46778cd479db55ff049ec5e12f9f1dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 14 Jun 2023 09:32:17 +0200 Subject: [PATCH 275/354] [issue-426] update model: primaryPurpose MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to ab0391a52864ce3fc568df3938f542058556731c Signed-off-by: Armin Tänzer --- README.md | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/package.py | 6 ++---- src/spdx_tools/spdx3/model/ai/ai_package.py | 4 +++- src/spdx_tools/spdx3/model/dataset/dataset.py | 4 +++- src/spdx_tools/spdx3/model/namespace_map.py | 2 -- src/spdx_tools/spdx3/model/software/file.py | 5 +++-- src/spdx_tools/spdx3/model/software/package.py | 5 +++-- src/spdx_tools/spdx3/model/software/snippet.py | 5 +++-- src/spdx_tools/spdx3/model/software/software_artifact.py | 4 +++- tests/spdx3/fixtures.py | 3 ++- 10 files changed, 23 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 54ea26b9e..78d412b11 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ additional installation of optional dependencies * Serialize to JSON-LD See [Quickstart to SPDX 3.0](#quickstart-to-spdx-30) below. -The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: a5e7cebcd2c7094f89fb7416be16803d67716402). +The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: ab0391a52864ce3fc568df3938f542058556731c). # Installation diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index bd0a07d11..919bcc431 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -93,9 +93,7 @@ def bump_package( elif isinstance(id_or_ref, ExternalIdentifier): external_identifiers.append(id_or_ref) - package_purpose = ( - [SoftwarePurpose[spdx2_package.primary_package_purpose.name]] if spdx2_package.primary_package_purpose else [] - ) + package_purpose = SoftwarePurpose[spdx2_package.primary_package_purpose.name] payload.add_element( Package( @@ -113,7 +111,7 @@ def bump_package( built_time=spdx2_package.built_date, release_time=spdx2_package.release_date, valid_until_time=spdx2_package.valid_until_date, - purpose=package_purpose, + primary_purpose=package_purpose, package_version=spdx2_package.version, download_location=download_location, package_url=package_url, diff --git a/src/spdx_tools/spdx3/model/ai/ai_package.py b/src/spdx_tools/spdx3/model/ai/ai_package.py index 9d5dd4114..e9ee07eb7 100644 --- a/src/spdx_tools/spdx3/model/ai/ai_package.py +++ b/src/spdx_tools/spdx3/model/ai/ai_package.py @@ -46,7 +46,7 @@ def __init__( supplied_by: List[str], download_location: str, package_version: str, - purpose: List[SoftwarePurpose], + primary_purpose: SoftwarePurpose, release_time: datetime, creation_info: Optional[CreationInfo] = None, summary: Optional[str] = None, @@ -61,6 +61,7 @@ def __init__( valid_until_time: Optional[datetime] = None, standard: List[str] = None, content_identifier: Optional[str] = None, + additional_purpose: List[SoftwarePurpose] = None, concluded_license: Optional[LicenseField] = None, declared_license: Optional[LicenseField] = None, copyright_text: Optional[str] = None, @@ -88,6 +89,7 @@ def __init__( external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier originated_by = [] if originated_by is None else originated_by + additional_purpose = [] if additional_purpose is None else additional_purpose standard = [] if standard is None else standard standard_compliance = [] if standard_compliance is None else standard_compliance type_of_model = [] if type_of_model is None else type_of_model diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py index 774a3bef2..9b108a9fb 100644 --- a/src/spdx_tools/spdx3/model/dataset/dataset.py +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -51,7 +51,7 @@ def __init__( name: str, originated_by: List[str], download_location: str, - purpose: List[SoftwarePurpose], + primary_purpose: SoftwarePurpose, built_time: datetime, release_time: datetime, dataset_type: str, @@ -67,6 +67,7 @@ def __init__( valid_until_time: Optional[datetime] = None, standard: List[str] = None, content_identifier: Optional[str] = None, + additional_purpose: List[SoftwarePurpose] = None, concluded_license: Optional[LicenseField] = None, declared_license: Optional[LicenseField] = None, copyright_text: Optional[str] = None, @@ -92,6 +93,7 @@ def __init__( external_references = [] if external_references is None else external_references external_identifier = [] if external_identifier is None else external_identifier originated_by = [] if originated_by is None else originated_by + additional_purpose = [] if additional_purpose is None else additional_purpose supplied_by = [] if supplied_by is None else supplied_by standard = [] if standard is None else standard data_preprocessing = [] if data_preprocessing is None else data_preprocessing diff --git a/src/spdx_tools/spdx3/model/namespace_map.py b/src/spdx_tools/spdx3/model/namespace_map.py index 68ad7c694..c4d1217a5 100644 --- a/src/spdx_tools/spdx3/model/namespace_map.py +++ b/src/spdx_tools/spdx3/model/namespace_map.py @@ -1,8 +1,6 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from beartype.typing import Optional - from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py index 0651aaadf..3989ecd68 100644 --- a/src/spdx_tools/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -36,7 +36,8 @@ def __init__( valid_until_time: Optional[datetime] = None, standard: List[str] = None, content_identifier: Optional[str] = None, - purpose: List[SoftwarePurpose] = None, + primary_purpose: Optional[SoftwarePurpose] = None, + additional_purpose: List[SoftwarePurpose] = None, concluded_license: Optional[LicenseField] = None, declared_license: Optional[LicenseField] = None, copyright_text: Optional[str] = None, @@ -49,5 +50,5 @@ def __init__( originated_by = [] if originated_by is None else originated_by supplied_by = [] if supplied_by is None else supplied_by standard = [] if standard is None else standard - purpose = [] if purpose is None else purpose + additional_purpose = [] if additional_purpose is None else additional_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py index 2b20ba398..9e9410f93 100644 --- a/src/spdx_tools/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -40,7 +40,8 @@ def __init__( valid_until_time: Optional[datetime] = None, standard: List[str] = None, content_identifier: Optional[str] = None, - purpose: List[SoftwarePurpose] = None, + primary_purpose: Optional[SoftwarePurpose] = None, + additional_purpose: List[SoftwarePurpose] = None, concluded_license: Optional[LicenseField] = None, declared_license: Optional[LicenseField] = None, copyright_text: Optional[str] = None, @@ -57,5 +58,5 @@ def __init__( originated_by = [] if originated_by is None else originated_by supplied_by = [] if supplied_by is None else supplied_by standard = [] if standard is None else standard - purpose = [] if purpose is None else purpose + additional_purpose = [] if additional_purpose is None else additional_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py index 4dc5ac6e3..aa561399e 100644 --- a/src/spdx_tools/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -38,7 +38,8 @@ def __init__( valid_until_time: Optional[datetime] = None, standard: List[str] = None, content_identifier: Optional[str] = None, - purpose: List[SoftwarePurpose] = None, + primary_purpose: Optional[SoftwarePurpose] = None, + additional_purpose: List[SoftwarePurpose] = None, concluded_license: Optional[LicenseField] = None, declared_license: Optional[LicenseField] = None, copyright_text: Optional[str] = None, @@ -52,5 +53,5 @@ def __init__( originated_by = [] if originated_by is None else originated_by supplied_by = [] if supplied_by is None else supplied_by standard = [] if standard is None else standard - purpose = [] if purpose is None else purpose + additional_purpose = [] if additional_purpose is None else additional_purpose check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/software_artifact.py b/src/spdx_tools/spdx3/model/software/software_artifact.py index 582c71613..afc2b7ff3 100644 --- a/src/spdx_tools/spdx3/model/software/software_artifact.py +++ b/src/spdx_tools/spdx3/model/software/software_artifact.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 from abc import abstractmethod +from dataclasses import field from beartype.typing import List, Optional @@ -14,7 +15,8 @@ @dataclass_with_properties class SoftwareArtifact(Artifact): content_identifier: Optional[str] = None - purpose: List[SoftwarePurpose] = None + primary_purpose: Optional[SoftwarePurpose] = None + additional_purpose: List[SoftwarePurpose] = field(default_factory=list) concluded_license: Optional[LicenseField] = None declared_license: Optional[LicenseField] = None copyright_text: Optional[str] = None diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 175ab2e1f..cf9691677 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -380,7 +380,8 @@ def listed_license_fixture( SOFTWARE_ARTIFACT_DICT = { "content_identifier": "https://spdx.test/tools-python/contentIdentifier", - "purpose": [SoftwarePurpose.OTHER], + "primary_purpose": SoftwarePurpose.SOURCE, + "additional_purpose": [SoftwarePurpose.OTHER], "concluded_license": listed_license_fixture(), "declared_license": listed_license_fixture(), "copyright_text": "copyrightText", From 4eeb7d13dc3dccb9d3c0d21f7b67f9c553301bb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 14 Jun 2023 10:13:16 +0200 Subject: [PATCH 276/354] [issue-426] update model: relationship types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to 9371a34a09b72aabb5831238d6ec034c82524ee6 Signed-off-by: Armin Tänzer --- README.md | 2 +- src/spdx_tools/spdx3/model/relationship.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 78d412b11..df66742fc 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ additional installation of optional dependencies * Serialize to JSON-LD See [Quickstart to SPDX 3.0](#quickstart-to-spdx-30) below. -The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: ab0391a52864ce3fc568df3938f542058556731c). +The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 9371a34a09b72aabb5831238d6ec034c82524ee6). # Installation diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index 85c29700d..ec30b5003 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -39,6 +39,7 @@ class RelationshipType(Enum): DOCUMENTATION = auto() DOES_NOT_AFFECT = auto() DYNAMIC_LINK = auto() + EVIDENCE_FOR = auto() EXAMPLE = auto() EXPANDED_FROM_ARCHIVE = auto() EXPLOIT_CREATED_BY = auto() @@ -67,9 +68,11 @@ class RelationshipType(Enum): SPECIFICATION_FOR = auto() STATIC_LINK = auto() TEST = auto() + TESTED_ON = auto() TEST_CASE = auto() TEST_DEPENDENCY = auto() TEST_TOOL = auto() + TRAINED_ON = auto() UNDER_INVESTIGATION_FOR = auto() VARIANT = auto() From 199cc42150575126dbeaff123fb29a02d330a848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 14 Jun 2023 10:15:06 +0200 Subject: [PATCH 277/354] [issue-426] update model: software purpose type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to 58b356c7fb046d90f8e0ddd49460246912a949c2 Signed-off-by: Armin Tänzer --- README.md | 2 +- src/spdx_tools/spdx3/model/software/software_purpose.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index df66742fc..799222c42 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ additional installation of optional dependencies * Serialize to JSON-LD See [Quickstart to SPDX 3.0](#quickstart-to-spdx-30) below. -The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 9371a34a09b72aabb5831238d6ec034c82524ee6). +The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 58b356c7fb046d90f8e0ddd49460246912a949c2). # Installation diff --git a/src/spdx_tools/spdx3/model/software/software_purpose.py b/src/spdx_tools/spdx3/model/software/software_purpose.py index 282def1d5..bd158e784 100644 --- a/src/spdx_tools/spdx3/model/software/software_purpose.py +++ b/src/spdx_tools/spdx3/model/software/software_purpose.py @@ -19,6 +19,7 @@ class SoftwarePurpose(Enum): FRAMEWORK = auto() INSTALL = auto() LIBRARY = auto() + ML_MODEL = auto() MODULE = auto() OPERATING_SYSTEM = auto() OTHER = auto() From e6343bfcbc8a511f1b376771397e119f8e3c0a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 14 Jun 2023 10:32:16 +0200 Subject: [PATCH 278/354] [issue-426] update model: external reference types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to 96d516e846c4911bf28c690fe2d925aa854991b4 Signed-off-by: Armin Tänzer --- README.md | 2 +- .../spdx3/model/external_reference.py | 20 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 799222c42..94ccb0556 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ additional installation of optional dependencies * Serialize to JSON-LD See [Quickstart to SPDX 3.0](#quickstart-to-spdx-30) below. -The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 58b356c7fb046d90f8e0ddd49460246912a949c2). +The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 96d516e846c4911bf28c690fe2d925aa854991b4). # Installation diff --git a/src/spdx_tools/spdx3/model/external_reference.py b/src/spdx_tools/spdx3/model/external_reference.py index 5e29aa583..2f44a54d6 100644 --- a/src/spdx_tools/spdx3/model/external_reference.py +++ b/src/spdx_tools/spdx3/model/external_reference.py @@ -16,23 +16,39 @@ class ExternalReferenceType(Enum): BINARY_ARTIFACT = auto() BUILD_META = auto() BUILD_SYSTEM = auto() + CERTIFICATION_REPORT = auto() CHAT = auto() + COMPONENT_ANALYSIS_REPORT = auto() DOCUMENTATION = auto() + DYNAMIC_ANALYSIS_REPORT = auto() + EOL_NOTICE = auto() FUNDING = auto() ISSUE_TRACKER = auto() + LICENSE = auto() MAILING_LIST = auto() METRICS = auto() - LICENSE = auto() OTHER = auto() - RELEASE_NOTES = auto() + PRODUCT_METADATA = auto() + QUALITY_ASSESSMENT_REPORT = auto() RELEASE_HISTORY = auto() + RELEASE_NOTES = auto() + RISK_ASSESSMENT = auto() + RUNTIME_ANALYSIS_REPORT = auto() + SECURE_SOFTWARE_ATTESTATION = auto() + SECURITY_ADVERSARY_MODEL = auto() SECURITY_ADVISORY = auto() SECURITY_FIX = auto() SECURITY_OTHER = auto() + SECURITY_PEN_TEST_REPORT = auto() + SECURITY_POLICY = auto() + SECURITY_THREAT_MODEL = auto() SOCIAL_MEDIA = auto() SOURCE_ARTIFACT = auto() + STATIC_ANALYSIS_REPORT = auto() SUPPORT = auto() VCS = auto() + VULNERABILITY_DISCLOSURE_REPORT = auto() + VULNERABILITY_EXPLOITABILITY_ASSESSMENT = auto() @dataclass_with_properties From 9758c99bb09cb5452a326c229d55f80aa8dc534d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 14 Jun 2023 10:33:33 +0200 Subject: [PATCH 279/354] [issue-426] update model: software purpose types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to d2c0975128d4e0ecb32b9bb5484272e9010318bb Signed-off-by: Armin Tänzer --- README.md | 2 +- src/spdx_tools/spdx3/model/software/software_purpose.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 94ccb0556..fb57c8c32 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ additional installation of optional dependencies * Serialize to JSON-LD See [Quickstart to SPDX 3.0](#quickstart-to-spdx-30) below. -The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 96d516e846c4911bf28c690fe2d925aa854991b4). +The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: d2c0975128d4e0ecb32b9bb5484272e9010318bb). # Installation diff --git a/src/spdx_tools/spdx3/model/software/software_purpose.py b/src/spdx_tools/spdx3/model/software/software_purpose.py index bd158e784..4e071181f 100644 --- a/src/spdx_tools/spdx3/model/software/software_purpose.py +++ b/src/spdx_tools/spdx3/model/software/software_purpose.py @@ -19,9 +19,10 @@ class SoftwarePurpose(Enum): FRAMEWORK = auto() INSTALL = auto() LIBRARY = auto() - ML_MODEL = auto() + MODEL = auto() MODULE = auto() OPERATING_SYSTEM = auto() OTHER = auto() PATCH = auto() SOURCE = auto() + TEST = auto() From d1e08eb0935ca8ff8e4b02a01112aea72b67aba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 14 Jun 2023 10:39:41 +0200 Subject: [PATCH 280/354] [issue-426] update model: dataset type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to 6607944c0d23488db607b8f56ad83c0b4fc3f264 Signed-off-by: Armin Tänzer --- README.md | 2 +- src/spdx_tools/spdx3/model/dataset/dataset.py | 21 +++++++++++++++++-- tests/spdx3/fixtures.py | 9 ++++++-- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fb57c8c32..096d39165 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ additional installation of optional dependencies * Serialize to JSON-LD See [Quickstart to SPDX 3.0](#quickstart-to-spdx-30) below. -The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: d2c0975128d4e0ecb32b9bb5484272e9010318bb). +The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 6607944c0d23488db607b8f56ad83c0b4fc3f264). # Installation diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py index 9b108a9fb..e863cc676 100644 --- a/src/spdx_tools/spdx3/model/dataset/dataset.py +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -14,6 +14,23 @@ from spdx_tools.spdx3.model.software import Package, SoftwarePurpose +class DatasetType(Enum): + STRUCTURED = auto() + NUMERIC = auto() + TEXT = auto() + CATEGORICAL = auto() + GRAPH = auto() + TIMESERIES = auto() + TIMESTAMP = auto() + SENSOR = auto() + IMAGE = auto() + SYNTACTIC = auto() + AUDIO = auto() + VIDEO = auto() + OTHER = auto() + NO_ASSERTION = auto() + + class ConfidentialityLevelType(Enum): RED = auto() AMBER = auto() @@ -31,7 +48,7 @@ class DatasetAvailabilityType(Enum): @dataclass_with_properties class Dataset(Package): - dataset_type: str = None + dataset_type: List[DatasetType] = None data_collection_process: Optional[str] = None intended_use: Optional[str] = None dataset_size: Optional[int] = None @@ -54,7 +71,7 @@ def __init__( primary_purpose: SoftwarePurpose, built_time: datetime, release_time: datetime, - dataset_type: str, + dataset_type: List[DatasetType], creation_info: Optional[CreationInfo] = None, summary: Optional[str] = None, description: Optional[str] = None, diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index cf9691677..df8d2f5a9 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -35,7 +35,12 @@ ) from spdx_tools.spdx3.model.ai.ai_package import AIPackage, SafetyRiskAssessmentType from spdx_tools.spdx3.model.build import Build -from spdx_tools.spdx3.model.dataset.dataset import ConfidentialityLevelType, Dataset, DatasetAvailabilityType +from spdx_tools.spdx3.model.dataset.dataset import ( + ConfidentialityLevelType, + Dataset, + DatasetAvailabilityType, + DatasetType, +) from spdx_tools.spdx3.model.licensing import ( CustomLicense, CustomLicenseAddition, @@ -406,7 +411,7 @@ def listed_license_fixture( } DATASET_DICT = { - "dataset_type": "DatasetType", + "dataset_type": [DatasetType.OTHER], "data_collection_process": "DatasetDataCollectionProcess", "intended_use": "DatasetIntendedUse", "dataset_size": 10, From b200026b8dd7c588358b95df0b8226efcd76db62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 14 Jun 2023 11:00:56 +0200 Subject: [PATCH 281/354] [issue-426] update model: relationship types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to a5372a3c145dbdfc1381fc1f791c68889aafc7ff Signed-off-by: Armin Tänzer --- README.md | 2 +- src/spdx_tools/spdx3/model/relationship.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 096d39165..d3ac972d7 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ additional installation of optional dependencies * Serialize to JSON-LD See [Quickstart to SPDX 3.0](#quickstart-to-spdx-30) below. -The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: 6607944c0d23488db607b8f56ad83c0b4fc3f264). +The implementation is based on the descriptive markdown files in the repository https://github.com/spdx/spdx-3-model (latest commit: a5372a3c145dbdfc1381fc1f791c68889aafc7ff). # Installation diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index ec30b5003..61c275060 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -17,16 +17,11 @@ class RelationshipType(Enum): AMENDS = auto() ANCESTOR = auto() AVAILABLE_FROM = auto() - BUILD_CONFIG_OF = auto() BUILD_DEPENDENCY = auto() - BUILD_HOST_OF = auto() - BUILD_INPUT_OF = auto() - BUILD_INVOKED_BY = auto() - BUILD_ON_BEHALF_OF = auto() - BUILD_OUTPUT_OF = auto() BUILD_TOOL = auto() - CONTAINS = auto() COORDINATED_BY = auto() + CONTAINS = auto() + CONFIG_OF = auto() COPY = auto() DATA_FILE = auto() DEPENDENCY_MANIFEST = auto() @@ -39,8 +34,8 @@ class RelationshipType(Enum): DOCUMENTATION = auto() DOES_NOT_AFFECT = auto() DYNAMIC_LINK = auto() - EVIDENCE_FOR = auto() EXAMPLE = auto() + EVIDENCE_FOR = auto() EXPANDED_FROM_ARCHIVE = auto() EXPLOIT_CREATED_BY = auto() FILE_ADDED = auto() @@ -52,10 +47,15 @@ class RelationshipType(Enum): GENERATES = auto() HAS_ASSESSMENT_FOR = auto() HAS_ASSOCIATED_VULNERABILITY = auto() + HOST_OF = auto() + INPUT_OF = auto() + INVOKED_BY = auto() METAFILE = auto() + ON_BEHALF_OF = auto() OPTIONAL_COMPONENT = auto() OPTIONAL_DEPENDENCY = auto() OTHER = auto() + OUTPUT_OF = auto() PACKAGES = auto() PATCH = auto() PREREQUISITE = auto() @@ -68,10 +68,10 @@ class RelationshipType(Enum): SPECIFICATION_FOR = auto() STATIC_LINK = auto() TEST = auto() - TESTED_ON = auto() TEST_CASE = auto() TEST_DEPENDENCY = auto() TEST_TOOL = auto() + TESTED_ON = auto() TRAINED_ON = auto() UNDER_INVESTIGATION_FOR = auto() VARIANT = auto() From ce8cf6831af1cfdcec98fd537071f603e570ae02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 14 Jun 2023 11:28:32 +0200 Subject: [PATCH 282/354] [issue-426] change external_references to singular MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/bump_from_spdx2/package.py | 12 ++++++------ src/spdx_tools/spdx3/model/agent.py | 4 ++-- src/spdx_tools/spdx3/model/ai/ai_package.py | 4 ++-- src/spdx_tools/spdx3/model/annotation.py | 4 ++-- src/spdx_tools/spdx3/model/bom.py | 4 ++-- src/spdx_tools/spdx3/model/build/build.py | 4 ++-- src/spdx_tools/spdx3/model/bundle.py | 4 ++-- src/spdx_tools/spdx3/model/dataset/dataset.py | 4 ++-- src/spdx_tools/spdx3/model/element.py | 2 +- .../spdx3/model/lifecycle_scoped_relationship.py | 4 ++-- src/spdx_tools/spdx3/model/organization.py | 4 ++-- src/spdx_tools/spdx3/model/person.py | 4 ++-- src/spdx_tools/spdx3/model/relationship.py | 4 ++-- .../security/cvss_v2_vuln_assessment_relationship.py | 4 ++-- .../security/cvss_v3_vuln_assessment_relationship.py | 4 ++-- .../security/epss_vuln_assessment_relationship.py | 4 ++-- .../exploit_catalog_vuln_assessment_relationship.py | 4 ++-- .../security/ssvc_vuln_assessment_relationship.py | 4 ++-- .../vex_affected_vuln_assessment_relationship.py | 4 ++-- .../vex_fixed_vuln_assessment_relationship.py | 4 ++-- .../vex_not_affected_vuln_assessment_relationship.py | 4 ++-- ...der_investigation_vuln_assessment_relationship.py | 4 ++-- src/spdx_tools/spdx3/model/security/vulnerability.py | 4 ++-- src/spdx_tools/spdx3/model/software/file.py | 4 ++-- src/spdx_tools/spdx3/model/software/package.py | 4 ++-- src/spdx_tools/spdx3/model/software/sbom.py | 4 ++-- src/spdx_tools/spdx3/model/software/snippet.py | 4 ++-- .../software/software_dependency_relationship.py | 4 ++-- src/spdx_tools/spdx3/model/software_agent.py | 4 ++-- src/spdx_tools/spdx3/model/spdx_document.py | 4 ++-- src/spdx_tools/spdx3/model/tool.py | 4 ++-- .../spdx3/writer/console/element_writer.py | 4 ++-- tests/spdx3/bump/test_package_bump.py | 8 ++++---- tests/spdx3/fixtures.py | 2 +- 34 files changed, 72 insertions(+), 72 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index 919bcc431..899506360 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -75,8 +75,8 @@ def bump_package( "and missing definition of license profile", ) - external_references = [] - external_identifiers = [] + external_reference = [] + external_identifier = [] purl_refs = [ external_ref for external_ref in spdx2_package.external_references if external_ref.reference_type == "purl" ] @@ -89,9 +89,9 @@ def bump_package( continue id_or_ref = bump_external_package_ref(spdx2_external_ref) if isinstance(id_or_ref, ExternalReference): - external_references.append(id_or_ref) + external_reference.append(id_or_ref) elif isinstance(id_or_ref, ExternalIdentifier): - external_identifiers.append(id_or_ref) + external_identifier.append(id_or_ref) package_purpose = SoftwarePurpose[spdx2_package.primary_package_purpose.name] @@ -104,8 +104,8 @@ def bump_package( description=spdx2_package.description, comment=spdx2_package.comment, verified_using=integrity_methods, - external_references=external_references, - external_identifier=external_identifiers, + external_reference=external_reference, + external_identifier=external_identifier, originated_by=originated_by_spdx_id, supplied_by=supplied_by_spdx_id, built_time=spdx2_package.built_date, diff --git a/src/spdx_tools/spdx3/model/agent.py b/src/spdx_tools/spdx3/model/agent.py index 0470ed304..9aa326e22 100644 --- a/src/spdx_tools/spdx3/model/agent.py +++ b/src/spdx_tools/spdx3/model/agent.py @@ -19,11 +19,11 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/ai/ai_package.py b/src/spdx_tools/spdx3/model/ai/ai_package.py index e9ee07eb7..b297385e3 100644 --- a/src/spdx_tools/spdx3/model/ai/ai_package.py +++ b/src/spdx_tools/spdx3/model/ai/ai_package.py @@ -53,7 +53,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, originated_by: List[str] = None, @@ -86,7 +86,7 @@ def __init__( safety_risk_assessment: Optional[SafetyRiskAssessmentType] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier originated_by = [] if originated_by is None else originated_by additional_purpose = [] if additional_purpose is None else additional_purpose diff --git a/src/spdx_tools/spdx3/model/annotation.py b/src/spdx_tools/spdx3/model/annotation.py index 9a016cfe8..e74d9d578 100644 --- a/src/spdx_tools/spdx3/model/annotation.py +++ b/src/spdx_tools/spdx3/model/annotation.py @@ -34,14 +34,14 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, content_type: List[str] = None, statement: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier content_type = [] if content_type is None else content_type check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/bom.py b/src/spdx_tools/spdx3/model/bom.py index 332d31652..a9ad7d57e 100644 --- a/src/spdx_tools/spdx3/model/bom.py +++ b/src/spdx_tools/spdx3/model/bom.py @@ -32,7 +32,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, namespaces: List[NamespaceMap] = None, @@ -40,7 +40,7 @@ def __init__( context: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports diff --git a/src/spdx_tools/spdx3/model/build/build.py b/src/spdx_tools/spdx3/model/build/build.py index 8d784e819..c6662ccce 100644 --- a/src/spdx_tools/spdx3/model/build/build.py +++ b/src/spdx_tools/spdx3/model/build/build.py @@ -33,7 +33,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, build_id: Optional[str] = None, @@ -46,7 +46,7 @@ def __init__( environment: Dict[str, str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier config_source_entrypoint = [] if config_source_entrypoint is None else config_source_entrypoint config_source_uri = [] if config_source_uri is None else config_source_uri diff --git a/src/spdx_tools/spdx3/model/bundle.py b/src/spdx_tools/spdx3/model/bundle.py index c90352308..63640f845 100644 --- a/src/spdx_tools/spdx3/model/bundle.py +++ b/src/spdx_tools/spdx3/model/bundle.py @@ -31,7 +31,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, namespaces: List[NamespaceMap] = None, @@ -39,7 +39,7 @@ def __init__( context: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports diff --git a/src/spdx_tools/spdx3/model/dataset/dataset.py b/src/spdx_tools/spdx3/model/dataset/dataset.py index e863cc676..bbb82cc3a 100644 --- a/src/spdx_tools/spdx3/model/dataset/dataset.py +++ b/src/spdx_tools/spdx3/model/dataset/dataset.py @@ -77,7 +77,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, supplied_by: List[str] = None, @@ -107,7 +107,7 @@ def __init__( dataset_availability: Optional[DatasetAvailabilityType] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier originated_by = [] if originated_by is None else originated_by additional_purpose = [] if additional_purpose is None else additional_purpose diff --git a/src/spdx_tools/spdx3/model/element.py b/src/spdx_tools/spdx3/model/element.py index f5ec4790e..08f2d7b85 100644 --- a/src/spdx_tools/spdx3/model/element.py +++ b/src/spdx_tools/spdx3/model/element.py @@ -19,7 +19,7 @@ class Element(ABC): description: Optional[str] = None comment: Optional[str] = None verified_using: List[IntegrityMethod] = field(default_factory=list) - external_references: List[ExternalReference] = field(default_factory=list) + external_reference: List[ExternalReference] = field(default_factory=list) external_identifier: List[ExternalIdentifier] = field(default_factory=list) extension: Optional[str] = None # placeholder for extension diff --git a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py index f5181a616..a06e108ce 100644 --- a/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py +++ b/src/spdx_tools/spdx3/model/lifecycle_scoped_relationship.py @@ -44,7 +44,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, @@ -54,6 +54,6 @@ def __init__( ): to = [] if to is None else to verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/organization.py b/src/spdx_tools/spdx3/model/organization.py index f896b2b33..c297b24b3 100644 --- a/src/spdx_tools/spdx3/model/organization.py +++ b/src/spdx_tools/spdx3/model/organization.py @@ -19,11 +19,11 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/person.py b/src/spdx_tools/spdx3/model/person.py index b06e263db..782e5a366 100644 --- a/src/spdx_tools/spdx3/model/person.py +++ b/src/spdx_tools/spdx3/model/person.py @@ -19,11 +19,11 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/relationship.py b/src/spdx_tools/spdx3/model/relationship.py index 61c275060..873559460 100644 --- a/src/spdx_tools/spdx3/model/relationship.py +++ b/src/spdx_tools/spdx3/model/relationship.py @@ -106,7 +106,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, @@ -115,6 +115,6 @@ def __init__( ): to = [] if to is None else to verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py index f480e961b..c686f9dfc 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v2_vuln_assessment_relationship.py @@ -37,7 +37,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, @@ -52,6 +52,6 @@ def __init__( vector: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py index fb30a215c..ab8a803af 100644 --- a/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/cvss_v3_vuln_assessment_relationship.py @@ -37,7 +37,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, @@ -52,6 +52,6 @@ def __init__( vector: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py index cde6445d6..f5001a92d 100644 --- a/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/epss_vuln_assessment_relationship.py @@ -36,7 +36,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, @@ -50,6 +50,6 @@ def __init__( severity: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py index 6ed309047..a7a67ac68 100644 --- a/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/exploit_catalog_vuln_assessment_relationship.py @@ -45,7 +45,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, @@ -58,6 +58,6 @@ def __init__( withdrawn_time: Optional[datetime] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py index 22105e379..d98803874 100644 --- a/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/ssvc_vuln_assessment_relationship.py @@ -43,7 +43,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, @@ -56,6 +56,6 @@ def __init__( withdrawn_time: Optional[datetime] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py index 014190770..2dc242273 100644 --- a/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_affected_vuln_assessment_relationship.py @@ -36,7 +36,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, @@ -53,7 +53,7 @@ def __init__( action_statement_time: List[datetime] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier action_statement_time = [] if action_statement_time is None else action_statement_time check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py index 79a495bb9..c8bdc2b38 100644 --- a/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_fixed_vuln_assessment_relationship.py @@ -32,7 +32,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, @@ -47,6 +47,6 @@ def __init__( status_notes: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py index ea4f5674c..4c019a973 100644 --- a/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_not_affected_vuln_assessment_relationship.py @@ -45,7 +45,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, @@ -63,6 +63,6 @@ def __init__( impact_statement_time: Optional[datetime] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py index a24db0156..ba63480bc 100644 --- a/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py +++ b/src/spdx_tools/spdx3/model/security/vex_under_investigation_vuln_assessment_relationship.py @@ -32,7 +32,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, @@ -47,6 +47,6 @@ def __init__( status_notes: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/security/vulnerability.py b/src/spdx_tools/spdx3/model/security/vulnerability.py index 1daa006a6..a137b1cb7 100644 --- a/src/spdx_tools/spdx3/model/security/vulnerability.py +++ b/src/spdx_tools/spdx3/model/security/vulnerability.py @@ -25,7 +25,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, published_time: Optional[datetime] = None, @@ -33,6 +33,6 @@ def __init__( withdrawn_time: Optional[datetime] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software/file.py b/src/spdx_tools/spdx3/model/software/file.py index 3989ecd68..c962b4dbd 100644 --- a/src/spdx_tools/spdx3/model/software/file.py +++ b/src/spdx_tools/spdx3/model/software/file.py @@ -26,7 +26,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, originated_by: List[str] = None, @@ -45,7 +45,7 @@ def __init__( content_type: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier originated_by = [] if originated_by is None else originated_by supplied_by = [] if supplied_by is None else supplied_by diff --git a/src/spdx_tools/spdx3/model/software/package.py b/src/spdx_tools/spdx3/model/software/package.py index 9e9410f93..0c249cc1b 100644 --- a/src/spdx_tools/spdx3/model/software/package.py +++ b/src/spdx_tools/spdx3/model/software/package.py @@ -30,7 +30,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, originated_by: List[str] = None, @@ -53,7 +53,7 @@ def __init__( source_info: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier originated_by = [] if originated_by is None else originated_by supplied_by = [] if supplied_by is None else supplied_by diff --git a/src/spdx_tools/spdx3/model/software/sbom.py b/src/spdx_tools/spdx3/model/software/sbom.py index ff702953f..1fb06f615 100644 --- a/src/spdx_tools/spdx3/model/software/sbom.py +++ b/src/spdx_tools/spdx3/model/software/sbom.py @@ -45,7 +45,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, namespaces: List[NamespaceMap] = None, @@ -54,7 +54,7 @@ def __init__( sbom_type: List[SBOMType] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports diff --git a/src/spdx_tools/spdx3/model/software/snippet.py b/src/spdx_tools/spdx3/model/software/snippet.py index aa561399e..b3ab61396 100644 --- a/src/spdx_tools/spdx3/model/software/snippet.py +++ b/src/spdx_tools/spdx3/model/software/snippet.py @@ -28,7 +28,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, originated_by: List[str] = None, @@ -48,7 +48,7 @@ def __init__( line_range: Optional[PositiveIntegerRange] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier originated_by = [] if originated_by is None else originated_by supplied_by = [] if supplied_by is None else supplied_by diff --git a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py index 1ce96aeb7..c6751ecaa 100644 --- a/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py +++ b/src/spdx_tools/spdx3/model/software/software_dependency_relationship.py @@ -52,7 +52,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, completeness: Optional[RelationshipCompleteness] = None, @@ -64,6 +64,6 @@ def __init__( ): to = [] if to is None else to verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/software_agent.py b/src/spdx_tools/spdx3/model/software_agent.py index 50fb57540..28e4b33a2 100644 --- a/src/spdx_tools/spdx3/model/software_agent.py +++ b/src/spdx_tools/spdx3/model/software_agent.py @@ -19,11 +19,11 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/model/spdx_document.py b/src/spdx_tools/spdx3/model/spdx_document.py index 43fcb3d6b..d9c70401c 100644 --- a/src/spdx_tools/spdx3/model/spdx_document.py +++ b/src/spdx_tools/spdx3/model/spdx_document.py @@ -32,7 +32,7 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, namespaces: List[NamespaceMap] = None, @@ -40,7 +40,7 @@ def __init__( context: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier namespaces = [] if namespaces is None else namespaces imports = [] if imports is None else imports diff --git a/src/spdx_tools/spdx3/model/tool.py b/src/spdx_tools/spdx3/model/tool.py index bc8447c1f..b4ba72cf3 100644 --- a/src/spdx_tools/spdx3/model/tool.py +++ b/src/spdx_tools/spdx3/model/tool.py @@ -19,11 +19,11 @@ def __init__( description: Optional[str] = None, comment: Optional[str] = None, verified_using: List[IntegrityMethod] = None, - external_references: List[ExternalReference] = None, + external_reference: List[ExternalReference] = None, external_identifier: List[ExternalIdentifier] = None, extension: Optional[str] = None, ): verified_using = [] if verified_using is None else verified_using - external_references = [] if external_references is None else external_references + external_reference = [] if external_reference is None else external_reference external_identifier = [] if external_identifier is None else external_identifier check_types_and_set_values(self, locals()) diff --git a/src/spdx_tools/spdx3/writer/console/element_writer.py b/src/spdx_tools/spdx3/writer/console/element_writer.py index 6614279f1..61eb72ecd 100644 --- a/src/spdx_tools/spdx3/writer/console/element_writer.py +++ b/src/spdx_tools/spdx3/writer/console/element_writer.py @@ -26,8 +26,8 @@ def write_element_properties(element: Element, text_output: TextIO): # as soon as there are more inherited classes we need to implement a logic # that determines the correct write function for the "integrity_method" object write_hash(integrity_method, text_output, heading=False) - write_optional_heading(element.external_references, "External References\n", text_output) - for external_reference in element.external_references: + write_optional_heading(element.external_reference, "External Reference\n", text_output) + for external_reference in element.external_reference: write_external_reference(external_reference, text_output) write_optional_heading(element.external_identifier, "External Identifier\n", text_output) for external_identifier in element.external_identifier: diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index e199b2995..6dc9ab39d 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -51,7 +51,7 @@ def test_bump_package(originator, expected_originator, supplier, expected_suppli assert isinstance(package, Package) assert package.spdx_id == expected_new_package_id assert package.package_version == spdx2_package.version - assert package.external_references == [ + assert package.external_reference == [ ExternalReference(ExternalReferenceType.SECURITY_ADVISORY, ["advisory_locator"], None, "advisory_comment") ] assert package.external_identifier == [ @@ -90,7 +90,7 @@ def test_bump_of_single_purl_without_comment(): package = payload.get_element(expected_new_package_id) assert package.package_url == "purl_locator" - assert package.external_references == [] + assert package.external_reference == [] assert package.external_identifier == [] @@ -108,7 +108,7 @@ def test_bump_of_single_purl_with_comment(): package = payload.get_element(expected_new_package_id) assert package.package_url is None - assert package.external_references == [] + assert package.external_reference == [] assert package.external_identifier == [ ExternalIdentifier(ExternalIdentifierType.PURL, "purl_locator", "purl_comment") ] @@ -129,7 +129,7 @@ def test_bump_of_multiple_purls(): package = payload.get_element(expected_new_package_id) assert package.package_url is None - assert package.external_references == [] + assert package.external_reference == [] TestCase().assertCountEqual( package.external_identifier, [ diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index df8d2f5a9..219135f4b 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -211,7 +211,7 @@ def listed_license_fixture( "description": "elementDescription", "comment": "elementComment", "verified_using": [hash_fixture()], - "external_references": [external_reference_fixture()], + "external_reference": [external_reference_fixture()], "external_identifier": [external_identifier_fixture()], "extension": "extensionPlaceholder", } From 55c638620388dde1f279046ba756e61ad786b6a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 12 Jun 2023 11:02:01 +0200 Subject: [PATCH 283/354] [issue-693] TV writer: fix for same file in multiple packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../spdx/writer/tagvalue/tagvalue_writer.py | 22 +++-- .../writer/tagvalue/test_tagvalue_writer.py | 99 ++++++++++++++++++- 2 files changed, 114 insertions(+), 7 deletions(-) diff --git a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py index d82a1213e..af58b8af0 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py @@ -11,7 +11,7 @@ from beartype.typing import List, TextIO from spdx_tools.spdx.document_utils import create_document_without_duplicates -from spdx_tools.spdx.model import Document +from spdx_tools.spdx.model import Document, Relationship, RelationshipType from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document from spdx_tools.spdx.validation.validation_message import ValidationMessage from spdx_tools.spdx.writer.tagvalue.annotation_writer import write_annotation @@ -70,17 +70,27 @@ def write_document(document: Document, text_output: TextIO): file_ids_with_contained_snippets[file.spdx_id], write_snippet, text_output, with_separator=True ) + already_written_file_ids = [] # a file can belong to multiple packages but must appear only once for package in document.packages: write_package(package, text_output) write_separator(text_output) if package.spdx_id in contained_files_by_package_id: for file in contained_files_by_package_id[package.spdx_id]: - write_file(file, text_output) - write_separator(text_output) - if file.spdx_id in file_ids_with_contained_snippets: - write_list_of_elements( - file_ids_with_contained_snippets[file.spdx_id], write_snippet, text_output, with_separator=True + if file.spdx_id in already_written_file_ids: + relationships_to_write.append( + Relationship(package.spdx_id, RelationshipType.CONTAINS, file.spdx_id) ) + else: + write_file(file, text_output) + write_separator(text_output) + if file.spdx_id in file_ids_with_contained_snippets: + write_list_of_elements( + file_ids_with_contained_snippets[file.spdx_id], + write_snippet, + text_output, + with_separator=True, + ) + already_written_file_ids.append(file.spdx_id) write_optional_heading(document.extracted_licensing_info, "## License Information\n", text_output) write_list_of_elements( diff --git a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py index 995687ce5..86e7a2f92 100644 --- a/tests/spdx/writer/tagvalue/test_tagvalue_writer.py +++ b/tests/spdx/writer/tagvalue/test_tagvalue_writer.py @@ -3,11 +3,24 @@ # SPDX-License-Identifier: Apache-2.0 import os +from datetime import datetime from unittest.mock import MagicMock, call, mock_open, patch import pytest -from spdx_tools.spdx.model import File, Package, Relationship, RelationshipType, Snippet +from spdx_tools.spdx.model import ( + Actor, + ActorType, + Checksum, + ChecksumAlgorithm, + CreationInfo, + Document, + File, + Package, + Relationship, + RelationshipType, + Snippet, +) from spdx_tools.spdx.parser.tagvalue import tagvalue_parser from spdx_tools.spdx.writer.tagvalue.tagvalue_writer import write_document, write_document_to_file from tests.spdx.fixtures import checksum_fixture, document_fixture @@ -122,3 +135,87 @@ def test_correct_order_of_elements(): call("\n"), ] ) + + +def test_same_file_in_multiple_packages(): + creation_info = CreationInfo( + spdx_version="SPDX-2.3", + spdx_id="SPDXRef-DOCUMENT", + data_license="CC0-1.0", + name="SPDX Lite Document", + document_namespace="https://test.namespace.com", + creators=[Actor(ActorType.PERSON, "John Doe")], + created=datetime(2023, 3, 14, 8, 49), + ) + package_a = Package( + name="Example package A", + spdx_id="SPDXRef-Package-A", + download_location="https://download.com", + ) + package_b = Package( + name="Example package B", + spdx_id="SPDXRef-Package-B", + download_location="https://download.com", + ) + file = File( + name="Example file", + spdx_id="SPDXRef-File", + checksums=[Checksum(ChecksumAlgorithm.SHA1, "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12")], + ) + + relationships = [ + Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package-A"), + Relationship("SPDXRef-DOCUMENT", RelationshipType.DESCRIBES, "SPDXRef-Package-B"), + Relationship("SPDXRef-Package-A", RelationshipType.CONTAINS, "SPDXRef-File"), + Relationship("SPDXRef-Package-B", RelationshipType.CONTAINS, "SPDXRef-File"), + ] + document = Document( + creation_info=creation_info, + packages=[package_a, package_b], + files=[file], + relationships=relationships, + ) + mock: MagicMock = mock_open() + with patch(f"{__name__}.open", mock, create=True): + with open("foo", "w") as file: + write_document(document, file) + + mock.assert_called_once_with("foo", "w") + handle = mock() + handle.write.assert_has_calls( + [ + call("## Document Information\n"), + call("SPDXVersion: SPDX-2.3\n"), + call("DataLicense: CC0-1.0\n"), + call("SPDXID: SPDXRef-DOCUMENT\n"), + call("DocumentName: SPDX Lite Document\n"), + call("DocumentNamespace: https://test.namespace.com\n"), + call("\n"), + call("## Creation Information\n"), + call("Creator: Person: John Doe\n"), + call("Created: 2023-03-14T08:49:00Z\n"), + call("\n"), + call("## Package Information\n"), + call("PackageName: Example package A\n"), + call("SPDXID: SPDXRef-Package-A\n"), + call("PackageDownloadLocation: https://download.com\n"), + call("FilesAnalyzed: True\n"), + call("\n"), + call("## File Information\n"), + call("FileName: Example file\n"), + call("SPDXID: SPDXRef-File\n"), + call("FileChecksum: SHA1: 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12\n"), + call("\n"), + call("## Package Information\n"), + call("PackageName: Example package B\n"), + call("SPDXID: SPDXRef-Package-B\n"), + call("PackageDownloadLocation: https://download.com\n"), + call("FilesAnalyzed: True\n"), + call("\n"), + call("## Relationships\n"), + call("Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-Package-A\n"), + call("Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-Package-B\n"), + call("Relationship: SPDXRef-Package-B CONTAINS SPDXRef-File\n"), + call("\n"), + ] + ) From 3ffd213a5f36f4da469e80588c08ca7cfbdb168d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 12 Jun 2023 15:42:26 +0200 Subject: [PATCH 284/354] bumping: fix root element to include DESCRIBED elements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py index 17a957c4f..a1083119b 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py @@ -70,7 +70,7 @@ def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload name=spdx2_creation_info.name, comment=spdx2_creation_info.document_comment, element=[], - root_element=[spdx_id], + root_element=[], imports=imports, namespaces=namespaces, ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py index a93d762ff..1c17a5de6 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py @@ -9,7 +9,9 @@ from spdx_tools.spdx3.bump_from_spdx2.snippet import bump_snippet from spdx_tools.spdx3.model import CreationInfo, SpdxDocument from spdx_tools.spdx3.payload import Payload +from spdx_tools.spdx.model import RelationshipType from spdx_tools.spdx.model.document import Document as Spdx2_Document +from spdx_tools.spdx.model.relationship_filters import filter_by_type_and_origin """ We want to implement a bump_from_spdx2 from the data model in src.spdx to the data model in src.spdx3. As there are many fundamental differences between these version we want each bump_from_spdx2 method to take @@ -20,6 +22,13 @@ def bump_spdx_document(document: Spdx2_Document) -> Payload: payload = Payload() document_namespace: str = document.creation_info.document_namespace spdx_document: SpdxDocument = bump_creation_info(document.creation_info, payload) + spdx_document.root_element = [ + f"{document_namespace}#{relationship.related_spdx_element_id}" + for relationship in filter_by_type_and_origin( + document.relationships, RelationshipType.DESCRIBES, "SPDXRef-DOCUMENT" + ) + ] + creation_info: CreationInfo = spdx_document.creation_info payload.add_element(spdx_document) From dfe48d8d621f5d722857f9878c24a46ec2ecc186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 12 Jun 2023 15:45:06 +0200 Subject: [PATCH 285/354] add URI to data_license during bumping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py index a1083119b..39a38edef 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py @@ -38,7 +38,7 @@ def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload created_by=[], created_using=[], profile=[ProfileIdentifier.CORE, ProfileIdentifier.SOFTWARE, ProfileIdentifier.LICENSING], - data_license=spdx2_creation_info.data_license, + data_license="https://spdx.org/licenses/" + spdx2_creation_info.data_license, ) # due to creators having a creation_info themselves which inherits from the document's one, From 1dc829f34cecb6fb44ef5426cf53759d15838586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 12 Jun 2023 15:46:48 +0200 Subject: [PATCH 286/354] bumping: make creation_info optional, remove licenses for now MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/bump_from_spdx2/actor.py | 23 +++++++++------- .../spdx3/bump_from_spdx2/annotation.py | 2 +- .../spdx3/bump_from_spdx2/creation_info.py | 2 +- src/spdx_tools/spdx3/bump_from_spdx2/file.py | 12 ++------- .../spdx3/bump_from_spdx2/package.py | 19 +++---------- .../spdx3/bump_from_spdx2/relationship.py | 14 ++-------- .../spdx3/bump_from_spdx2/snippet.py | 12 ++------- .../spdx3/bump_from_spdx2/spdx_document.py | 8 +----- tests/spdx3/bump/test_actor_bump.py | 4 +-- tests/spdx3/bump/test_file_bump.py | 10 ++----- tests/spdx3/bump/test_package_bump.py | 16 +++-------- tests/spdx3/bump/test_relationship_bump.py | 27 ++++++------------- tests/spdx3/bump/test_snippet_bump.py | 10 ++----- 13 files changed, 43 insertions(+), 116 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/actor.py b/src/spdx_tools/spdx3/bump_from_spdx2/actor.py index 3fac60412..3283bf11a 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/actor.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/actor.py @@ -1,6 +1,8 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from typing import Optional + from beartype.typing import List from spdx_tools.spdx3.model import CreationInfo, ExternalIdentifier, ExternalIdentifierType, Organization, Person, Tool @@ -10,7 +12,7 @@ def bump_actor( - spdx2_actor: Spdx2_Actor, payload: Payload, creation_info: CreationInfo, document_namespace: str + spdx2_actor: Spdx2_Actor, payload: Payload, document_namespace: str, creation_info: Optional[CreationInfo] = None ) -> str: name: str = spdx2_actor.name email: str = spdx2_actor.email @@ -27,20 +29,21 @@ def bump_actor( if spdx_id in payload.get_full_map(): # the agent/tool already exists, so we don't need to create a new one return spdx_id + value_dict = { + "spdx_id": spdx_id, + "creation_info": creation_info, + "name": name, + "external_identifier": external_identifiers, + } + if actor_type == ActorType.PERSON: - agent_or_tool = Person( - spdx_id=spdx_id, creation_info=creation_info, name=name, external_identifier=external_identifiers - ) + agent_or_tool = Person(**value_dict) elif actor_type == ActorType.ORGANIZATION: - agent_or_tool = Organization( - spdx_id=spdx_id, creation_info=creation_info, name=name, external_identifier=external_identifiers - ) + agent_or_tool = Organization(**value_dict) elif actor_type == ActorType.TOOL: - agent_or_tool = Tool( - spdx_id=spdx_id, creation_info=creation_info, name=name, external_identifier=external_identifiers - ) + agent_or_tool = Tool(**value_dict) else: raise ValueError(f"no conversion rule defined for ActorType {actor_type}") diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py index adcb51046..bae61160c 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/annotation.py @@ -25,7 +25,7 @@ def bump_annotation( # caution: the annotator and the annotation will only share the same creation_info if the actor # has not been previously defined annotator = spdx2_annotation.annotator - creator_id: str = bump_actor(annotator, payload, creation_info, document_namespace) + creator_id: str = bump_actor(annotator, payload, document_namespace, creation_info) if annotator.actor_type in [ActorType.PERSON, ActorType.ORGANIZATION]: creation_info.created_by = [creator_id] else: diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py index 39a38edef..b919449a8 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py @@ -46,7 +46,7 @@ def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload creator_ids: List[str] = [] tool_ids: List[str] = [] for creator in spdx2_creation_info.creators: - bumped_actor_id = bump_actor(creator, payload, creation_info, document_namespace) + bumped_actor_id = bump_actor(creator, payload, document_namespace, creation_info) if creator.actor_type in [ActorType.PERSON, ActorType.ORGANIZATION]: creator_ids.append(bumped_actor_id) else: diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/file.py b/src/spdx_tools/spdx3/bump_from_spdx2/file.py index c1f8226aa..824f95a1f 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/file.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/file.py @@ -4,12 +4,11 @@ from beartype.typing import List from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum -from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model import CreationInfo, ExternalMap +from spdx_tools.spdx3.model import ExternalMap from spdx_tools.spdx3.model.software import File from spdx_tools.spdx3.payload import Payload -from spdx_tools.spdx.model import ExternalDocumentRef, ExtractedLicensingInfo, SpdxNoAssertion +from spdx_tools.spdx.model import ExternalDocumentRef, SpdxNoAssertion from spdx_tools.spdx.model.file import File as Spdx2_File from spdx_tools.spdx.spdx_element_utils import get_full_element_spdx_id @@ -17,9 +16,7 @@ def bump_file( spdx2_file: Spdx2_File, payload: Payload, - creation_info: CreationInfo, document_namespace: str, - extracted_licensing_info: List[ExtractedLicensingInfo], external_document_refs: List[ExternalDocumentRef], imports: List[ExternalMap], ): @@ -36,9 +33,6 @@ def bump_file( print_missing_conversion( "file.file_type", 0, "different cardinalities, " "https://github.com/spdx/spdx-3-model/issues/82" ) - license_concluded = bump_license_expression_or_none_or_no_assertion( - spdx2_file.license_concluded, extracted_licensing_info - ) copyright_text = None if isinstance(spdx2_file.copyright_text, str): copyright_text = spdx2_file.copyright_text @@ -53,11 +47,9 @@ def bump_file( payload.add_element( File( spdx_id, - creation_info=creation_info, name=spdx2_file.name, comment=spdx2_file.comment, verified_using=integrity_methods, - concluded_license=license_concluded, copyright_text=copyright_text, attribution_text=", ".join(spdx2_file.attribution_texts), ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index 899506360..a7414d1b4 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -6,10 +6,8 @@ from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor from spdx_tools.spdx3.bump_from_spdx2.bump_utils import handle_no_assertion_or_none from spdx_tools.spdx3.bump_from_spdx2.checksum import bump_checksum -from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion from spdx_tools.spdx3.model import ( - CreationInfo, ExternalIdentifier, ExternalIdentifierType, ExternalMap, @@ -19,7 +17,7 @@ from spdx_tools.spdx3.model.software import Package, SoftwarePurpose from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model import Actor as Spdx2_Actor -from spdx_tools.spdx.model import ExternalDocumentRef, ExtractedLicensingInfo, SpdxNoAssertion +from spdx_tools.spdx.model import ExternalDocumentRef, SpdxNoAssertion from spdx_tools.spdx.model.package import ExternalPackageRef from spdx_tools.spdx.model.package import Package as Spdx2_Package from spdx_tools.spdx.spdx_element_utils import get_full_element_spdx_id @@ -28,9 +26,7 @@ def bump_package( spdx2_package: Spdx2_Package, payload: Payload, - creation_info: CreationInfo, document_namespace: str, - extracted_licensing_info: List[ExtractedLicensingInfo], external_document_refs: List[ExternalDocumentRef], imports: List[ExternalMap], ): @@ -46,11 +42,11 @@ def bump_package( download_location = handle_no_assertion_or_none(spdx2_package.download_location, "package.download_location") print_missing_conversion("package2.file_name", 0, "https://github.com/spdx/spdx-3-model/issues/83") if isinstance(spdx2_package.supplier, Spdx2_Actor): - supplied_by_spdx_id = [bump_actor(spdx2_package.supplier, payload, creation_info, document_namespace)] + supplied_by_spdx_id = [bump_actor(spdx2_package.supplier, payload, document_namespace)] else: supplied_by_spdx_id = None if isinstance(spdx2_package.originator, Spdx2_Actor): - originated_by_spdx_id = [bump_actor(spdx2_package.originator, payload, creation_info, document_namespace)] + originated_by_spdx_id = [bump_actor(spdx2_package.originator, payload, document_namespace)] else: originated_by_spdx_id = None print_missing_conversion("package2.files_analyzed", 0, "https://github.com/spdx/spdx-3-model/issues/84") @@ -58,12 +54,6 @@ def bump_package( "package2.verification_code", 1, "of IntegrityMethod, https://github.com/spdx/spdx-3-model/issues/85" ) integrity_methods = [bump_checksum(checksum) for checksum in spdx2_package.checksums] - declared_license = bump_license_expression_or_none_or_no_assertion( - spdx2_package.license_declared, extracted_licensing_info - ) - concluded_license = bump_license_expression_or_none_or_no_assertion( - spdx2_package.license_concluded, extracted_licensing_info - ) copyright_text = None if isinstance(spdx2_package.copyright_text, str): copyright_text = spdx2_package.copyright_text @@ -99,7 +89,6 @@ def bump_package( Package( spdx_id, spdx2_package.name, - creation_info=creation_info, summary=spdx2_package.summary, description=spdx2_package.description, comment=spdx2_package.comment, @@ -119,8 +108,6 @@ def bump_package( source_info=spdx2_package.source_info, copyright_text=copyright_text, attribution_text=", ".join(spdx2_package.attribution_texts), - concluded_license=concluded_license, - declared_license=declared_license, ) ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py index ee5d35418..918cbdafb 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/relationship.py @@ -7,13 +7,7 @@ from beartype.typing import Dict, List, Optional, Tuple, Union from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model import ( - CreationInfo, - LifecycleScopeType, - Relationship, - RelationshipCompleteness, - RelationshipType, -) +from spdx_tools.spdx3.model import LifecycleScopeType, Relationship, RelationshipCompleteness, RelationshipType from spdx_tools.spdx3.model.software import ( DependencyConditionalityType, SoftwareDependencyLinkType, @@ -158,12 +152,11 @@ def bump_relationships( spdx2_relationships: List[Spdx2_Relationship], payload: Payload, - creation_info: CreationInfo, document_namespace: str, ): generated_relationships: Dict[Tuple[str, str], List[Relationship]] = {} for counter, spdx2_relationship in enumerate(spdx2_relationships): - relationship = bump_relationship(spdx2_relationship, creation_info, document_namespace, counter) + relationship = bump_relationship(spdx2_relationship, document_namespace, counter) if relationship: generated_relationships.setdefault( (relationship.from_element, relationship.relationship_type.name), [] @@ -178,7 +171,6 @@ def bump_relationships( def bump_relationship( spdx2_relationship: Spdx2_Relationship, - creation_info: CreationInfo, document_namespace: str, counter: int, ) -> Optional[Union[Relationship, SoftwareDependencyRelationship]]: @@ -208,7 +200,6 @@ def bump_relationship( f"{document_namespace}#{from_element}", relationship_type, [f"{document_namespace}#{t}" for t in to], - creation_info=creation_info, comment=spdx2_relationship.comment, completeness=completeness, scope=parameters.get("scope"), @@ -221,7 +212,6 @@ def bump_relationship( f"{document_namespace}#{from_element}", relationship_type, [f"{document_namespace}#{t}" for t in to], - creation_info=creation_info, comment=spdx2_relationship.comment, completeness=completeness, ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py index 7810357a5..b052511c1 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/snippet.py @@ -3,13 +3,12 @@ # SPDX-License-Identifier: Apache-2.0 from beartype.typing import List, Optional, Tuple -from spdx_tools.spdx3.bump_from_spdx2.license_expression import bump_license_expression_or_none_or_no_assertion from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model import CreationInfo, ExternalMap +from spdx_tools.spdx3.model import ExternalMap from spdx_tools.spdx3.model.positive_integer_range import PositiveIntegerRange from spdx_tools.spdx3.model.software import Snippet from spdx_tools.spdx3.payload import Payload -from spdx_tools.spdx.model import ExternalDocumentRef, ExtractedLicensingInfo, SpdxNoAssertion +from spdx_tools.spdx.model import ExternalDocumentRef, SpdxNoAssertion from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet from spdx_tools.spdx.spdx_element_utils import get_full_element_spdx_id @@ -21,9 +20,7 @@ def bump_integer_range(spdx2_range: Optional[Tuple[int, int]]) -> PositiveIntege def bump_snippet( spdx2_snippet: Spdx2_Snippet, payload: Payload, - creation_info: CreationInfo, document_namespace: str, - extracted_licensing_info: List[ExtractedLicensingInfo], external_document_refs: List[ExternalDocumentRef], imports: List[ExternalMap], ): @@ -37,9 +34,6 @@ def bump_snippet( ) print_missing_conversion("snippet.file_spdx_id", 0, "https://github.com/spdx/spdx-3-model/issues/130") - concluded_license = bump_license_expression_or_none_or_no_assertion( - spdx2_snippet.license_concluded, extracted_licensing_info - ) copyright_text = None if isinstance(spdx2_snippet.copyright_text, str): copyright_text = spdx2_snippet.copyright_text @@ -54,13 +48,11 @@ def bump_snippet( payload.add_element( Snippet( spdx_id=spdx_id, - creation_info=creation_info, name=spdx2_snippet.name, comment=spdx2_snippet.comment, byte_range=bump_integer_range(spdx2_snippet.byte_range), line_range=bump_integer_range(spdx2_snippet.line_range), copyright_text=copyright_text, attribution_text=", ".join(spdx2_snippet.attribution_texts), - concluded_license=concluded_license, ) ) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py index 1c17a5de6..0257c403f 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/spdx_document.py @@ -37,9 +37,7 @@ def bump_spdx_document(document: Spdx2_Document) -> Payload: bump_package( spdx2_package, payload, - creation_info, document_namespace, - document.extracted_licensing_info, document.creation_info.external_document_refs, spdx_document.imports, ) @@ -48,9 +46,7 @@ def bump_spdx_document(document: Spdx2_Document) -> Payload: bump_file( spdx2_file, payload, - creation_info, document_namespace, - document.extracted_licensing_info, document.creation_info.external_document_refs, spdx_document.imports, ) @@ -59,14 +55,12 @@ def bump_spdx_document(document: Spdx2_Document) -> Payload: bump_snippet( spdx2_snippet, payload, - creation_info, document_namespace, - document.extracted_licensing_info, document.creation_info.external_document_refs, spdx_document.imports, ) - bump_relationships(document.relationships, payload, creation_info, document_namespace) + bump_relationships(document.relationships, payload, document_namespace) for counter, spdx2_annotation in enumerate(document.annotations): bump_annotation(spdx2_annotation, payload, creation_info, document_namespace, counter) diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index 124341f87..04d6540c5 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -40,7 +40,7 @@ def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_i creation_info = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], [ProfileIdentifier.CORE]) actor = Actor(actor_type, actor_name, actor_mail) - agent_or_tool_id = bump_actor(actor, payload, creation_info, document_namespace) + agent_or_tool_id = bump_actor(actor, payload, document_namespace, creation_info) agent_or_tool = payload.get_element(agent_or_tool_id) assert isinstance(agent_or_tool, element_type) @@ -68,7 +68,7 @@ def test_bump_actor_that_already_exists(): ) actor = Actor(ActorType.PERSON, name, "some@mail.com") - agent_spdx_id = bump_actor(actor, payload, creation_info_new, document_namespace) + agent_spdx_id = bump_actor(actor, payload, document_namespace, creation_info_new) # assert that there is only one Person in the payload assert ( diff --git a/tests/spdx3/bump/test_file_bump.py b/tests/spdx3/bump/test_file_bump.py index ca7dafa5c..06e93db42 100644 --- a/tests/spdx3/bump/test_file_bump.py +++ b/tests/spdx3/bump/test_file_bump.py @@ -1,33 +1,27 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from unittest import mock from spdx_tools.spdx3.bump_from_spdx2.file import bump_file from spdx_tools.spdx3.model import Hash, HashAlgorithm -from spdx_tools.spdx3.model.licensing import ConjunctiveLicenseSet, ListedLicense from spdx_tools.spdx3.model.software import File from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.file import File as Spdx2_File from tests.spdx.fixtures import file_fixture -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_bump_file(creation_info): +def test_bump_file(): payload = Payload() document_namespace = "https://doc.namespace" spdx2_file: Spdx2_File = file_fixture() integrity_method: Hash = Hash(HashAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c") expected_new_file_id = f"{document_namespace}#{spdx2_file.spdx_id}" - bump_file(spdx2_file, payload, creation_info, document_namespace, [], [], []) + bump_file(spdx2_file, payload, document_namespace, [], []) file = payload.get_element(expected_new_file_id) assert isinstance(file, File) assert file.spdx_id == expected_new_file_id assert file.verified_using == [integrity_method] - assert file.concluded_license == ConjunctiveLicenseSet( - [ListedLicense("MIT", "MIT", "blank"), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "blank")] - ) assert file.copyright_text == spdx2_file.copyright_text assert file.attribution_text == spdx2_file.attribution_texts[0] diff --git a/tests/spdx3/bump/test_package_bump.py b/tests/spdx3/bump/test_package_bump.py index 6dc9ab39d..efef7933d 100644 --- a/tests/spdx3/bump/test_package_bump.py +++ b/tests/spdx3/bump/test_package_bump.py @@ -7,13 +7,11 @@ from spdx_tools.spdx3.bump_from_spdx2.package import bump_package from spdx_tools.spdx3.model import ExternalIdentifier, ExternalIdentifierType, ExternalReference, ExternalReferenceType -from spdx_tools.spdx3.model.licensing import ConjunctiveLicenseSet, ListedLicense from spdx_tools.spdx3.model.software import Package from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model import SpdxNoAssertion from spdx_tools.spdx.model.package import ExternalPackageRef, ExternalPackageRefCategory from spdx_tools.spdx.model.package import Package as Spdx2_Package -from tests.spdx3.fixtures import creation_info_fixture from tests.spdx.fixtures import actor_fixture, package_fixture @@ -45,7 +43,7 @@ def test_bump_package(originator, expected_originator, supplier, expected_suppli ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_info_fixture(), document_namespace, [], [], []) + bump_package(spdx2_package, payload, document_namespace, [], []) package = payload.get_element(expected_new_package_id) assert isinstance(package, Package) @@ -68,12 +66,6 @@ def test_bump_package(originator, expected_originator, supplier, expected_suppli assert package.valid_until_time == spdx2_package.valid_until_date assert package.copyright_text == spdx2_package.copyright_text assert package.attribution_text == spdx2_package.attribution_texts[0] - assert package.concluded_license == ConjunctiveLicenseSet( - [ListedLicense("MIT", "MIT", "blank"), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "blank")] - ) - assert package.declared_license == ConjunctiveLicenseSet( - [ListedLicense("MIT", "MIT", "blank"), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "blank")] - ) def test_bump_of_single_purl_without_comment(): @@ -86,7 +78,7 @@ def test_bump_of_single_purl_without_comment(): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_info_fixture(), document_namespace, [], [], []) + bump_package(spdx2_package, payload, document_namespace, [], []) package = payload.get_element(expected_new_package_id) assert package.package_url == "purl_locator" @@ -104,7 +96,7 @@ def test_bump_of_single_purl_with_comment(): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_info_fixture(), document_namespace, [], [], []) + bump_package(spdx2_package, payload, document_namespace, [], []) package = payload.get_element(expected_new_package_id) assert package.package_url is None @@ -125,7 +117,7 @@ def test_bump_of_multiple_purls(): ) expected_new_package_id = f"{document_namespace}#{spdx2_package.spdx_id}" - bump_package(spdx2_package, payload, creation_info_fixture(), document_namespace, [], [], []) + bump_package(spdx2_package, payload, document_namespace, [], []) package = payload.get_element(expected_new_package_id) assert package.package_url is None diff --git a/tests/spdx3/bump/test_relationship_bump.py b/tests/spdx3/bump/test_relationship_bump.py index e865a22c2..cd2910268 100644 --- a/tests/spdx3/bump/test_relationship_bump.py +++ b/tests/spdx3/bump/test_relationship_bump.py @@ -1,8 +1,6 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from unittest import mock - from spdx_tools.spdx3.bump_from_spdx2.relationship import bump_relationship, bump_relationships from spdx_tools.spdx3.model import Relationship, RelationshipCompleteness, RelationshipType from spdx_tools.spdx3.payload import Payload @@ -11,31 +9,28 @@ from tests.spdx.fixtures import relationship_fixture -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_relationship_bump(creation_info): +def test_relationship_bump(): spdx2_relationship = relationship_fixture() document_namespace = "https://doc.namespace" - relationship = bump_relationship(spdx2_relationship, creation_info, document_namespace, 1) + relationship = bump_relationship(spdx2_relationship, document_namespace, 1) assert relationship == Relationship( f"{document_namespace}#SPDXRef-Relationship-1", f"{document_namespace}#{spdx2_relationship.spdx_element_id}", RelationshipType.DESCRIBES, [f"{document_namespace}#{spdx2_relationship.related_spdx_element_id}"], - creation_info=creation_info, comment=spdx2_relationship.comment, ) -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_relationships_bump(creation_info): +def test_relationships_bump(): relationships = [ relationship_fixture(comment=None), relationship_fixture(related_spdx_element_id="SPDXRef-Package", comment=None), ] payload = Payload() document_namespace = "https://doc.namespace" - bump_relationships(relationships, payload, creation_info, document_namespace) + bump_relationships(relationships, payload, document_namespace) assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-1") == Relationship( f"{document_namespace}#SPDXRef-Relationship-1", @@ -45,12 +40,10 @@ def test_relationships_bump(creation_info): f"{document_namespace}#{relationships[0].related_spdx_element_id}", f"{document_namespace}#{relationships[1].related_spdx_element_id}", ], - creation_info=creation_info, ) -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_relationships_bump_with_setting_completeness(creation_info): +def test_relationships_bump_with_setting_completeness(): relationships = [ relationship_fixture(related_spdx_element_id=SpdxNoAssertion()), relationship_fixture(related_spdx_element_id="SPDXRef-Package"), @@ -62,14 +55,13 @@ def test_relationships_bump_with_setting_completeness(creation_info): ] payload = Payload() document_namespace = "https://doc.namespace" - bump_relationships(relationships, payload, creation_info, document_namespace) + bump_relationships(relationships, payload, document_namespace) assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-0") == Relationship( f"{document_namespace}#SPDXRef-Relationship-0", f"{document_namespace}#{relationships[0].spdx_element_id}", RelationshipType.DESCRIBES, [], - creation_info=creation_info, comment=relationships[0].comment, completeness=RelationshipCompleteness.NOASSERTION, ) @@ -78,7 +70,6 @@ def test_relationships_bump_with_setting_completeness(creation_info): f"{document_namespace}#{relationships[1].spdx_element_id}", RelationshipType.DESCRIBES, [f"{document_namespace}#{relationships[1].related_spdx_element_id}"], - creation_info=creation_info, comment=relationships[1].comment, ) assert payload.get_element(f"{document_namespace}#SPDXRef-Relationship-2") == Relationship( @@ -86,13 +77,11 @@ def test_relationships_bump_with_setting_completeness(creation_info): f"{document_namespace}#{relationships[2].spdx_element_id}", RelationshipType.SPECIFICATION_FOR, [], - creation_info=creation_info, completeness=RelationshipCompleteness.COMPLETE, ) -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_undefined_relationship_bump(creation_info, capsys): +def test_undefined_relationship_bump(capsys): relationships = [ relationship_fixture( related_spdx_element_id=SpdxNoAssertion(), relationship_type=Spdx2_RelationshipType.CONTAINED_BY @@ -101,7 +90,7 @@ def test_undefined_relationship_bump(creation_info, capsys): ] payload = Payload() document_namespace = "https://doc.namespace" - bump_relationships(relationships, payload, creation_info, document_namespace) + bump_relationships(relationships, payload, document_namespace) captured = capsys.readouterr() assert ( diff --git a/tests/spdx3/bump/test_snippet_bump.py b/tests/spdx3/bump/test_snippet_bump.py index 6ee2c4237..1ded094b6 100644 --- a/tests/spdx3/bump/test_snippet_bump.py +++ b/tests/spdx3/bump/test_snippet_bump.py @@ -1,30 +1,24 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from unittest import mock from spdx_tools.spdx3.bump_from_spdx2.snippet import bump_snippet -from spdx_tools.spdx3.model.licensing import ConjunctiveLicenseSet, ListedLicense from spdx_tools.spdx3.model.software import Snippet from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.snippet import Snippet as Spdx2_Snippet from tests.spdx.fixtures import snippet_fixture -@mock.patch("spdx_tools.spdx3.model.CreationInfo", autospec=True) -def test_bump_snippet(creation_info): +def test_bump_snippet(): payload = Payload() document_namespace = "https://doc.namespace" spdx2_snippet: Spdx2_Snippet = snippet_fixture() expected_new_snippet_id = f"{document_namespace}#{spdx2_snippet.spdx_id}" - bump_snippet(spdx2_snippet, payload, creation_info, document_namespace, [], [], []) + bump_snippet(spdx2_snippet, payload, document_namespace, [], []) snippet = payload.get_element(expected_new_snippet_id) assert isinstance(snippet, Snippet) assert snippet.spdx_id == expected_new_snippet_id assert snippet.copyright_text == spdx2_snippet.copyright_text assert snippet.attribution_text == spdx2_snippet.attribution_texts[0] - assert snippet.concluded_license == ConjunctiveLicenseSet( - [ListedLicense("MIT", "MIT", "blank"), ListedLicense("GPL-2.0-only", "GPL-2.0-only", "blank")] - ) From 5fcb6954aa851a5925ae2a64952b262510fa7be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 15 Jun 2023 13:29:50 +0200 Subject: [PATCH 287/354] [issue-426] update model: make created_using optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py | 1 - src/spdx_tools/spdx3/model/creation_info.py | 10 ++++++---- tests/spdx3/bump/test_actor_bump.py | 6 +++--- tests/spdx3/fixtures.py | 2 +- tests/spdx3/model/test_creation_info.py | 4 ++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py index b919449a8..4a59f81e2 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py @@ -36,7 +36,6 @@ def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload spec_version=Version("3.0.0"), created=spdx2_creation_info.created, created_by=[], - created_using=[], profile=[ProfileIdentifier.CORE, ProfileIdentifier.SOFTWARE, ProfileIdentifier.LICENSING], data_license="https://spdx.org/licenses/" + spdx2_creation_info.data_license, ) diff --git a/src/spdx_tools/spdx3/model/creation_info.py b/src/spdx_tools/spdx3/model/creation_info.py index 615a30445..71b80f1a5 100644 --- a/src/spdx_tools/spdx3/model/creation_info.py +++ b/src/spdx_tools/spdx3/model/creation_info.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from dataclasses import field from datetime import datetime from beartype.typing import List, Optional @@ -16,9 +17,9 @@ class CreationInfo: spec_version: Version created: datetime created_by: List[str] # SPDXID of Agents - created_using: List[str] # SPDXID of Tools profile: List[ProfileIdentifier] - data_license: str + data_license: Optional[str] = "CC0-1.0" + created_using: List[str] = field(default_factory=list) # SPDXID of Tools comment: Optional[str] = None def __init__( @@ -26,9 +27,10 @@ def __init__( spec_version: Version, created: datetime, created_by: List[str], - created_using: List[str], profile: List[ProfileIdentifier], - data_license: str = "CC0", + data_license: Optional[str] = "CC0-1.0", + created_using: List[str] = None, comment: Optional[str] = None, ): + created_using = [] if created_using is None else created_using check_types_and_set_values(self, locals()) diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index 04d6540c5..c0a4a2af0 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -37,7 +37,7 @@ def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_id): payload = Payload() document_namespace = "https://doc.namespace" - creation_info = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], [ProfileIdentifier.CORE]) + creation_info = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [ProfileIdentifier.CORE]) actor = Actor(actor_type, actor_name, actor_mail) agent_or_tool_id = bump_actor(actor, payload, document_namespace, creation_info) @@ -54,8 +54,8 @@ def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_i def test_bump_actor_that_already_exists(): - creation_info_old = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [], [ProfileIdentifier.CORE]) - creation_info_new = CreationInfo(Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], [], [ProfileIdentifier.CORE]) + creation_info_old = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [ProfileIdentifier.CORE]) + creation_info_new = CreationInfo(Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], [ProfileIdentifier.CORE]) name = "some name" document_namespace = "https://doc.namespace" diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 219135f4b..6c7e9db34 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -101,9 +101,9 @@ def creation_info_fixture( spec_version=spec_version, created=created, created_by=created_by, - created_using=created_using, profile=profile, data_license=data_license, + created_using=created_using, comment=comment, ) diff --git a/tests/spdx3/model/test_creation_info.py b/tests/spdx3/model/test_creation_info.py index 154ae028d..40b6d4536 100644 --- a/tests/spdx3/model/test_creation_info.py +++ b/tests/spdx3/model/test_creation_info.py @@ -32,7 +32,7 @@ def test_correct_initialization(): def test_invalid_initialization(): with pytest.raises(TypeError) as err: - CreationInfo("2.3", "2012-01-01", [], [], "core", 3, []) + CreationInfo("2.3", "2012-01-01", [], "core", 3, [], []) assert len(err.value.args[0]) == 5 for error in err.value.args[0]: @@ -44,6 +44,6 @@ def test_incomplete_initialization(): CreationInfo("2.3") assert ( - "__init__() missing 4 required positional arguments: 'created', 'created_by', 'created_using', and 'profile'" + "__init__() missing 3 required positional arguments: 'created', 'created_by', and 'profile'" in err.value.args[0] ) From 14a0707ab350dfe53832baaea90111f60d14ddaf Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 20 Jun 2023 10:53:08 +0200 Subject: [PATCH 288/354] Add methods to serialize SPDX documents to a stream object rather than always expecting a file name Signed-off-by: Holger Frydrych --- src/spdx_tools/spdx/writer/json/json_writer.py | 18 ++++++++++++++---- src/spdx_tools/spdx/writer/rdf/rdf_writer.py | 11 ++++++++--- .../spdx/writer/tagvalue/tagvalue_writer.py | 8 ++++++-- src/spdx_tools/spdx/writer/xml/xml_writer.py | 18 ++++++++++++++---- src/spdx_tools/spdx/writer/yaml/yaml_writer.py | 18 ++++++++++++++---- 5 files changed, 56 insertions(+), 17 deletions(-) diff --git a/src/spdx_tools/spdx/writer/json/json_writer.py b/src/spdx_tools/spdx/writer/json/json_writer.py index a644bd889..c083e23a7 100644 --- a/src/spdx_tools/spdx/writer/json/json_writer.py +++ b/src/spdx_tools/spdx/writer/json/json_writer.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import json -from beartype.typing import List +from beartype.typing import List, IO from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter @@ -12,9 +12,9 @@ from spdx_tools.spdx.validation.validation_message import ValidationMessage -def write_document_to_file( +def write_document_to_stream( document: Document, - file_name: str, + stream: IO[str], validate: bool = True, converter: DocumentConverter = None, drop_duplicates: bool = True, @@ -33,5 +33,15 @@ def write_document_to_file( if converter is None: converter = DocumentConverter() document_dict = converter.convert(document) + json.dump(document_dict, stream, indent=4) + + +def write_document_to_file( + document: Document, + file_name: str, + validate: bool = True, + converter: DocumentConverter = None, + drop_duplicates: bool = True, +): with open(file_name, "w") as out: - json.dump(document_dict, out, indent=4) + write_document_to_stream(document, out, validate, converter, drop_duplicates) diff --git a/src/spdx_tools/spdx/writer/rdf/rdf_writer.py b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py index 7c85613ec..ec6f3c1d0 100644 --- a/src/spdx_tools/spdx/writer/rdf/rdf_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from beartype.typing import Dict, List +from beartype.typing import Dict, List, IO from rdflib import DOAP, Graph from rdflib.compare import to_isomorphic @@ -19,7 +19,7 @@ from spdx_tools.spdx.writer.rdf.snippet_writer import add_snippet_to_graph -def write_document_to_file(document: Document, file_name: str, validate: bool, drop_duplicates: bool = True): +def write_document_to_stream(document: Document, stream: IO[bytes], validate: bool, drop_duplicates: bool = True): if validate: validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) if validation_messages: @@ -55,4 +55,9 @@ def write_document_to_file(document: Document, file_name: str, validate: bool, d graph.bind("spdx", SPDX_NAMESPACE) graph.bind("doap", DOAP) graph.bind("ptr", POINTER_NAMESPACE) - graph.serialize(file_name, "pretty-xml", encoding="UTF-8", max_depth=100) + graph.serialize(stream, "pretty-xml", encoding="UTF-8", max_depth=100) + + +def write_document_to_file(document: Document, file_name: str, validate: bool, drop_duplicates: bool = True): + with open(file_name, "wb") as out: + write_document_to_stream(document, out, validate, drop_duplicates) diff --git a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py index af58b8af0..33ddcaf94 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py @@ -30,7 +30,7 @@ ) -def write_document_to_file(document: Document, file_name: str, validate: bool = True, drop_duplicates: bool = True): +def write_document_to_stream(document: Document, stream: TextIO, validate: bool = True, drop_duplicates: bool = True): if validate: validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) if validation_messages: @@ -38,8 +38,12 @@ def write_document_to_file(document: Document, file_name: str, validate: bool = if drop_duplicates: document = create_document_without_duplicates(document) + write_document(document, stream) + + +def write_document_to_file(document: Document, file_name: str, validate: bool = True, drop_duplicates: bool = True): with open(file_name, "w") as out: - write_document(document, out) + write_document_to_stream(document, out, validate, drop_duplicates) def write_document(document: Document, text_output: TextIO): diff --git a/src/spdx_tools/spdx/writer/xml/xml_writer.py b/src/spdx_tools/spdx/writer/xml/xml_writer.py index 70484da4b..e534a2413 100644 --- a/src/spdx_tools/spdx/writer/xml/xml_writer.py +++ b/src/spdx_tools/spdx/writer/xml/xml_writer.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 import xmltodict -from beartype.typing import List +from beartype.typing import List, IO from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter @@ -11,9 +11,9 @@ from spdx_tools.spdx.validation.validation_message import ValidationMessage -def write_document_to_file( +def write_document_to_stream( document: Document, - file_name: str, + stream: IO[str], validate: bool = True, converter: DocumentConverter = None, drop_duplicates: bool = True, @@ -33,5 +33,15 @@ def write_document_to_file( if converter is None: converter = DocumentConverter() document_dict = {"Document": converter.convert(document)} + xmltodict.unparse(document_dict, stream, encoding="utf-8", pretty=True) + + +def write_document_to_file( + document: Document, + file_name: str, + validate: bool = True, + converter: DocumentConverter = None, + drop_duplicates: bool = True, +): with open(file_name, "w") as out: - xmltodict.unparse(document_dict, out, encoding="utf-8", pretty=True) + write_document_to_stream(document, out, validate, converter, drop_duplicates) diff --git a/src/spdx_tools/spdx/writer/yaml/yaml_writer.py b/src/spdx_tools/spdx/writer/yaml/yaml_writer.py index 5211fd3de..92b13834e 100644 --- a/src/spdx_tools/spdx/writer/yaml/yaml_writer.py +++ b/src/spdx_tools/spdx/writer/yaml/yaml_writer.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 import yaml -from beartype.typing import List +from beartype.typing import List, IO from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter @@ -11,9 +11,9 @@ from spdx_tools.spdx.validation.validation_message import ValidationMessage -def write_document_to_file( +def write_document_to_stream( document: Document, - file_name: str, + stream: IO[str], validate: bool = True, converter: DocumentConverter = None, drop_duplicates: bool = True, @@ -32,5 +32,15 @@ def write_document_to_file( if converter is None: converter = DocumentConverter() document_dict = converter.convert(document) + yaml.safe_dump(document_dict, stream, indent=2) + + +def write_document_to_file( + document: Document, + file_name: str, + validate: bool = True, + converter: DocumentConverter = None, + drop_duplicates: bool = True, +): with open(file_name, "w") as out: - yaml.safe_dump(document_dict, out, indent=2) + write_document_to_stream(document, out, validate, converter, drop_duplicates) From 08e9c03f009d9a5cb11cff9d7d1eba25d7d10b69 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 20 Jun 2023 11:13:41 +0200 Subject: [PATCH 289/354] Extract common validation, deduplication and conversion code for the writers Signed-off-by: Holger Frydrych --- .../spdx/writer/json/json_writer.py | 17 +++--------- src/spdx_tools/spdx/writer/rdf/rdf_writer.py | 13 +++------- .../spdx/writer/tagvalue/tagvalue_writer.py | 14 +++------- src/spdx_tools/spdx/writer/write_utils.py | 26 +++++++++++++++++++ src/spdx_tools/spdx/writer/xml/xml_writer.py | 18 +++---------- .../spdx/writer/yaml/yaml_writer.py | 17 +++--------- 6 files changed, 44 insertions(+), 61 deletions(-) create mode 100644 src/spdx_tools/spdx/writer/write_utils.py diff --git a/src/spdx_tools/spdx/writer/json/json_writer.py b/src/spdx_tools/spdx/writer/json/json_writer.py index c083e23a7..42c1a8335 100644 --- a/src/spdx_tools/spdx/writer/json/json_writer.py +++ b/src/spdx_tools/spdx/writer/json/json_writer.py @@ -3,13 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 import json -from beartype.typing import List, IO +from beartype.typing import IO -from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter from spdx_tools.spdx.model import Document -from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document -from spdx_tools.spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.writer.write_utils import convert, validate_and_deduplicate def write_document_to_stream( @@ -24,15 +22,8 @@ def write_document_to_stream( to False, validates the document before serialization. Unless a DocumentConverter instance is provided, a new one is created. """ - if validate: - validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) - if validation_messages: - raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}") - if drop_duplicates: - document = create_document_without_duplicates(document) - if converter is None: - converter = DocumentConverter() - document_dict = converter.convert(document) + document = validate_and_deduplicate(document, validate, drop_duplicates) + document_dict = convert(document, converter) json.dump(document_dict, stream, indent=4) diff --git a/src/spdx_tools/spdx/writer/rdf/rdf_writer.py b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py index ec6f3c1d0..7756e56c6 100644 --- a/src/spdx_tools/spdx/writer/rdf/rdf_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py @@ -1,15 +1,12 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from beartype.typing import Dict, List, IO +from beartype.typing import IO, Dict from rdflib import DOAP, Graph from rdflib.compare import to_isomorphic -from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.model import Document from spdx_tools.spdx.rdfschema.namespace import POINTER_NAMESPACE, SPDX_NAMESPACE -from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document -from spdx_tools.spdx.validation.validation_message import ValidationMessage from spdx_tools.spdx.writer.rdf.annotation_writer import add_annotation_to_graph from spdx_tools.spdx.writer.rdf.creation_info_writer import add_creation_info_to_graph from spdx_tools.spdx.writer.rdf.extracted_licensing_info_writer import add_extracted_licensing_info_to_graph @@ -17,15 +14,11 @@ from spdx_tools.spdx.writer.rdf.package_writer import add_package_to_graph from spdx_tools.spdx.writer.rdf.relationship_writer import add_relationship_to_graph from spdx_tools.spdx.writer.rdf.snippet_writer import add_snippet_to_graph +from spdx_tools.spdx.writer.write_utils import validate_and_deduplicate def write_document_to_stream(document: Document, stream: IO[bytes], validate: bool, drop_duplicates: bool = True): - if validate: - validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) - if validation_messages: - raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}") - if drop_duplicates: - document = create_document_without_duplicates(document) + document = validate_and_deduplicate(document, validate, drop_duplicates) graph = Graph() doc_namespace = document.creation_info.document_namespace external_doc_ref_to_namespace: Dict[str, str] = { diff --git a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py index 33ddcaf94..50615fa18 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py @@ -8,12 +8,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from beartype.typing import List, TextIO +from beartype.typing import TextIO -from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.model import Document, Relationship, RelationshipType -from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document -from spdx_tools.spdx.validation.validation_message import ValidationMessage from spdx_tools.spdx.writer.tagvalue.annotation_writer import write_annotation from spdx_tools.spdx.writer.tagvalue.creation_info_writer import write_creation_info from spdx_tools.spdx.writer.tagvalue.extracted_licensing_info_writer import write_extracted_licensing_info @@ -28,16 +25,11 @@ write_optional_heading, write_separator, ) +from spdx_tools.spdx.writer.write_utils import validate_and_deduplicate def write_document_to_stream(document: Document, stream: TextIO, validate: bool = True, drop_duplicates: bool = True): - if validate: - validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) - if validation_messages: - raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}") - if drop_duplicates: - document = create_document_without_duplicates(document) - + document = validate_and_deduplicate(document, validate, drop_duplicates) write_document(document, stream) diff --git a/src/spdx_tools/spdx/writer/write_utils.py b/src/spdx_tools/spdx/writer/write_utils.py new file mode 100644 index 000000000..13a48bb80 --- /dev/null +++ b/src/spdx_tools/spdx/writer/write_utils.py @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from beartype.typing import List + +from spdx_tools.spdx.document_utils import create_document_without_duplicates +from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter +from spdx_tools.spdx.model import Document +from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document +from spdx_tools.spdx.validation.validation_message import ValidationMessage + + +def validate_and_deduplicate(document: Document, validate: bool = True, drop_duplicates: bool = True) -> Document: + if validate: + validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) + if validation_messages: + raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}") + if drop_duplicates: + document = create_document_without_duplicates(document) + return document + + +def convert(document: Document, converter: DocumentConverter) -> dict: + if converter is None: + converter = DocumentConverter() + return converter.convert(document) diff --git a/src/spdx_tools/spdx/writer/xml/xml_writer.py b/src/spdx_tools/spdx/writer/xml/xml_writer.py index e534a2413..042093513 100644 --- a/src/spdx_tools/spdx/writer/xml/xml_writer.py +++ b/src/spdx_tools/spdx/writer/xml/xml_writer.py @@ -2,13 +2,11 @@ # # SPDX-License-Identifier: Apache-2.0 import xmltodict -from beartype.typing import List, IO +from beartype.typing import IO -from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter from spdx_tools.spdx.model import Document -from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document -from spdx_tools.spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.writer.write_utils import convert, validate_and_deduplicate def write_document_to_stream( @@ -23,16 +21,8 @@ def write_document_to_stream( to False, validates the document before serialization. Unless a DocumentConverter instance is provided, a new one is created. """ - if validate: - validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) - if validation_messages: - raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}") - if drop_duplicates: - document = create_document_without_duplicates(document) - - if converter is None: - converter = DocumentConverter() - document_dict = {"Document": converter.convert(document)} + document = validate_and_deduplicate(document, validate, drop_duplicates) + document_dict = {"Document": convert(document, converter)} xmltodict.unparse(document_dict, stream, encoding="utf-8", pretty=True) diff --git a/src/spdx_tools/spdx/writer/yaml/yaml_writer.py b/src/spdx_tools/spdx/writer/yaml/yaml_writer.py index 92b13834e..997120e81 100644 --- a/src/spdx_tools/spdx/writer/yaml/yaml_writer.py +++ b/src/spdx_tools/spdx/writer/yaml/yaml_writer.py @@ -2,13 +2,11 @@ # # SPDX-License-Identifier: Apache-2.0 import yaml -from beartype.typing import List, IO +from beartype.typing import IO -from spdx_tools.spdx.document_utils import create_document_without_duplicates from spdx_tools.spdx.jsonschema.document_converter import DocumentConverter from spdx_tools.spdx.model import Document -from spdx_tools.spdx.validation.document_validator import validate_full_spdx_document -from spdx_tools.spdx.validation.validation_message import ValidationMessage +from spdx_tools.spdx.writer.write_utils import convert, validate_and_deduplicate def write_document_to_stream( @@ -23,15 +21,8 @@ def write_document_to_stream( to False, validates the document before serialization. Unless a DocumentConverter instance is provided, a new one is created. """ - if validate: - validation_messages: List[ValidationMessage] = validate_full_spdx_document(document) - if validation_messages: - raise ValueError(f"Document is not valid. The following errors were detected: {validation_messages}") - if drop_duplicates: - document = create_document_without_duplicates(document) - if converter is None: - converter = DocumentConverter() - document_dict = converter.convert(document) + document = validate_and_deduplicate(document, validate, drop_duplicates) + document_dict = convert(document, converter) yaml.safe_dump(document_dict, stream, indent=2) From 00c355df4f54b102497739a60f91ccfdacc01284 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 20 Jun 2023 14:51:56 +0200 Subject: [PATCH 290/354] Execute test_graph_generation as part of the regular test run rather than a separate step in the pipeline. Background: there is currently an issue with newer patch versions of Python 3.7 on macos, which are missing bz2 support, thus leading to a failure to include the optional networkx package. This in turn results in that particular test being skipped. But if it runs as a separate step in the pipeline, this means that no tests will execute at all in that step and it will then be marked as an overall failure. See https://github.com/actions/setup-python/issues/682 Signed-off-by: Holger Frydrych --- .github/workflows/install_and_test.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/install_and_test.yml b/.github/workflows/install_and_test.yml index 637d6a473..02a36bc22 100644 --- a/.github/workflows/install_and_test.yml +++ b/.github/workflows/install_and_test.yml @@ -29,13 +29,9 @@ jobs: python -m pip install --upgrade ./dist/*.whl python -m pip install pytest python -m pip install pyshacl + python -m pip install networkx shell: bash - name: Run tests run: pytest - name: Run CLI run: pyspdxtools -i ./tests/spdx/data/SPDXJSONExample-v2.3.spdx.json - - - name: Install optional dependencies - run: python -m pip install networkx - - name: Run tests for graph generation - run: pytest tests/spdx/test_graph_generation.py From e021793c9cadd05ce77336a4469c8daa6dc2be58 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Wed, 21 Jun 2023 10:34:20 +0200 Subject: [PATCH 291/354] Create new Github workflow to build a release when a tag is pushed Signed-off-by: Holger Frydrych --- .github/workflows/prepare_release.yml | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .github/workflows/prepare_release.yml diff --git a/.github/workflows/prepare_release.yml b/.github/workflows/prepare_release.yml new file mode 100644 index 000000000..2dc4ce3e1 --- /dev/null +++ b/.github/workflows/prepare_release.yml @@ -0,0 +1,40 @@ +name: Prepare release + +on: + push: + tags: [ 'v*.*.*'] + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.7' + - name: Set up dependencies + run: | + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools wheel setuptools_scm build twine + python -m pip install -e . + shell: bash + - name: Build wheel + run: python -m build + - name: Verify build + run: twine check dist/* + - name: Create build archive + uses: a7ul/tar-action@v1.1.0 + with: + command: c + files: dist + outPath: spdx_tools_dist.tar.gz + - name: Create GitHub release + uses: softprops/action-gh-release@v1 + with: + files: spdx_tools_dist.tar.gz + generate_release_notes: true + draft: true From e27cef9441124b7ef883406f3bb02ac910f33643 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Wed, 21 Jun 2023 11:57:37 +0200 Subject: [PATCH 292/354] Add missing license headers to workflow files Signed-off-by: Holger Frydrych --- .github/workflows/check_codestyle.yml | 4 ++++ .github/workflows/install_and_test.yml | 4 ++++ .github/workflows/prepare_release.yml | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/.github/workflows/check_codestyle.yml b/.github/workflows/check_codestyle.yml index 89f6a13b5..15dfd17f9 100644 --- a/.github/workflows/check_codestyle.yml +++ b/.github/workflows/check_codestyle.yml @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + name: Run Linter on: diff --git a/.github/workflows/install_and_test.yml b/.github/workflows/install_and_test.yml index 02a36bc22..eadbc8b67 100644 --- a/.github/workflows/install_and_test.yml +++ b/.github/workflows/install_and_test.yml @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + name: Install and Test on: diff --git a/.github/workflows/prepare_release.yml b/.github/workflows/prepare_release.yml index 2dc4ce3e1..1197a3d1d 100644 --- a/.github/workflows/prepare_release.yml +++ b/.github/workflows/prepare_release.yml @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 + name: Prepare release on: From 5c99b5caad82cc9db6b24bc46863e47bf0be138d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 13 Apr 2023 16:25:47 +0200 Subject: [PATCH 293/354] [issue-413] add workflow for circle conversion integration test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .github/workflows/integration_test.yml | 43 ++ .../circleConversionTestInitialDocument.json | 433 ++++++++++++++++++ 2 files changed, 476 insertions(+) create mode 100644 .github/workflows/integration_test.yml create mode 100644 tests/spdx/data/circleConversionTestInitialDocument.json diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml new file mode 100644 index 000000000..2a37fa7a6 --- /dev/null +++ b/.github/workflows/integration_test.yml @@ -0,0 +1,43 @@ +name: Circle conversion test + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +jobs: + install_and_test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Set up Python 3.11 + uses: actions/setup-python@v4 + with: + python-version: 3.11 + - name: Installation + run: | + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools wheel setuptools_scm build + python -m build -nwx . + python -m pip install --upgrade ./dist/*.whl + shell: bash + - name: Install jd + uses: jaxxstorm/action-install-gh-release@v1.10.0 + with: # Grab the latest version + repo: josephburnett/jd + platform: linux + extension-matching: disable + rename-to: jd + chmod: 0755 + - name: Run CLI + run: | + pyspdxtools -i ./tests/spdx/data/circleConversionTestInitialDocument.json -o circleTest.yaml + pyspdxtools -i circleTest.yaml -o circleTest.xml + pyspdxtools -i circleTest.xml -o circleTest.rdf + pyspdxtools -i circleTest.rdf -o circleTest.spdx + pyspdxtools -i circleTest.spdx -o circleTest.json + - name: Compare initial and final json document of the circle conversion test + run: jd -set ./tests/spdx/data/circleConversionTestInitialDocument.json circleTest.json diff --git a/tests/spdx/data/circleConversionTestInitialDocument.json b/tests/spdx/data/circleConversionTestInitialDocument.json new file mode 100644 index 000000000..40e61a19c --- /dev/null +++ b/tests/spdx/data/circleConversionTestInitialDocument.json @@ -0,0 +1,433 @@ +{ + "SPDXID": "SPDXRef-DOCUMENT", + "spdxVersion": "SPDX-2.3", + "creationInfo": { + "comment": "This package has been shipped in source and binary form.\nThe binaries were created with gcc 4.5.1 and expect to link to\ncompatible system run time libraries.", + "created": "2010-01-29T18:30:22Z", + "creators": [ + "Tool: LicenseFind-1.0", + "Organization: ExampleCodeInspect", + "Person: Jane Doe" + ], + "licenseListVersion": "3.17" + }, + "name": "SPDX-Tools-v2.0", + "dataLicense": "CC0-1.0", + "comment": "This document was created using SPDX 2.0 using licenses from the web site.", + "externalDocumentRefs": [ + { + "externalDocumentId": "DocumentRef-spdx-tool-1.2", + "checksum": { + "algorithm": "SHA1", + "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2759" + }, + "spdxDocument": "http://spdx.org/spdxdocs/spdx-tools-v1.2-3F2504E0-4F89-41D3-9A0C-0305E82C3301" + } + ], + "hasExtractedLicensingInfos": [ + { + "licenseId": "LicenseRef-1", + "extractedText": "/*\n * (c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/" + }, + { + "licenseId": "LicenseRef-2", + "extractedText": "This package includes the GRDDL parser developed by Hewlett Packard under the following license:\n© Copyright 2007 Hewlett-Packard Development Company, LP\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: \n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. \nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. \nThe name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. \nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + }, + { + "licenseId": "LicenseRef-4", + "extractedText": "/*\n * (c) Copyright 2009 University of Bristol\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. The name of the author may not be used to endorse or promote products\n * derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/" + }, + { + "licenseId": "LicenseRef-Beerware-4.2", + "comment": "The beerware license has a couple of other standard variants.", + "extractedText": "\"THE BEER-WARE LICENSE\" (Revision 42):\nphk@FreeBSD.ORG wrote this file. As long as you retain this notice you\ncan do whatever you want with this stuff. If we meet some day, and you think this stuff is worth it, you can buy me a beer in return Poul-Henning Kamp", + "name": "Beer-Ware License (Version 42)", + "seeAlsos": [ + "http://people.freebsd.org/~phk/" + ] + }, + { + "licenseId": "LicenseRef-3", + "comment": "This is tye CyperNeko License", + "extractedText": "The CyberNeko Software License, Version 1.0\n\n \n(C) Copyright 2002-2005, Andy Clark. All rights reserved.\n \nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n1. Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer. \n\n2. Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in\n the documentation and/or other materials provided with the\n distribution.\n\n3. The end-user documentation included with the redistribution,\n if any, must include the following acknowledgment: \n \"This product includes software developed by Andy Clark.\"\n Alternately, this acknowledgment may appear in the software itself,\n if and wherever such third-party acknowledgments normally appear.\n\n4. The names \"CyberNeko\" and \"NekoHTML\" must not be used to endorse\n or promote products derived from this software without prior \n written permission. For written permission, please contact \n andyc@cyberneko.net.\n\n5. Products derived from this software may not be called \"CyberNeko\",\n nor may \"CyberNeko\" appear in their name, without prior written\n permission of the author.\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED\nWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS\nBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, \nOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT \nOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR \nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \nOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", + "name": "CyberNeko License", + "seeAlsos": [ + "http://people.apache.org/~andyc/neko/LICENSE", + "http://justasample.url.com" + ] + } + ], + "annotations": [ + { + "annotationDate": "2010-01-29T18:30:22Z", + "annotationType": "OTHER", + "annotator": "Person: Jane Doe", + "comment": "Document level annotation" + }, + { + "annotationDate": "2010-02-10T00:00:00Z", + "annotationType": "REVIEW", + "annotator": "Person: Joe Reviewer", + "comment": "This is just an example. Some of the non-standard licenses look like they are actually BSD 3 clause licenses" + }, + { + "annotationDate": "2011-03-13T00:00:00Z", + "annotationType": "REVIEW", + "annotator": "Person: Suzanne Reviewer", + "comment": "Another example reviewer." + } + ], + "documentNamespace": "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9B0C-0305E82C3301", + "packages": [ + { + "SPDXID": "SPDXRef-Package", + "annotations": [ + { + "annotationDate": "2011-01-29T18:30:22Z", + "annotationType": "OTHER", + "annotator": "Person: Package Commenter", + "comment": "Package level annotation" + } + ], + "attributionTexts": [ + "The GNU C Library is free software. See the file COPYING.LIB for copying conditions, and LICENSES for notices about a few contributions that require these additional notices to be distributed. License copyright years may be listed using range notation, e.g., 1996-2015, indicating that every year in the range, inclusive, is a copyrightable year that would otherwise be listed individually." + ], + "builtDate": "2011-01-29T18:30:22Z", + "checksums": [ + { + "algorithm": "MD5", + "checksumValue": "624c1abb3664f4b35547e7c73864ad24" + }, + { + "algorithm": "SHA1", + "checksumValue": "85ed0817af83a24ad8da68c2b5094de69833983c" + }, + { + "algorithm": "SHA256", + "checksumValue": "11b6d3ee554eedf79299905a98f9b9a04e498210b59f15094c916c91d150efcd" + }, + { + "algorithm": "BLAKE2b-384", + "checksumValue": "aaabd89c926ab525c242e6621f2f5fa73aa4afe3d9e24aed727faaadd6af38b620bdb623dd2b4788b1c8086984af8706" + } + ], + "copyrightText": "Copyright 2008-2010 John Smith", + "description": "The GNU C Library defines functions that are specified by the ISO C standard, as well as additional features specific to POSIX and other derivatives of the Unix operating system, and extensions specific to GNU systems.", + "downloadLocation": "http://ftp.gnu.org/gnu/glibc/glibc-ports-2.15.tar.gz", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceLocator": "cpe:2.3:a:pivotal_software:spring_framework:4.1.0:*:*:*:*:*:*:*", + "referenceType": "cpe23Type" + }, + { + "comment": "This is the external ref for Acme", + "referenceCategory": "OTHER", + "referenceLocator": "acmecorp/acmenator/4.1.3-alpha", + "referenceType": "http://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301#LocationRef-acmeforge" + } + ], + "filesAnalyzed": true, + "homepage": "http://ftp.gnu.org/gnu/glibc", + "licenseComments": "The license for this project changed with the release of version x.y. The version of the project included here post-dates the license change.", + "licenseConcluded": "LGPL-2.0-only", + "licenseDeclared": "LicenseRef-3", + "licenseInfoFromFiles": [ + "GPL-2.0-only", + "LicenseRef-2", + "LicenseRef-1" + ], + "name": "glibc", + "originator": "Organization: ExampleCodeInspect (contact@example.com)", + "packageFileName": "glibc-2.11.1.tar.gz", + "packageVerificationCode": { + "packageVerificationCodeExcludedFiles": [ + "./package.spdx" + ], + "packageVerificationCodeValue": "d6a770ba38583ed4bb4525bd96e50461655d2758" + }, + "primaryPackagePurpose": "SOURCE", + "releaseDate": "2012-01-29T18:30:22Z", + "sourceInfo": "uses glibc-2_11-branch from git://sourceware.org/git/glibc.git.", + "summary": "GNU C library.", + "supplier": "Person: Jane Doe (jane.doe@example.com)", + "validUntilDate": "2014-01-29T18:30:22Z", + "versionInfo": "2.11.1" + }, + { + "SPDXID": "SPDXRef-fromDoap-1", + "copyrightText": "NOASSERTION", + "downloadLocation": "NOASSERTION", + "filesAnalyzed": false, + "homepage": "http://commons.apache.org/proper/commons-lang/", + "licenseConcluded": "NOASSERTION", + "licenseDeclared": "NOASSERTION", + "name": "Apache Commons Lang" + }, + { + "SPDXID": "SPDXRef-fromDoap-0", + "downloadLocation": "https://search.maven.org/remotecontent?filepath=org/apache/jena/apache-jena/3.12.0/apache-jena-3.12.0.tar.gz", + "externalRefs": [ + { + "referenceCategory": "PACKAGE_MANAGER", + "referenceLocator": "pkg:maven/org.apache.jena/apache-jena@3.12.0", + "referenceType": "purl" + } + ], + "filesAnalyzed": false, + "homepage": "http://www.openjena.org/", + "name": "Jena", + "versionInfo": "3.12.0" + }, + { + "SPDXID": "SPDXRef-Saxon", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "85ed0817af83a24ad8da68c2b5094de69833983c" + } + ], + "copyrightText": "Copyright Saxonica Ltd", + "description": "The Saxon package is a collection of tools for processing XML documents.", + "downloadLocation": "https://sourceforge.net/projects/saxon/files/Saxon-B/8.8.0.7/saxonb8-8-0-7j.zip/download", + "filesAnalyzed": false, + "homepage": "http://saxon.sourceforge.net/", + "licenseComments": "Other versions available for a commercial license", + "licenseConcluded": "MPL-1.0", + "licenseDeclared": "MPL-1.0", + "name": "Saxon", + "packageFileName": "saxonB-8.8.zip", + "versionInfo": "8.8" + } + ], + "files": [ + { + "SPDXID": "SPDXRef-DoapSource", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12" + } + ], + "copyrightText": "Copyright 2010, 2011 Source Auditor Inc.", + "fileContributors": [ + "Protecode Inc.", + "SPDX Technical Team Members", + "Open Logic Inc.", + "Source Auditor Inc.", + "Black Duck Software In.c" + ], + "fileName": "./src/org/spdx/parser/DOAPProject.java", + "fileTypes": [ + "SOURCE" + ], + "licenseConcluded": "Apache-2.0", + "licenseInfoInFiles": [ + "Apache-2.0" + ] + }, + { + "SPDXID": "SPDXRef-CommonsLangSrc", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "c2b4e1c67a2d28fced849ee1bb76e7391b93f125" + } + ], + "comment": "This file is used by Jena", + "copyrightText": "Copyright 2001-2011 The Apache Software Foundation", + "fileContributors": [ + "Apache Software Foundation" + ], + "fileName": "./lib-source/commons-lang3-3.1-sources.jar", + "fileTypes": [ + "ARCHIVE" + ], + "licenseConcluded": "Apache-2.0", + "licenseInfoInFiles": [ + "Apache-2.0" + ], + "noticeText": "Apache Commons Lang\nCopyright 2001-2011 The Apache Software Foundation\n\nThis product includes software developed by\nThe Apache Software Foundation (http://www.apache.org/).\n\nThis product includes software from the Spring Framework,\nunder the Apache License 2.0 (see: StringUtils.containsWhitespace())" + }, + { + "SPDXID": "SPDXRef-JenaLib", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "3ab4e1c67a2d28fced849ee1bb76e7391b93f125" + } + ], + "comment": "This file belongs to Jena", + "copyrightText": "(c) Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Hewlett-Packard Development Company, LP", + "fileContributors": [ + "Apache Software Foundation", + "Hewlett Packard Inc." + ], + "fileName": "./lib-source/jena-2.6.3-sources.jar", + "fileTypes": [ + "ARCHIVE" + ], + "licenseComments": "This license is used by Jena", + "licenseConcluded": "LicenseRef-1", + "licenseInfoInFiles": [ + "LicenseRef-1" + ] + }, + { + "SPDXID": "SPDXRef-Specification", + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "fff4e1c67a2d28fced849ee1bb76e7391b93f125" + } + ], + "comment": "Specification Documentation", + "fileName": "./docs/myspec.pdf", + "fileTypes": [ + "DOCUMENTATION" + ] + }, + { + "SPDXID": "SPDXRef-File", + "annotations": [ + { + "annotationDate": "2011-01-29T18:30:22Z", + "annotationType": "OTHER", + "annotator": "Person: File Commenter", + "comment": "File level annotation" + } + ], + "checksums": [ + { + "algorithm": "SHA1", + "checksumValue": "d6a770ba38583ed4bb4525bd96e50461655d2758" + }, + { + "algorithm": "MD5", + "checksumValue": "624c1abb3664f4b35547e7c73864ad24" + } + ], + "comment": "The concluded license was taken from the package level that the file was included in.\nThis information was found in the COPYING.txt file in the xyz directory.", + "copyrightText": "Copyright 2008-2010 John Smith", + "fileContributors": [ + "The Regents of the University of California", + "Modified by Paul Mundt lethal@linux-sh.org", + "IBM Corporation" + ], + "fileName": "./package/foo.c", + "fileTypes": [ + "SOURCE" + ], + "licenseComments": "The concluded license was taken from the package level that the file was included in.", + "licenseConcluded": "LicenseRef-2", + "licenseInfoInFiles": [ + "GPL-2.0-only", + "LicenseRef-2" + ], + "noticeText": "Copyright (c) 2001 Aaron Lehmann aaroni@vitelus.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: \nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." + } + ], + "snippets": [ + { + "SPDXID": "SPDXRef-Snippet", + "comment": "This snippet was identified as significant and highlighted in this Apache-2.0 file, when a commercial scanner identified it as being derived from file foo.c in package xyz which is licensed under GPL-2.0.", + "copyrightText": "Copyright 2008-2010 John Smith", + "licenseComments": "The concluded license was taken from package xyz, from which the snippet was copied into the current file. The concluded license information was found in the COPYING.txt file in package xyz.", + "licenseConcluded": "GPL-2.0-only", + "licenseInfoInSnippets": [ + "GPL-2.0-only" + ], + "name": "from linux kernel", + "ranges": [ + { + "endPointer": { + "offset": 420, + "reference": "SPDXRef-DoapSource" + }, + "startPointer": { + "offset": 310, + "reference": "SPDXRef-DoapSource" + } + }, + { + "endPointer": { + "lineNumber": 23, + "reference": "SPDXRef-DoapSource" + }, + "startPointer": { + "lineNumber": 5, + "reference": "SPDXRef-DoapSource" + } + } + ], + "snippetFromFile": "SPDXRef-DoapSource" + } + ], + "relationships": [ + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-Package" + }, + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relationshipType": "DESCRIBES", + "relatedSpdxElement": "SPDXRef-Package" + }, + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relationshipType": "DESCRIBES", + "relatedSpdxElement": "SPDXRef-File" + }, + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relationshipType": "COPY_OF", + "relatedSpdxElement": "DocumentRef-spdx-tool-1.2:SPDXRef-ToolsElement" + }, + { + "spdxElementId": "SPDXRef-Package", + "relationshipType": "DYNAMIC_LINK", + "relatedSpdxElement": "SPDXRef-Saxon" + }, + { + "spdxElementId": "SPDXRef-CommonsLangSrc", + "relationshipType": "GENERATED_FROM", + "relatedSpdxElement": "NOASSERTION" + }, + { + "spdxElementId": "SPDXRef-JenaLib", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-Package" + }, + { + "spdxElementId": "SPDXRef-Specification", + "relationshipType": "SPECIFICATION_FOR", + "relatedSpdxElement": "SPDXRef-fromDoap-0" + }, + { + "spdxElementId": "SPDXRef-File", + "relationshipType": "GENERATED_FROM", + "relatedSpdxElement": "SPDXRef-fromDoap-0" + }, + { + "spdxElementId": "SPDXRef-Package", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-Specification" + }, + { + "spdxElementId": "SPDXRef-Package", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-CommonsLangSrc" + }, + { + "spdxElementId": "SPDXRef-Package", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-JenaLib" + }, + { + "spdxElementId": "SPDXRef-Package", + "relationshipType": "CONTAINS", + "relatedSpdxElement": "SPDXRef-DoapSource" + } + ] +} From 2330f4ae1c77ec76f3f7616343a2e6a55629f8a4 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Fri, 23 Jun 2023 15:30:00 +0200 Subject: [PATCH 294/354] Add example for parsing and using an existing SPDX2 document Signed-off-by: Holger Frydrych --- examples/spdx2_parse_file.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 examples/spdx2_parse_file.py diff --git a/examples/spdx2_parse_file.py b/examples/spdx2_parse_file.py new file mode 100644 index 000000000..878b0aefc --- /dev/null +++ b/examples/spdx2_parse_file.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import logging +from os import path + +from spdx_tools.spdx.model.document import Document +from spdx_tools.spdx.parser.error import SPDXParsingError +from spdx_tools.spdx.parser.parse_anything import parse_file + +# This example demonstrates how to parse an existing spdx file. + +# Provide a path to the input file +input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx") +document: Document +try: + # Try to parse the input file. If successful, returns a Document, otherwise raises an SPDXParsingError + document = parse_file(input_path) +except SPDXParsingError: + logging.exception("Failed to parse spdx file") + +# We can now access attributes from the parsed document +print(f"Parsed document name: {document.creation_info.name}") +creators_as_str = ", ".join([creator.to_serialized_string() for creator in document.creation_info.creators]) +print(f"Created on {document.creation_info.created} by {creators_as_str}") From 279e0953ceae7b5b7398f853a1512c7840f8237f Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 27 Jun 2023 09:07:32 +0200 Subject: [PATCH 295/354] Add example for converting SPDX 2 to 3 Signed-off-by: Holger Frydrych --- examples/spdx2_convert_to_spdx3.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 examples/spdx2_convert_to_spdx3.py diff --git a/examples/spdx2_convert_to_spdx3.py b/examples/spdx2_convert_to_spdx3.py new file mode 100644 index 000000000..dbd2cc06f --- /dev/null +++ b/examples/spdx2_convert_to_spdx3.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from os import path + +from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload + +from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document + +from spdx_tools.spdx.parser.parse_anything import parse_file + +# This example demonstrates how to load an existing SPDX2 file and convert it to the SPDX3 format + +# Provide a path to the input file +input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx") +# Parse the original SPDX2 input file +spdx2_document = parse_file(input_path) +# Convert original document to an SPDX3 payload +spdx3_payload = bump_spdx_document(spdx2_document) +# Write SPDX3 payload in json-ld format +write_payload(spdx3_payload, "spdx2_to_3.json") From e7df27d543820ba1cb0048ddc0972dd03cf2aa3c Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 27 Jun 2023 09:08:09 +0200 Subject: [PATCH 296/354] SPDX 2 to 3 conversion should not fail if external_document_refs are empty Signed-off-by: Holger Frydrych --- .../spdx3/bump_from_spdx2/creation_info.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py index 4a59f81e2..54ac666eb 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py @@ -19,11 +19,15 @@ def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload print_missing_conversion("creation_info.document_namespace", 0, "https://github.com/spdx/spdx-3-model/issues/87") - namespaces, imports = zip( - *[ - bump_external_document_ref(external_document_ref) - for external_document_ref in spdx2_creation_info.external_document_refs - ] + namespaces, imports = ( + zip( + *[ + bump_external_document_ref(external_document_ref) + for external_document_ref in spdx2_creation_info.external_document_refs + ] + ) + if spdx2_creation_info.external_document_refs + else ([], []) ) namespaces = list(namespaces) imports = list(imports) From 02bb169691e257906021477754bd21e5741c71c2 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 27 Jun 2023 09:08:30 +0200 Subject: [PATCH 297/354] SPDX 2 to 3 conversion should not fail if primary_package_purpose is empty Signed-off-by: Holger Frydrych --- src/spdx_tools/spdx3/bump_from_spdx2/package.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/package.py b/src/spdx_tools/spdx3/bump_from_spdx2/package.py index a7414d1b4..3d358babd 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/package.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/package.py @@ -83,7 +83,9 @@ def bump_package( elif isinstance(id_or_ref, ExternalIdentifier): external_identifier.append(id_or_ref) - package_purpose = SoftwarePurpose[spdx2_package.primary_package_purpose.name] + package_purpose = ( + SoftwarePurpose[spdx2_package.primary_package_purpose.name] if spdx2_package.primary_package_purpose else None + ) payload.add_element( Package( From d01af72bab31c1baf9dfe8c9d8c6a222b57b7551 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 27 Jun 2023 11:28:20 +0200 Subject: [PATCH 298/354] Add tests for the examples to ensure they are working in principle Signed-off-by: Holger Frydrych --- examples/spdx2_convert_to_spdx3.py | 2 +- tests/spdx/examples/test_examples.py | 43 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tests/spdx/examples/test_examples.py diff --git a/examples/spdx2_convert_to_spdx3.py b/examples/spdx2_convert_to_spdx3.py index dbd2cc06f..fbdda317e 100644 --- a/examples/spdx2_convert_to_spdx3.py +++ b/examples/spdx2_convert_to_spdx3.py @@ -18,4 +18,4 @@ # Convert original document to an SPDX3 payload spdx3_payload = bump_spdx_document(spdx2_document) # Write SPDX3 payload in json-ld format -write_payload(spdx3_payload, "spdx2_to_3.json") +write_payload(spdx3_payload, "spdx2_to_3") diff --git a/tests/spdx/examples/test_examples.py b/tests/spdx/examples/test_examples.py new file mode 100644 index 000000000..1b3f8af8c --- /dev/null +++ b/tests/spdx/examples/test_examples.py @@ -0,0 +1,43 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import os.path +import runpy + +import pytest + + +@pytest.fixture +def cleanup_output_files(): + yield + + files_to_delete = ["spdx2_to_3.jsonld", "my_spdx_document.spdx.json"] + for file in files_to_delete: + output_file = os.path.join(os.path.dirname(__file__), file) + if os.path.exists(output_file): + os.remove(output_file) + + +def run_example(example_file: str): + file_path = os.path.join(os.path.dirname(__file__), "../../../examples/", example_file) + runpy.run_path(file_path) + + +def test_spdx2_parse_file(): + run_example("spdx2_parse_file.py") + + +@pytest.mark.usefixtures('cleanup_output_files') +def test_spdx2_convert_to_spdx3(): + run_example("spdx2_convert_to_spdx3.py") + + output_file = os.path.join(os.path.dirname(__file__), "spdx2_to_3.jsonld") + assert os.path.exists(output_file) + + +@pytest.mark.usefixtures('cleanup_output_files') +def test_spdx2_document_from_scratch(): + run_example("spdx2_document_from_scratch.py") + + output_file = os.path.join(os.path.dirname(__file__), "my_spdx_document.spdx.json") + assert os.path.exists(output_file) From 3263db4f0a8581d69e812483cb64c420c8e12e83 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 27 Jun 2023 13:58:02 +0200 Subject: [PATCH 299/354] Add example to convert between SPDX2 file formats Signed-off-by: Holger Frydrych --- examples/spdx2_convert_format.py | 16 ++++++++++++++++ tests/spdx/examples/test_examples.py | 10 +++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 examples/spdx2_convert_format.py diff --git a/examples/spdx2_convert_format.py b/examples/spdx2_convert_format.py new file mode 100644 index 000000000..16fc7fa5f --- /dev/null +++ b/examples/spdx2_convert_format.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from os import path + +from spdx_tools.spdx.writer.write_anything import write_file +from spdx_tools.spdx.parser.parse_anything import parse_file + +# This example demonstrates how to load an existing SPDX2 file and convert it to a different SPDX2 format + +# Provide a path to the input file in tagvalue format +input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx") +# Parse the original input file +document = parse_file(input_path) +# Write to XML file format +write_file(document, "converted_format.xml") diff --git a/tests/spdx/examples/test_examples.py b/tests/spdx/examples/test_examples.py index 1b3f8af8c..9c56951f1 100644 --- a/tests/spdx/examples/test_examples.py +++ b/tests/spdx/examples/test_examples.py @@ -11,7 +11,7 @@ def cleanup_output_files(): yield - files_to_delete = ["spdx2_to_3.jsonld", "my_spdx_document.spdx.json"] + files_to_delete = ["spdx2_to_3.jsonld", "my_spdx_document.spdx.json", "converted_format.xml"] for file in files_to_delete: output_file = os.path.join(os.path.dirname(__file__), file) if os.path.exists(output_file): @@ -41,3 +41,11 @@ def test_spdx2_document_from_scratch(): output_file = os.path.join(os.path.dirname(__file__), "my_spdx_document.spdx.json") assert os.path.exists(output_file) + + +@pytest.mark.usefixtures('cleanup_output_files') +def test_spdx2_convert_format(): + run_example("spdx2_convert_format.py") + + output_file = os.path.join(os.path.dirname(__file__), "converted_format.xml") + assert os.path.exists(output_file) From f886a4885acc76ad7471c156bee66b4f7cf8ff89 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 27 Jun 2023 14:30:03 +0200 Subject: [PATCH 300/354] Add example for generating relationship graphs Signed-off-by: Holger Frydrych --- examples/spdx2_generate_graph.py | 16 ++++++++++++++++ tests/spdx/examples/test_examples.py | 22 ++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 examples/spdx2_generate_graph.py diff --git a/examples/spdx2_generate_graph.py b/examples/spdx2_generate_graph.py new file mode 100644 index 000000000..109f4a604 --- /dev/null +++ b/examples/spdx2_generate_graph.py @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from os import path + +from spdx_tools.spdx.graph_generation import export_graph_from_document +from spdx_tools.spdx.parser.parse_anything import parse_file + +# This example demonstrates how to generate a relationship graph for an SPDX2 document + +# Provide a path to the input file +input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXJSONExample-v2.3.spdx.json") +# Parse the file +document = parse_file(input_path) +# Generate the graph (note: you need to have installed the optional dependency networkx, pygraphviz) +export_graph_from_document(document, "graph.png") diff --git a/tests/spdx/examples/test_examples.py b/tests/spdx/examples/test_examples.py index 9c56951f1..03da24436 100644 --- a/tests/spdx/examples/test_examples.py +++ b/tests/spdx/examples/test_examples.py @@ -11,7 +11,7 @@ def cleanup_output_files(): yield - files_to_delete = ["spdx2_to_3.jsonld", "my_spdx_document.spdx.json", "converted_format.xml"] + files_to_delete = ["spdx2_to_3.jsonld", "my_spdx_document.spdx.json", "converted_format.xml", "graph.png"] for file in files_to_delete: output_file = os.path.join(os.path.dirname(__file__), file) if os.path.exists(output_file): @@ -27,7 +27,7 @@ def test_spdx2_parse_file(): run_example("spdx2_parse_file.py") -@pytest.mark.usefixtures('cleanup_output_files') +@pytest.mark.usefixtures("cleanup_output_files") def test_spdx2_convert_to_spdx3(): run_example("spdx2_convert_to_spdx3.py") @@ -35,7 +35,7 @@ def test_spdx2_convert_to_spdx3(): assert os.path.exists(output_file) -@pytest.mark.usefixtures('cleanup_output_files') +@pytest.mark.usefixtures("cleanup_output_files") def test_spdx2_document_from_scratch(): run_example("spdx2_document_from_scratch.py") @@ -43,9 +43,23 @@ def test_spdx2_document_from_scratch(): assert os.path.exists(output_file) -@pytest.mark.usefixtures('cleanup_output_files') +@pytest.mark.usefixtures("cleanup_output_files") def test_spdx2_convert_format(): run_example("spdx2_convert_format.py") output_file = os.path.join(os.path.dirname(__file__), "converted_format.xml") assert os.path.exists(output_file) + + +@pytest.mark.usefixtures("cleanup_output_files") +def test_spdx2_generate_graph(): + try: + import networkx # noqa F401 + import pygraphviz # noqa F401 + except ImportError: + pytest.skip("Missing optional dependencies") + + run_example("spdx2_generate_graph.py") + + output_file = os.path.join(os.path.dirname(__file__), "graph.png") + assert os.path.exists(output_file) From 70b54e01aa689921589f5517b120ea5a84a9dceb Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 27 Jun 2023 15:06:14 +0200 Subject: [PATCH 301/354] Fix output file paths in pipeline run Signed-off-by: Holger Frydrych --- tests/spdx/examples/test_examples.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/tests/spdx/examples/test_examples.py b/tests/spdx/examples/test_examples.py index 03da24436..95de85576 100644 --- a/tests/spdx/examples/test_examples.py +++ b/tests/spdx/examples/test_examples.py @@ -13,9 +13,8 @@ def cleanup_output_files(): files_to_delete = ["spdx2_to_3.jsonld", "my_spdx_document.spdx.json", "converted_format.xml", "graph.png"] for file in files_to_delete: - output_file = os.path.join(os.path.dirname(__file__), file) - if os.path.exists(output_file): - os.remove(output_file) + if os.path.exists(file): + os.remove(file) def run_example(example_file: str): @@ -30,25 +29,19 @@ def test_spdx2_parse_file(): @pytest.mark.usefixtures("cleanup_output_files") def test_spdx2_convert_to_spdx3(): run_example("spdx2_convert_to_spdx3.py") - - output_file = os.path.join(os.path.dirname(__file__), "spdx2_to_3.jsonld") - assert os.path.exists(output_file) + assert os.path.exists("spdx2_to_3.jsonld") @pytest.mark.usefixtures("cleanup_output_files") def test_spdx2_document_from_scratch(): run_example("spdx2_document_from_scratch.py") - - output_file = os.path.join(os.path.dirname(__file__), "my_spdx_document.spdx.json") - assert os.path.exists(output_file) + assert os.path.exists("my_spdx_document.spdx.json") @pytest.mark.usefixtures("cleanup_output_files") def test_spdx2_convert_format(): run_example("spdx2_convert_format.py") - - output_file = os.path.join(os.path.dirname(__file__), "converted_format.xml") - assert os.path.exists(output_file) + assert os.path.exists("converted_format.xml") @pytest.mark.usefixtures("cleanup_output_files") @@ -60,6 +53,4 @@ def test_spdx2_generate_graph(): pytest.skip("Missing optional dependencies") run_example("spdx2_generate_graph.py") - - output_file = os.path.join(os.path.dirname(__file__), "graph.png") - assert os.path.exists(output_file) + assert os.path.exists("graph.png") From 56fd6022e7ee817b7a37526266d8e3bef088647e Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 27 Jun 2023 17:10:02 +0200 Subject: [PATCH 302/354] Address review comments Signed-off-by: Holger Frydrych --- examples/spdx2_convert_format.py | 9 +++++---- examples/spdx2_convert_to_spdx3.py | 8 ++++---- examples/spdx2_generate_graph.py | 5 +++-- examples/spdx2_parse_file.py | 3 +-- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/examples/spdx2_convert_format.py b/examples/spdx2_convert_format.py index 16fc7fa5f..63cb4a67a 100644 --- a/examples/spdx2_convert_format.py +++ b/examples/spdx2_convert_format.py @@ -3,14 +3,15 @@ # SPDX-License-Identifier: Apache-2.0 from os import path +from spdx_tools.spdx.model import Document from spdx_tools.spdx.writer.write_anything import write_file from spdx_tools.spdx.parser.parse_anything import parse_file # This example demonstrates how to load an existing SPDX2 file and convert it to a different SPDX2 format -# Provide a path to the input file in tagvalue format +# Provide a path to the input file in the originating format input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx") -# Parse the original input file -document = parse_file(input_path) -# Write to XML file format +# Parse the original input file (format is deduced automatically from the file extension) +document: Document = parse_file(input_path) +# Write to a different file format (e.g. XML, format is deduced automatically from the file extension) write_file(document, "converted_format.xml") diff --git a/examples/spdx2_convert_to_spdx3.py b/examples/spdx2_convert_to_spdx3.py index fbdda317e..ebbbbc7c7 100644 --- a/examples/spdx2_convert_to_spdx3.py +++ b/examples/spdx2_convert_to_spdx3.py @@ -3,10 +3,10 @@ # SPDX-License-Identifier: Apache-2.0 from os import path +from spdx_tools.spdx.model import Document +from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx3.writer.json_ld.json_ld_writer import write_payload - from spdx_tools.spdx3.bump_from_spdx2.spdx_document import bump_spdx_document - from spdx_tools.spdx.parser.parse_anything import parse_file # This example demonstrates how to load an existing SPDX2 file and convert it to the SPDX3 format @@ -14,8 +14,8 @@ # Provide a path to the input file input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx") # Parse the original SPDX2 input file -spdx2_document = parse_file(input_path) +spdx2_document: Document = parse_file(input_path) # Convert original document to an SPDX3 payload -spdx3_payload = bump_spdx_document(spdx2_document) +spdx3_payload: Payload = bump_spdx_document(spdx2_document) # Write SPDX3 payload in json-ld format write_payload(spdx3_payload, "spdx2_to_3") diff --git a/examples/spdx2_generate_graph.py b/examples/spdx2_generate_graph.py index 109f4a604..dad7dcfce 100644 --- a/examples/spdx2_generate_graph.py +++ b/examples/spdx2_generate_graph.py @@ -4,6 +4,7 @@ from os import path from spdx_tools.spdx.graph_generation import export_graph_from_document +from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.parse_anything import parse_file # This example demonstrates how to generate a relationship graph for an SPDX2 document @@ -11,6 +12,6 @@ # Provide a path to the input file input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXJSONExample-v2.3.spdx.json") # Parse the file -document = parse_file(input_path) -# Generate the graph (note: you need to have installed the optional dependency networkx, pygraphviz) +document: Document = parse_file(input_path) +# Generate the graph (note: you need to have installed the optional dependencies networkx and pygraphviz) export_graph_from_document(document, "graph.png") diff --git a/examples/spdx2_parse_file.py b/examples/spdx2_parse_file.py index 878b0aefc..a6564e127 100644 --- a/examples/spdx2_parse_file.py +++ b/examples/spdx2_parse_file.py @@ -12,10 +12,9 @@ # Provide a path to the input file input_path = path.join(path.dirname(__file__), "..", "tests", "spdx", "data", "SPDXLite.spdx") -document: Document try: # Try to parse the input file. If successful, returns a Document, otherwise raises an SPDXParsingError - document = parse_file(input_path) + document: Document = parse_file(input_path) except SPDXParsingError: logging.exception("Failed to parse spdx file") From 9a3e1289d982a33a655d4708fa385ec413853207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Fri, 30 Jun 2023 10:41:30 +0200 Subject: [PATCH 303/354] [issue-718] ignore microseconds during datetime conversion to ISO string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx/datetime_conversions.py | 3 +++ tests/spdx/test_datetime_conversions.py | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/spdx_tools/spdx/datetime_conversions.py b/src/spdx_tools/spdx/datetime_conversions.py index 58ac88324..7b54ae91e 100644 --- a/src/spdx_tools/spdx/datetime_conversions.py +++ b/src/spdx_tools/spdx/datetime_conversions.py @@ -16,4 +16,7 @@ def datetime_to_iso_string(date: datetime) -> str: """ Return an ISO-8601 representation of a datetime object. """ + if date.microsecond != 0: + date = date.replace(microsecond=0) # SPDX does not support microseconds + return date.isoformat() + "Z" diff --git a/tests/spdx/test_datetime_conversions.py b/tests/spdx/test_datetime_conversions.py index 4c4b8070f..2c4858ced 100644 --- a/tests/spdx/test_datetime_conversions.py +++ b/tests/spdx/test_datetime_conversions.py @@ -12,6 +12,10 @@ def test_datetime_to_iso_string(): assert datetime_to_iso_string(datetime(2022, 12, 13, 1, 2, 3)) == "2022-12-13T01:02:03Z" +def test_datetime_to_iso_string_with_microseconds(): + assert datetime_to_iso_string(datetime(2022, 12, 13, 1, 2, 3, 666666)) == "2022-12-13T01:02:03Z" + + def test_datetime_from_str(): date_str = "2010-03-04T05:45:11Z" From 2e26b6b1dfa8bc5a7b3c8adbd64f704ed65eab74 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Fri, 23 Jun 2023 12:11:18 +0200 Subject: [PATCH 304/354] Add missing license headers in source files Signed-off-by: Holger Frydrych --- src/spdx_tools/common/typing/constructor_type_errors.py | 3 +++ src/spdx_tools/spdx/parser/parse_anything.py | 1 + src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py | 1 + src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py | 1 + src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py | 1 + .../spdx/writer/tagvalue/extracted_licensing_info_writer.py | 1 + src/spdx_tools/spdx/writer/tagvalue/file_writer.py | 1 + src/spdx_tools/spdx/writer/tagvalue/package_writer.py | 1 + src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py | 1 + src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py | 1 + src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py | 1 + .../spdx/writer/tagvalue/tagvalue_writer_helper_functions.py | 1 + src/spdx_tools/spdx3/model/__init__.py | 3 +++ src/spdx_tools/spdx3/model/dataset/__init__.py | 3 +++ src/spdx_tools/spdx3/model/software/__init__.py | 3 +++ src/spdx_tools/spdx3/writer/console/__init__.py | 3 +++ src/spdx_tools/spdx3/writer/console/tool_writer.py | 1 + tests/spdx/test_cli.py | 3 +++ 18 files changed, 30 insertions(+) diff --git a/src/spdx_tools/common/typing/constructor_type_errors.py b/src/spdx_tools/common/typing/constructor_type_errors.py index e70f53329..a9b4046aa 100644 --- a/src/spdx_tools/common/typing/constructor_type_errors.py +++ b/src/spdx_tools/common/typing/constructor_type_errors.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 from beartype.typing import List diff --git a/src/spdx_tools/spdx/parser/parse_anything.py b/src/spdx_tools/spdx/parser/parse_anything.py index b54bb7694..b91f76111 100644 --- a/src/spdx_tools/spdx/parser/parse_anything.py +++ b/src/spdx_tools/spdx/parser/parse_anything.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright (c) spdx contributors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py b/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py index 5c9bd85ee..71637073f 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/annotation_writer.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2022 spdx contributors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py b/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py index b641c0f53..cf87e1a4e 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/checksum_writer.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2022 spdx contributors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py b/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py index 6987702d5..81fd3586c 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/creation_info_writer.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2022 spdx contributors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py b/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py index 356722859..0e89faa34 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/extracted_licensing_info_writer.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2022 spdx contributors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/spdx_tools/spdx/writer/tagvalue/file_writer.py b/src/spdx_tools/spdx/writer/tagvalue/file_writer.py index d3f3d85e3..0b1d8c8f5 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/file_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/file_writer.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2022 spdx contributors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/spdx_tools/spdx/writer/tagvalue/package_writer.py b/src/spdx_tools/spdx/writer/tagvalue/package_writer.py index 8ba0f8f0e..9be4ec46f 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/package_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/package_writer.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2022 spdx contributors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py b/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py index a9cb9b754..446bc6fd9 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/relationship_writer.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2022 spdx contributors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py b/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py index f5cd2e84d..f6449951f 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/snippet_writer.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2022 spdx contributors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py index 50615fa18..8f12d1a99 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2022 spdx contributors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py index 458d76711..907c155b7 100644 --- a/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py +++ b/src/spdx_tools/spdx/writer/tagvalue/tagvalue_writer_helper_functions.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2022 spdx contributors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/spdx_tools/spdx3/model/__init__.py b/src/spdx_tools/spdx3/model/__init__.py index 6ee016fe2..9bdc62b36 100644 --- a/src/spdx_tools/spdx3/model/__init__.py +++ b/src/spdx_tools/spdx3/model/__init__.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 from spdx_tools.spdx3.model.profile_identifier import ProfileIdentifier from spdx_tools.spdx3.model.creation_info import CreationInfo from spdx_tools.spdx3.model.integrity_method import IntegrityMethod diff --git a/src/spdx_tools/spdx3/model/dataset/__init__.py b/src/spdx_tools/spdx3/model/dataset/__init__.py index 7ccfa13e7..5e2b4e153 100644 --- a/src/spdx_tools/spdx3/model/dataset/__init__.py +++ b/src/spdx_tools/spdx3/model/dataset/__init__.py @@ -1 +1,4 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 from spdx_tools.spdx3.model.dataset.dataset import Dataset, DatasetAvailabilityType, ConfidentialityLevelType diff --git a/src/spdx_tools/spdx3/model/software/__init__.py b/src/spdx_tools/spdx3/model/software/__init__.py index df338b385..f3b157024 100644 --- a/src/spdx_tools/spdx3/model/software/__init__.py +++ b/src/spdx_tools/spdx3/model/software/__init__.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 from spdx_tools.spdx3.model.software.software_purpose import SoftwarePurpose from spdx_tools.spdx3.model.software.file import File from spdx_tools.spdx3.model.software.package import Package diff --git a/src/spdx_tools/spdx3/writer/console/__init__.py b/src/spdx_tools/spdx3/writer/console/__init__.py index 7c191400b..39bbda884 100644 --- a/src/spdx_tools/spdx3/writer/console/__init__.py +++ b/src/spdx_tools/spdx3/writer/console/__init__.py @@ -1,2 +1,5 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 """ This is a temporary package to write the implemented model of spdx_tools.spdx3.0 to console. As soon as serialization formats are properly defined this package can be deleted.""" diff --git a/src/spdx_tools/spdx3/writer/console/tool_writer.py b/src/spdx_tools/spdx3/writer/console/tool_writer.py index 23eeb6a1a..1873263bc 100644 --- a/src/spdx_tools/spdx3/writer/console/tool_writer.py +++ b/src/spdx_tools/spdx3/writer/console/tool_writer.py @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 # Copyright (c) 2023 spdx contributors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/spdx/test_cli.py b/tests/spdx/test_cli.py index 8bdedbb8e..f269c2f5a 100644 --- a/tests/spdx/test_cli.py +++ b/tests/spdx/test_cli.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 import os import pytest From 7a04d6adb89b66726750763ef2fc95a235dbeb0c Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Fri, 30 Jun 2023 11:14:55 +0200 Subject: [PATCH 305/354] Update README for upcoming v0.8 RC release Signed-off-by: Holger Frydrych --- README.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d3ac972d7..8a0ee72e1 100644 --- a/README.md +++ b/README.md @@ -7,21 +7,20 @@ CI status (Linux, macOS and Windows): [![Install and Test][1]][2] [2]: https://github.com/spdx/tools-python/actions/workflows/install_and_test.yml -# Current state, please read! +# Breaking changes v0.7 -> v0.8 -This repository was subject to a major refactoring recently to get ready for the upcoming SPDX v3.0 release. -Therefore, we'd like to encourage you to post any and all issues you find at https://github.com/spdx/tools-python/issues. -If you are looking for the source code of the [current PyPI release](https://pypi.python.org/pypi/spdx-tools), check out -the [v0.7 branch](https://github.com/spdx/tools-python/tree/version/v0.7). -Note, though, that this will only receive bug fixes but no new features. +Please be aware that the upcoming 0.8 release has undergone a significant refactoring in preparation for the upcoming +SPDX v3.0 release, leading to breaking changes in the API. +Please refer to the [migration guide](https://github.com/spdx/tools-python/wiki/How-to-migrate-from-0.7-to-0.8) +to update your existing code. -We encourage you to use the new, refactored version (on the main branch) if you -- want to use the soon-to-be released SPDX v3.0 in the future -- want to perform full validation of your SPDX documents against the v2.2 and v2.3 specification -- want to use the RDF format of SPDX with all v2.3 features. +We encourage new users to work with v0.8.0rc1 directly as the older v0.7 release is in maintenance mode. -If you are planning to migrate from v0.7.x of these tools, -please have a look at the [migration guide](https://github.com/spdx/tools-python/wiki/How-to-migrate-from-0.7-to-0.8). +The main features of v0.8 are: +- experimental support for the upcoming SPDX v3 specification (note, however, that support is neither complete nor + stable at this point, as the spec is still evolving) +- full validation of SPDX documents against the v2.2 and v2.3 specification +- support for SPDX's RDF format with all v2.3 features. # Information From 119298f2dd0f4d9a72fb5760e9b15d291af94452 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Fri, 30 Jun 2023 12:05:29 +0200 Subject: [PATCH 306/354] Update CHANGELOG for v0.8.0rc1 release Signed-off-by: Holger Frydrych --- CHANGELOG.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81dc51c9b..1bf074eb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,37 @@ # Changelog +## v0.8.0rc1 (2023-06-30) + +### New features and changes + +* major refactoring of the library + * new and improved data model + * type hints and type checks have been added to the model classes + * license expressions and SPDX license list are now handled by the `license-expression` package + * to update your existing code, refer to the [migration guide](https://github.com/spdx/tools-python/wiki/How-to-migrate-from-0.7-to-0.8) +* experimental support for the upcoming SPDX v3 specification (note, however, that support is neither complete nor + stable at this point, as the spec is still evolving) +* full validation of SPDX documents against the v2.2 and v2.3 specification +* support for SPDX's RDF format with all v2.3 features +* unified `pysdpxtools` CLI tool replaces separate `pyspdxtools_parser` and `pyspdxtools_convertor` + +### Contributors + +This release was made possible by the following contributors. Thank you very much! + +* Armin Tänzer @armintaenzertng +* Gary O'Neall @goneall +* Gaurav Mishra @GMishx +* HarshvMahawar @HarshvMahawar +* Holger Frydrych @fholger +* Jeff Licquia @licquia +* Kate Stewart @kestewart +* Maximilian Huber @maxhbr +* Meret Behrens @meretp +* Nicolaus Weidner @nicoweidner +* William Armiros @willarmiros + + ## v0.7.1 (2023-03-14) ### New features and changes From c98b3e4aa460509ec03e54639a59d3dd18b839a2 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Thu, 29 Jun 2023 09:21:48 +0200 Subject: [PATCH 307/354] Add GH workflow to generate API docs and deploy them to GH Pages Signed-off-by: Holger Frydrych --- .github/workflows/docs.yml | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/docs.yml diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..095f9ec7a --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +name: Generate API docs + +on: + push: + branches: + - main + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + - name: Install dependencies + run: | + sudo apt-get install graphviz-dev + pip install -e ".[test,graph_generation]" + pip install pdoc + - name: Generate docs + run: pdoc spdx_tools -o docs/ + - name: Upload docs as artifact + uses: actions/upload-pages-artifact@v1 + with: + path: docs/ + + deploy: + needs: build + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - id: deployment + name: Deploy docs to GitHub pages + uses: actions/deploy-pages@v2 From de51774bd358eed3727d63568ecd5775f5be589c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 11 Jul 2023 10:01:08 +0200 Subject: [PATCH 308/354] [issue-713] add link to API doc in the README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8a0ee72e1..9516b5de2 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ This library implements SPDX parsers, convertors, validators and handlers in Pyt - Home: https://github.com/spdx/tools-python - Issues: https://github.com/spdx/tools-python/issues - PyPI: https://pypi.python.org/pypi/spdx-tools +- Browse the API: https://spdx.github.io/tools-python # License From 17602fc2b0ab9c3c7a35341d91b11912224fbc4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 5 Jul 2023 15:53:59 +0200 Subject: [PATCH 309/354] [issue-721] update Actor regex and parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx/parser/actor_parser.py | 52 +++++++++---------- .../parser/tagvalue/test_annotation_parser.py | 2 +- tests/spdx/test_actor_parser.py | 11 ++++ 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/spdx_tools/spdx/parser/actor_parser.py b/src/spdx_tools/spdx/parser/actor_parser.py index 734b41386..14cc4ffb0 100644 --- a/src/spdx_tools/spdx/parser/actor_parser.py +++ b/src/spdx_tools/spdx/parser/actor_parser.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import re -from beartype.typing import Match, Optional, Pattern +from beartype.typing import Match, Pattern from spdx_tools.spdx.model import Actor, ActorType from spdx_tools.spdx.parser.error import SPDXParsingError @@ -14,8 +14,8 @@ class ActorParser: @staticmethod def parse_actor(actor: str) -> Actor: tool_re: Pattern = re.compile(r"^Tool:\s*(.+)", re.UNICODE) - person_re: Pattern = re.compile(r"^Person:\s*(([^(])+)(\((.*)\))?", re.UNICODE) - org_re: Pattern = re.compile(r"^Organization:\s*(([^(])+)(\((.*)\))?", re.UNICODE) + person_re: Pattern = re.compile(r"^Person:\s*(?:(.*)\((.*)\)|(.*))$", re.UNICODE) + org_re: Pattern = re.compile(r"^Organization:\s*(?:(.*)\((.*)\)|(.*))$", re.UNICODE) tool_match: Match = tool_re.match(actor) person_match: Match = person_re.match(actor) org_match: Match = org_re.match(actor) @@ -24,34 +24,30 @@ def parse_actor(actor: str) -> Actor: name: str = tool_match.group(1).strip() if not name: raise SPDXParsingError([f"No name for Tool provided: {actor}."]) - creator = construct_or_raise_parsing_error(Actor, dict(actor_type=ActorType.TOOL, name=name)) + return construct_or_raise_parsing_error(Actor, dict(actor_type=ActorType.TOOL, name=name)) - elif person_match: - name: str = person_match.group(1).strip() - if not name: - raise SPDXParsingError([f"No name for Person provided: {actor}."]) - email: Optional[str] = ActorParser.get_email_or_none(person_match) - creator = construct_or_raise_parsing_error( - Actor, dict(actor_type=ActorType.PERSON, name=name, email=email) - ) + if person_match: + actor_type = ActorType.PERSON + match = person_match elif org_match: - name: str = org_match.group(1).strip() - if not name: - raise SPDXParsingError([f"No name for Organization provided: {actor}."]) - email: Optional[str] = ActorParser.get_email_or_none(org_match) - creator = construct_or_raise_parsing_error( - Actor, dict(actor_type=ActorType.ORGANIZATION, name=name, email=email) - ) + actor_type = ActorType.ORGANIZATION + match = org_match else: raise SPDXParsingError([f"Actor {actor} doesn't match any of person, organization or tool."]) - return creator - - @staticmethod - def get_email_or_none(match: Match) -> Optional[str]: - email_match = match.group(4) - if email_match and email_match.strip(): - email = email_match.strip() + if match.group(3): + return construct_or_raise_parsing_error( + Actor, dict(actor_type=actor_type, name=match.group(3).strip(), email=None) + ) else: - email = None - return email + name = match.group(1) + if not name: + raise SPDXParsingError([f"No name for Actor provided: {actor}."]) + else: + name = name.strip() + + email = match.group(2).strip() + + return construct_or_raise_parsing_error( + Actor, dict(actor_type=actor_type, name=name, email=email if email else None) + ) diff --git a/tests/spdx/parser/tagvalue/test_annotation_parser.py b/tests/spdx/parser/tagvalue/test_annotation_parser.py index 204756187..629fe72e9 100644 --- a/tests/spdx/parser/tagvalue/test_annotation_parser.py +++ b/tests/spdx/parser/tagvalue/test_annotation_parser.py @@ -57,7 +57,7 @@ def test_parse_annotation(): "not match specified grammar rule. Line: 1', 'Error while parsing " "AnnotationDate: Token did not match specified grammar rule. Line: 2']", ), - ("Annotator: Person: ()", "Error while parsing Annotation: [['No name for Person provided: Person: ().']]"), + ("Annotator: Person: ()", "Error while parsing Annotation: [['No name for Actor provided: Person: ().']]"), ( "AnnotationType: REVIEW", "Element Annotation is not the current element in scope, probably the " diff --git a/tests/spdx/test_actor_parser.py b/tests/spdx/test_actor_parser.py index 17d12a296..24002794c 100644 --- a/tests/spdx/test_actor_parser.py +++ b/tests/spdx/test_actor_parser.py @@ -21,7 +21,16 @@ "organization@example.com", ), ("Organization: Example organization ( )", ActorType.ORGANIZATION, "Example organization", None), + ("Person: Example person ()", ActorType.PERSON, "Example person", None), + ("Person: Example person ", ActorType.PERSON, "Example person", None), ("Tool: Example tool ", ActorType.TOOL, "Example tool", None), + ("Tool: Example tool (email@mail.com)", ActorType.TOOL, "Example tool (email@mail.com)", None), + ( + "Organization: (c) Chris Sainty (chris@sainty.com)", + ActorType.ORGANIZATION, + "(c) Chris Sainty", + "chris@sainty.com", + ), ], ) def test_parse_actor(actor_string, expected_type, expected_name, expected_mail): @@ -42,6 +51,8 @@ def test_parse_actor(actor_string, expected_type, expected_name, expected_mail): ["Actor Perso: Jane Doe (jane.doe@example.com) doesn't match any of person, organization or tool."], ), ("Toole Example Tool ()", ["Actor Toole Example Tool () doesn't match any of person, organization or tool."]), + ("Organization:", ["No name for Actor provided: Organization:."]), + ("Person: ( )", ["No name for Actor provided: Person: ( )."]), ], ) def test_parse_invalid_actor(actor_string, expected_message): From f9efcac5477f63e731377cde5ea8dfab26ba8ec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 3 Jul 2023 16:41:09 +0200 Subject: [PATCH 310/354] [issue-722] add calculate_package_verification_code() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit also add calculate_file_checksum(), as this is needed by the package verification code Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx/spdx_element_utils.py | 41 +++++++++++- tests/spdx/test_checksum_calculation.py | 76 +++++++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 tests/spdx/test_checksum_calculation.py diff --git a/src/spdx_tools/spdx/spdx_element_utils.py b/src/spdx_tools/spdx/spdx_element_utils.py index 49b466144..dcb0cf2e2 100644 --- a/src/spdx_tools/spdx/spdx_element_utils.py +++ b/src/spdx_tools/spdx/spdx_element_utils.py @@ -1,9 +1,11 @@ # SPDX-FileCopyrightText: 2022 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +import hashlib + from beartype.typing import List, Union -from spdx_tools.spdx.model import ExternalDocumentRef, File, Package, Snippet +from spdx_tools.spdx.model import ChecksumAlgorithm, ExternalDocumentRef, File, Package, Snippet def get_full_element_spdx_id( @@ -29,3 +31,40 @@ def get_full_element_spdx_id( raise ValueError(f"external id {external_id} not found in external document references") return external_uri + "#" + local_id + + +def calculate_package_verification_code(files: List[File]) -> str: + list_of_file_hashes = [] + for file in files: + file_checksum_value = None + for checksum in file.checksums: + if checksum.algorithm == ChecksumAlgorithm.SHA1: + file_checksum_value = checksum.value + if not file_checksum_value: + try: + file_checksum_value = calculate_file_checksum(file.name, ChecksumAlgorithm.SHA1) + except FileNotFoundError: + raise FileNotFoundError( + f"Cannot calculate package verification code because the file '{file.name}' " + f"provides no SHA1 checksum and can't be found at the specified location." + ) + list_of_file_hashes.append(file_checksum_value) + + list_of_file_hashes.sort() + hasher = hashlib.new("sha1") + hasher.update("".join(list_of_file_hashes).encode("utf-8")) + return hasher.hexdigest() + + +def calculate_file_checksum(file_name: str, hash_algorithm=ChecksumAlgorithm.SHA1) -> str: + BUFFER_SIZE = 65536 + + file_hash = hashlib.new(hash_algorithm.name.lower()) + with open(file_name, "rb") as file_handle: + while True: + data = file_handle.read(BUFFER_SIZE) + if not data: + break + file_hash.update(data) + + return file_hash.hexdigest() diff --git a/tests/spdx/test_checksum_calculation.py b/tests/spdx/test_checksum_calculation.py new file mode 100644 index 000000000..0aa4b3b85 --- /dev/null +++ b/tests/spdx/test_checksum_calculation.py @@ -0,0 +1,76 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +import pytest + +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, File +from spdx_tools.spdx.spdx_element_utils import calculate_file_checksum, calculate_package_verification_code + + +@pytest.fixture +def generate_test_files(tmp_path): + file_path_1 = tmp_path.joinpath("file1") + file_path_2 = tmp_path.joinpath("file2") + + with open(file_path_1, "wb") as file: + file.write(bytes(111)) + with open(file_path_2, "wb") as file: + file.write(bytes(222)) + + yield str(file_path_1), str(file_path_2) + + +def test_file_checksum_calculation(generate_test_files): + filepath1, filepath2 = generate_test_files + checksum = calculate_file_checksum(filepath1, ChecksumAlgorithm.SHA1) + assert checksum == "dd90903d2f566a3922979dd5e18378a075c7ed33" + checksum = calculate_file_checksum(filepath2, ChecksumAlgorithm.SHA1) + assert checksum == "140dc52658e2eeee3fdc4d471cce84fec7253fe3" + + +def test_verification_code_calculation_with_predefined_checksums(generate_test_files): + filepath1, filepath2 = generate_test_files + file1 = File( + filepath1, + "SPDXRef-hello", + [Checksum(ChecksumAlgorithm.SHA1, "20862a6d08391d07d09344029533ec644fac6b21")], + ) + file2 = File( + filepath2, + "SPDXRef-Makefile", + [Checksum(ChecksumAlgorithm.SHA1, "69a2e85696fff1865c3f0686d6c3824b59915c80")], + ) + verification_code = calculate_package_verification_code([file1, file2]) + + assert verification_code == "c6cb0949d7cd7439fce8690262a0946374824639" + + +def test_verification_code_calculation_with_calculated_checksums(generate_test_files): + filepath1, filepath2 = generate_test_files + file1 = File( + filepath1, + "SPDXRef-hello", + [Checksum(ChecksumAlgorithm.MD4, "20862a6d08391d07d09344029533ec644fac6b21")], + ) + file2 = File( + filepath2, + "SPDXRef-Makefile", + [Checksum(ChecksumAlgorithm.MD4, "69a2e85696fff1865c3f0686d6c3824b59915c80")], + ) + verification_code = calculate_package_verification_code([file1, file2]) + + assert verification_code == "6f29d813abb63ee52a47dbcb691ea2e70f956328" + + +def test_verification_code_calculation_with_wrong_file_location(): + unknown_file_name = "./unknown_file_name" + file1 = File( + unknown_file_name, + "SPDXRef-unknown", + [Checksum(ChecksumAlgorithm.MD4, "20862a6d08391d07d09344029533ec644fac6b21")], + ) + + with pytest.raises(FileNotFoundError) as err: + calculate_package_verification_code([file1]) + + assert unknown_file_name in str(err.value) From 8e8a246df6a1ede16181823d9d540741fa70c096 Mon Sep 17 00:00:00 2001 From: Holger Frydrych Date: Tue, 11 Jul 2023 16:52:24 +0200 Subject: [PATCH 311/354] SPDX3: rename ProfileIdentifier to ProfileIdentifierType to be consistent with the naming in the spec Signed-off-by: Holger Frydrych --- src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py | 4 ++-- src/spdx_tools/spdx3/model/__init__.py | 2 +- src/spdx_tools/spdx3/model/creation_info.py | 6 +++--- src/spdx_tools/spdx3/model/profile_identifier.py | 2 +- tests/spdx3/bump/test_actor_bump.py | 8 ++++---- tests/spdx3/fixtures.py | 4 ++-- tests/spdx3/model/test_creation_info.py | 8 ++++---- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py index 54ac666eb..914d12226 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/creation_info.py @@ -7,7 +7,7 @@ from spdx_tools.spdx3.bump_from_spdx2.actor import bump_actor from spdx_tools.spdx3.bump_from_spdx2.external_document_ref import bump_external_document_ref from spdx_tools.spdx3.bump_from_spdx2.message import print_missing_conversion -from spdx_tools.spdx3.model import CreationInfo, ProfileIdentifier, SpdxDocument +from spdx_tools.spdx3.model import CreationInfo, ProfileIdentifierType, SpdxDocument from spdx_tools.spdx3.payload import Payload from spdx_tools.spdx.model.actor import ActorType from spdx_tools.spdx.model.document import CreationInfo as Spdx2_CreationInfo @@ -40,7 +40,7 @@ def bump_creation_info(spdx2_creation_info: Spdx2_CreationInfo, payload: Payload spec_version=Version("3.0.0"), created=spdx2_creation_info.created, created_by=[], - profile=[ProfileIdentifier.CORE, ProfileIdentifier.SOFTWARE, ProfileIdentifier.LICENSING], + profile=[ProfileIdentifierType.CORE, ProfileIdentifierType.SOFTWARE, ProfileIdentifierType.LICENSING], data_license="https://spdx.org/licenses/" + spdx2_creation_info.data_license, ) diff --git a/src/spdx_tools/spdx3/model/__init__.py b/src/spdx_tools/spdx3/model/__init__.py index 9bdc62b36..8fab45e9e 100644 --- a/src/spdx_tools/spdx3/model/__init__.py +++ b/src/spdx_tools/spdx3/model/__init__.py @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 -from spdx_tools.spdx3.model.profile_identifier import ProfileIdentifier +from spdx_tools.spdx3.model.profile_identifier import ProfileIdentifierType from spdx_tools.spdx3.model.creation_info import CreationInfo from spdx_tools.spdx3.model.integrity_method import IntegrityMethod from spdx_tools.spdx3.model.hash import Hash, HashAlgorithm diff --git a/src/spdx_tools/spdx3/model/creation_info.py b/src/spdx_tools/spdx3/model/creation_info.py index 71b80f1a5..125d4d30d 100644 --- a/src/spdx_tools/spdx3/model/creation_info.py +++ b/src/spdx_tools/spdx3/model/creation_info.py @@ -9,7 +9,7 @@ from spdx_tools.common.typing.dataclass_with_properties import dataclass_with_properties from spdx_tools.common.typing.type_checks import check_types_and_set_values -from spdx_tools.spdx3.model import ProfileIdentifier +from spdx_tools.spdx3.model import ProfileIdentifierType @dataclass_with_properties @@ -17,7 +17,7 @@ class CreationInfo: spec_version: Version created: datetime created_by: List[str] # SPDXID of Agents - profile: List[ProfileIdentifier] + profile: List[ProfileIdentifierType] data_license: Optional[str] = "CC0-1.0" created_using: List[str] = field(default_factory=list) # SPDXID of Tools comment: Optional[str] = None @@ -27,7 +27,7 @@ def __init__( spec_version: Version, created: datetime, created_by: List[str], - profile: List[ProfileIdentifier], + profile: List[ProfileIdentifierType], data_license: Optional[str] = "CC0-1.0", created_using: List[str] = None, comment: Optional[str] = None, diff --git a/src/spdx_tools/spdx3/model/profile_identifier.py b/src/spdx_tools/spdx3/model/profile_identifier.py index 7295abfcb..40fe7ac41 100644 --- a/src/spdx_tools/spdx3/model/profile_identifier.py +++ b/src/spdx_tools/spdx3/model/profile_identifier.py @@ -4,7 +4,7 @@ from enum import Enum, auto -class ProfileIdentifier(Enum): +class ProfileIdentifierType(Enum): CORE = auto() SOFTWARE = auto() LICENSING = auto() diff --git a/tests/spdx3/bump/test_actor_bump.py b/tests/spdx3/bump/test_actor_bump.py index c0a4a2af0..e6606134e 100644 --- a/tests/spdx3/bump/test_actor_bump.py +++ b/tests/spdx3/bump/test_actor_bump.py @@ -13,7 +13,7 @@ ExternalIdentifierType, Organization, Person, - ProfileIdentifier, + ProfileIdentifierType, Tool, ) from spdx_tools.spdx3.payload import Payload @@ -37,7 +37,7 @@ def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_id): payload = Payload() document_namespace = "https://doc.namespace" - creation_info = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [ProfileIdentifier.CORE]) + creation_info = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [ProfileIdentifierType.CORE]) actor = Actor(actor_type, actor_name, actor_mail) agent_or_tool_id = bump_actor(actor, payload, document_namespace, creation_info) @@ -54,8 +54,8 @@ def test_bump_actor(actor_type, actor_name, actor_mail, element_type, new_spdx_i def test_bump_actor_that_already_exists(): - creation_info_old = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [ProfileIdentifier.CORE]) - creation_info_new = CreationInfo(Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], [ProfileIdentifier.CORE]) + creation_info_old = CreationInfo(Version("3.0.0"), datetime(2022, 1, 1), ["Creator"], [ProfileIdentifierType.CORE]) + creation_info_new = CreationInfo(Version("3.0.0"), datetime(2023, 2, 2), ["Creator"], [ProfileIdentifierType.CORE]) name = "some name" document_namespace = "https://doc.namespace" diff --git a/tests/spdx3/fixtures.py b/tests/spdx3/fixtures.py index 6c7e9db34..9d7e5fd24 100644 --- a/tests/spdx3/fixtures.py +++ b/tests/spdx3/fixtures.py @@ -25,7 +25,7 @@ NamespaceMap, Organization, Person, - ProfileIdentifier, + ProfileIdentifierType, Relationship, RelationshipCompleteness, RelationshipType, @@ -93,7 +93,7 @@ def creation_info_fixture( ["https://spdx.test/tools-python/creation_info_created_using"] if created_using is None else created_using ) profile = ( - [ProfileIdentifier.CORE, ProfileIdentifier.SOFTWARE, ProfileIdentifier.LICENSING] + [ProfileIdentifierType.CORE, ProfileIdentifierType.SOFTWARE, ProfileIdentifierType.LICENSING] if profile is None else profile ) diff --git a/tests/spdx3/model/test_creation_info.py b/tests/spdx3/model/test_creation_info.py index 40b6d4536..03b2fad58 100644 --- a/tests/spdx3/model/test_creation_info.py +++ b/tests/spdx3/model/test_creation_info.py @@ -6,7 +6,7 @@ import pytest from semantic_version import Version -from spdx_tools.spdx3.model import CreationInfo, ProfileIdentifier +from spdx_tools.spdx3.model import CreationInfo, ProfileIdentifierType from tests.spdx3.fixtures import creation_info_fixture from tests.spdx3.model.model_test_utils import get_property_names @@ -22,9 +22,9 @@ def test_correct_initialization(): assert creation_info.created_by == ["https://spdx.test/tools-python/creation_info_created_by"] assert creation_info.created_using == ["https://spdx.test/tools-python/creation_info_created_using"] assert creation_info.profile == [ - ProfileIdentifier.CORE, - ProfileIdentifier.SOFTWARE, - ProfileIdentifier.LICENSING, + ProfileIdentifierType.CORE, + ProfileIdentifierType.SOFTWARE, + ProfileIdentifierType.LICENSING, ] assert creation_info.data_license == "CC0-1.0" assert creation_info.comment == "creationInfoComment" From 9b8183e5254276be586a7d10c0d59874682d57e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 12 Jul 2023 16:35:41 +0200 Subject: [PATCH 312/354] [issue-722] change return type of calculate_package_verification_code() to PackageVerificationCode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx/spdx_element_utils.py | 14 +++++++++++--- tests/spdx/test_checksum_calculation.py | 6 +++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/spdx_tools/spdx/spdx_element_utils.py b/src/spdx_tools/spdx/spdx_element_utils.py index dcb0cf2e2..c3cb3f7fa 100644 --- a/src/spdx_tools/spdx/spdx_element_utils.py +++ b/src/spdx_tools/spdx/spdx_element_utils.py @@ -5,7 +5,14 @@ from beartype.typing import List, Union -from spdx_tools.spdx.model import ChecksumAlgorithm, ExternalDocumentRef, File, Package, Snippet +from spdx_tools.spdx.model import ( + ChecksumAlgorithm, + ExternalDocumentRef, + File, + Package, + PackageVerificationCode, + Snippet, +) def get_full_element_spdx_id( @@ -33,7 +40,7 @@ def get_full_element_spdx_id( return external_uri + "#" + local_id -def calculate_package_verification_code(files: List[File]) -> str: +def calculate_package_verification_code(files: List[File]) -> PackageVerificationCode: list_of_file_hashes = [] for file in files: file_checksum_value = None @@ -53,7 +60,8 @@ def calculate_package_verification_code(files: List[File]) -> str: list_of_file_hashes.sort() hasher = hashlib.new("sha1") hasher.update("".join(list_of_file_hashes).encode("utf-8")) - return hasher.hexdigest() + value = hasher.hexdigest() + return PackageVerificationCode(value) def calculate_file_checksum(file_name: str, hash_algorithm=ChecksumAlgorithm.SHA1) -> str: diff --git a/tests/spdx/test_checksum_calculation.py b/tests/spdx/test_checksum_calculation.py index 0aa4b3b85..0e45b11c9 100644 --- a/tests/spdx/test_checksum_calculation.py +++ b/tests/spdx/test_checksum_calculation.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 import pytest -from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, File +from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, File, PackageVerificationCode from spdx_tools.spdx.spdx_element_utils import calculate_file_checksum, calculate_package_verification_code @@ -42,7 +42,7 @@ def test_verification_code_calculation_with_predefined_checksums(generate_test_f ) verification_code = calculate_package_verification_code([file1, file2]) - assert verification_code == "c6cb0949d7cd7439fce8690262a0946374824639" + assert verification_code == PackageVerificationCode("c6cb0949d7cd7439fce8690262a0946374824639") def test_verification_code_calculation_with_calculated_checksums(generate_test_files): @@ -59,7 +59,7 @@ def test_verification_code_calculation_with_calculated_checksums(generate_test_f ) verification_code = calculate_package_verification_code([file1, file2]) - assert verification_code == "6f29d813abb63ee52a47dbcb691ea2e70f956328" + assert verification_code == PackageVerificationCode("6f29d813abb63ee52a47dbcb691ea2e70f956328") def test_verification_code_calculation_with_wrong_file_location(): From 4dad0e1a8c6af7484a309a3e826a33f8df89c0cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Fri, 14 Jul 2023 09:56:04 +0200 Subject: [PATCH 313/354] remove unused CircleCI workflow and directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .circleci/config.yml | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 7bca2704d..000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Empty Circle CI configuration file to make pipeline pass - -version: 2.1 - -jobs: - empty-job: - docker: - - image: python:3.11 - steps: - - run: echo "Empty Job to make CircleCI green, we switched to https://github.com/spdx/tools-python/actions" - -workflows: - simple-workflow: - jobs: - - empty-job From 2402596f1b7f12791e8516dd7b3634c6aa830f36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 19 Jul 2023 10:49:02 +0200 Subject: [PATCH 314/354] make "Package CONTAINS Package" valid even when files_analyzed == False MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx/spdx_element_utils.py | 15 ++++++++++++- .../spdx/validation/package_validator.py | 16 ++++++++++++-- .../spdx/validation/test_package_validator.py | 21 +++++++++++++++++-- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/spdx_tools/spdx/spdx_element_utils.py b/src/spdx_tools/spdx/spdx_element_utils.py index c3cb3f7fa..0d6bd8946 100644 --- a/src/spdx_tools/spdx/spdx_element_utils.py +++ b/src/spdx_tools/spdx/spdx_element_utils.py @@ -3,10 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 import hashlib -from beartype.typing import List, Union +from beartype.typing import List, Optional, Type, Union from spdx_tools.spdx.model import ( ChecksumAlgorithm, + Document, ExternalDocumentRef, File, Package, @@ -15,6 +16,18 @@ ) +def get_element_type_from_spdx_id( + spdx_id: str, document: Document +) -> Optional[Union[Type[Package], Type[File], Type[Snippet]]]: + if spdx_id in [package.spdx_id for package in document.packages]: + return Package + if spdx_id in [file.spdx_id for file in document.files]: + return File + if spdx_id in [snippet.spdx_id for snippet in document.snippets]: + return Snippet + return None + + def get_full_element_spdx_id( element: Union[Package, File, Snippet], document_namespace: str, diff --git a/src/spdx_tools/spdx/validation/package_validator.py b/src/spdx_tools/spdx/validation/package_validator.py index 4307fc8ef..25cd6147f 100644 --- a/src/spdx_tools/spdx/validation/package_validator.py +++ b/src/spdx_tools/spdx/validation/package_validator.py @@ -4,8 +4,9 @@ from beartype.typing import List, Optional -from spdx_tools.spdx.model import Document, Package, Relationship, RelationshipType +from spdx_tools.spdx.model import Document, File, Package, Relationship, RelationshipType from spdx_tools.spdx.model.relationship_filters import filter_by_type_and_origin, filter_by_type_and_target +from spdx_tools.spdx.spdx_element_utils import get_element_type_from_spdx_id from spdx_tools.spdx.validation.checksum_validator import validate_checksums from spdx_tools.spdx.validation.external_package_ref_validator import validate_external_package_refs from spdx_tools.spdx.validation.license_expression_validator import ( @@ -50,12 +51,23 @@ def validate_package_within_document( package_contains_relationships = filter_by_type_and_origin( document.relationships, RelationshipType.CONTAINS, package.spdx_id ) + package_contains_file_relationships = [ + relationship + for relationship in package_contains_relationships + if get_element_type_from_spdx_id(relationship.related_spdx_element_id, document) == File + ] + contained_in_package_relationships = filter_by_type_and_target( document.relationships, RelationshipType.CONTAINED_BY, package.spdx_id ) + file_contained_in_package_relationships = [ + relationship + for relationship in contained_in_package_relationships + if get_element_type_from_spdx_id(relationship.spdx_element_id, document) == File + ] combined_relationships: List[Relationship] = ( - package_contains_relationships + contained_in_package_relationships + package_contains_file_relationships + file_contained_in_package_relationships ) if combined_relationships: diff --git a/tests/spdx/validation/test_package_validator.py b/tests/spdx/validation/test_package_validator.py index c2b6640d2..a6ef976ef 100644 --- a/tests/spdx/validation/test_package_validator.py +++ b/tests/spdx/validation/test_package_validator.py @@ -74,10 +74,27 @@ def test_invalid_package(package_input, expected_message): @pytest.mark.parametrize( "relationships", [ - [Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File1")], [Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "DocumentRef-external:SPDXRef-File")], - [Relationship("SPDXRef-File2", RelationshipType.CONTAINED_BY, "SPDXRef-Package")], [Relationship("DocumentRef-external:SPDXRef-File", RelationshipType.CONTAINED_BY, "SPDXRef-Package")], + ], +) +def test_valid_package_with_contains(relationships): + document = document_fixture( + relationships=relationships, + files=[file_fixture(spdx_id="SPDXRef-File1"), file_fixture(spdx_id="SPDXRef-File2")], + ) + package = package_fixture(files_analyzed=False, verification_code=None, license_info_from_files=[]) + + validation_messages: List[ValidationMessage] = validate_package_within_document(package, "SPDX-2.3", document) + + assert validation_messages == [] + + +@pytest.mark.parametrize( + "relationships", + [ + [Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File1")], + [Relationship("SPDXRef-File2", RelationshipType.CONTAINED_BY, "SPDXRef-Package")], [ Relationship("SPDXRef-Package", RelationshipType.CONTAINS, "SPDXRef-File2"), Relationship("SPDXRef-File1", RelationshipType.CONTAINED_BY, "SPDXRef-Package"), From 8ef0cef2f53a98139ce6c25767762bd152dbbd62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Wed, 19 Jul 2023 15:32:16 +0200 Subject: [PATCH 315/354] set validate=True as default value in the rdf writer to be consistent with the writers of the other formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- src/spdx_tools/spdx/writer/rdf/rdf_writer.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/spdx_tools/spdx/writer/rdf/rdf_writer.py b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py index 7756e56c6..206494def 100644 --- a/src/spdx_tools/spdx/writer/rdf/rdf_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/rdf_writer.py @@ -17,7 +17,9 @@ from spdx_tools.spdx.writer.write_utils import validate_and_deduplicate -def write_document_to_stream(document: Document, stream: IO[bytes], validate: bool, drop_duplicates: bool = True): +def write_document_to_stream( + document: Document, stream: IO[bytes], validate: bool = True, drop_duplicates: bool = True +): document = validate_and_deduplicate(document, validate, drop_duplicates) graph = Graph() doc_namespace = document.creation_info.document_namespace @@ -51,6 +53,6 @@ def write_document_to_stream(document: Document, stream: IO[bytes], validate: bo graph.serialize(stream, "pretty-xml", encoding="UTF-8", max_depth=100) -def write_document_to_file(document: Document, file_name: str, validate: bool, drop_duplicates: bool = True): +def write_document_to_file(document: Document, file_name: str, validate: bool = True, drop_duplicates: bool = True): with open(file_name, "wb") as out: write_document_to_stream(document, out, validate, drop_duplicates) From ef31285dd4eefdfe88bcb8f3fedba319e386b714 Mon Sep 17 00:00:00 2001 From: Maximilian Huber Date: Fri, 14 Jul 2023 16:50:23 +0200 Subject: [PATCH 316/354] add script to publish from tag Signed-off-by: Maximilian Huber --- .gitignore | 2 +- dev/publish_from_tag.sh | 62 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100755 dev/publish_from_tag.sh diff --git a/.gitignore b/.gitignore index 23a3c2678..d82f5bc0d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ __pycache__/ *.py[cod] *.out /build/ -/dist/ +/dist*/ /tmp/ src/spdx_tools/spdx/parser/tagvalue/parsetab.py /.cache/ diff --git a/dev/publish_from_tag.sh b/dev/publish_from_tag.sh new file mode 100755 index 000000000..eb367d781 --- /dev/null +++ b/dev/publish_from_tag.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +set -euo pipefail + +if [ $# -eq 0 ]; then + cat< /dev/null; then + echo "twine could not be found" + echo "maybe load venv with" + echo " . ./venv/bin/activate" + echo " . ./venv/bin/activate.fish" + echo + + if [[ -d ./venv/bin/ ]]; then + echo "will try to activate ./venv ..." + + source ./venv/bin/activate + + if ! command -v twine &> /dev/null; then + echo "twine still could not be found" + exit 1 + fi + else + exit 1 + fi +fi + + +if [[ -d "$tag_dir" ]]; then + echo "the dir \"$tag_dir\" already exists, exiting for safety" + exit 1 +fi + +mkdir -p "$tag_dir" +(cd "$tag_dir" && wget -c "$tar_gz" -O - | tar --strip-components=1 -xz) + +twine check "${tag_dir}/spdx-tools-${version}.tar.gz" "${tag_dir}/spdx_tools-${version}-py3-none-any.whl" +read -r -p "Do you want to upload? [y/N] " response +case "$response" in + [yY][eE][sS]|[yY]) + twine upload -r pypi "${tag_dir}/spdx-tools-${version}.tar.gz" "${tag_dir}/spdx_tools-${version}-py3-none-any.whl" + ;; +esac From 69eea911ff773878a08965da704ee9d786147a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Mon, 24 Jul 2023 11:56:20 +0200 Subject: [PATCH 317/354] update README and CHANGELOG for the upcoming release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- CHANGELOG.md | 4 +++- README.md | 14 +++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bf074eb7..a8382307c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## v0.8.0rc1 (2023-06-30) +## v0.8.0 (2023-07-25) ### New features and changes @@ -14,6 +14,8 @@ * full validation of SPDX documents against the v2.2 and v2.3 specification * support for SPDX's RDF format with all v2.3 features * unified `pysdpxtools` CLI tool replaces separate `pyspdxtools_parser` and `pyspdxtools_convertor` +* [online API documentation](https://spdx.github.io/tools-python) +* replaced CircleCI with GitHub Actions ### Contributors diff --git a/README.md b/README.md index 9516b5de2..757cf8d41 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,13 @@ SPDX v3.0 release, leading to breaking changes in the API. Please refer to the [migration guide](https://github.com/spdx/tools-python/wiki/How-to-migrate-from-0.7-to-0.8) to update your existing code. -We encourage new users to work with v0.8.0rc1 directly as the older v0.7 release is in maintenance mode. - The main features of v0.8 are: -- experimental support for the upcoming SPDX v3 specification (note, however, that support is neither complete nor - stable at this point, as the spec is still evolving) - full validation of SPDX documents against the v2.2 and v2.3 specification -- support for SPDX's RDF format with all v2.3 features. +- support for SPDX's RDF format with all v2.3 features +- experimental support for the upcoming SPDX v3 specification. Note, however, that support is neither complete nor + stable at this point, as the spec is still evolving. SPDX3-related code is contained in a separate subpackage "spdx3" + and its use is optional. We do not recommend using it in production code yet. + # Information @@ -124,7 +124,7 @@ instead of `bin`. ## Example Here are some examples of possible use cases to quickly get you started with the spdx-tools. -If you want a more comprehensive example about how to create an SPDX document from scratch, have a look [here](examples%2Fspdx2_document_from_scratch.py). +If you want more examples, like how to create an SPDX document from scratch, have a look [at the examples folder](examples). ```python import logging @@ -210,4 +210,4 @@ codebase. This is the result of an initial GSoC contribution by @[ah450](https://github.com/ah450) (or https://github.com/a-h-i) and is maintained by a community of SPDX adopters and enthusiasts. -In order to prepare for the release of SPDX v3.0, the repository has undergone a major refactoring during the time from 11/2022 to 03/2023. +In order to prepare for the release of SPDX v3.0, the repository has undergone a major refactoring during the time from 11/2022 to 07/2023. From f15a64fdd3c2b889c613997fc35da908a794c607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 25 Jul 2023 12:18:16 +0200 Subject: [PATCH 318/354] add SPDX tech mailing list link to README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 757cf8d41..99112ea02 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ This library implements SPDX parsers, convertors, validators and handlers in Pyt - PyPI: https://pypi.python.org/pypi/spdx-tools - Browse the API: https://spdx.github.io/tools-python +Important updates regarding this library are shared via the SPDX tech mailing list: https://lists.spdx.org/g/Spdx-tech. + # License From eab5db97896fff1aeb27cff5e0aaca1396679f1f Mon Sep 17 00:00:00 2001 From: Brandon Lum Date: Tue, 1 Aug 2023 22:21:12 -0400 Subject: [PATCH 319/354] make relationship parsing to be more efficient through precomputation Signed-off-by: Brandon Lum --- .../parser/jsonlikedict/relationship_parser.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py index 432dd38dc..881297c44 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py @@ -35,24 +35,26 @@ def parse_all_relationships(self, input_doc_dict: Dict) -> List[Relationship]: document_describes: List[str] = delete_duplicates_from_list(input_doc_dict.get("documentDescribes", [])) doc_spdx_id: Optional[str] = input_doc_dict.get("SPDXID") + existing_relationships_without_comments: List[Relationship] = self.get_all_relationships_without_comments(relationships) relationships.extend( parse_field_or_log_error( self.logger, document_describes, lambda x: self.parse_document_describes( - doc_spdx_id=doc_spdx_id, described_spdx_ids=x, existing_relationships=relationships + doc_spdx_id=doc_spdx_id, described_spdx_ids=x, existing_relationships=existing_relationships_without_comments ), [], ) ) package_dicts: List[Dict] = input_doc_dict.get("packages", []) + existing_relationships_without_comments: List[Relationship] = self.get_all_relationships_without_comments(relationships) relationships.extend( parse_field_or_log_error( self.logger, package_dicts, - lambda x: self.parse_has_files(package_dicts=x, existing_relationships=relationships), + lambda x: self.parse_has_files(package_dicts=x, existing_relationships=existing_relationships_without_comments), [], ) ) @@ -151,13 +153,11 @@ def parse_has_files( def check_if_relationship_exists( self, relationship: Relationship, existing_relationships: List[Relationship] ) -> bool: - existing_relationships_without_comments: List[Relationship] = self.get_all_relationships_without_comments( - existing_relationships - ) - if relationship in existing_relationships_without_comments: + # assume existing relationships are stripped of comments + if relationship in existing_relationships: return True relationship_inverted: Relationship = self.invert_relationship(relationship) - if relationship_inverted in existing_relationships_without_comments: + if relationship_inverted in existing_relationships: return True return False From 32e3d2d4b8ba9f5534c93390e6affaaa3751c430 Mon Sep 17 00:00:00 2001 From: Brandon Lum Date: Fri, 11 Aug 2023 16:10:21 -0400 Subject: [PATCH 320/354] fix test to correctly use assumption of no comments in relationships Signed-off-by: Brandon Lum --- src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py | 1 + tests/spdx/parser/jsonlikedict/test_relationship_parser.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py index 881297c44..459361269 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py @@ -125,6 +125,7 @@ def parse_document_describes( def parse_has_files( self, package_dicts: List[Dict], existing_relationships: List[Relationship] ) -> List[Relationship]: + # assume existing relationships are stripped of comments logger = Logger() contains_relationships = [] for package in package_dicts: diff --git a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py index 327a83f6c..dae0e90d7 100644 --- a/tests/spdx/parser/jsonlikedict/test_relationship_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_relationship_parser.py @@ -169,6 +169,7 @@ def test_parse_has_files(): @pytest.mark.parametrize( "has_files,existing_relationships,contains_relationships", [ + # pre-requisite for parse_has_files requires that comments in relationships are stripped ( ["SPDXRef-File1", "SPDXRef-File2"], [ @@ -176,7 +177,6 @@ def test_parse_has_files(): spdx_element_id="SPDXRef-Package", relationship_type=RelationshipType.CONTAINS, related_spdx_element_id="SPDXRef-File1", - comment="This relationship has a comment.", ), Relationship( spdx_element_id="SPDXRef-File2", From 3f1c62fac641d003bce71933fa664fd20c963185 Mon Sep 17 00:00:00 2001 From: Brandon Lum Date: Fri, 11 Aug 2023 16:18:02 -0400 Subject: [PATCH 321/354] fix lint errors Signed-off-by: Brandon Lum --- .../parser/jsonlikedict/relationship_parser.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py index 459361269..17374bef5 100644 --- a/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py +++ b/src/spdx_tools/spdx/parser/jsonlikedict/relationship_parser.py @@ -35,26 +35,34 @@ def parse_all_relationships(self, input_doc_dict: Dict) -> List[Relationship]: document_describes: List[str] = delete_duplicates_from_list(input_doc_dict.get("documentDescribes", [])) doc_spdx_id: Optional[str] = input_doc_dict.get("SPDXID") - existing_relationships_without_comments: List[Relationship] = self.get_all_relationships_without_comments(relationships) + existing_relationships_without_comments: List[Relationship] = self.get_all_relationships_without_comments( + relationships + ) relationships.extend( parse_field_or_log_error( self.logger, document_describes, lambda x: self.parse_document_describes( - doc_spdx_id=doc_spdx_id, described_spdx_ids=x, existing_relationships=existing_relationships_without_comments + doc_spdx_id=doc_spdx_id, + described_spdx_ids=x, + existing_relationships=existing_relationships_without_comments, ), [], ) ) package_dicts: List[Dict] = input_doc_dict.get("packages", []) - existing_relationships_without_comments: List[Relationship] = self.get_all_relationships_without_comments(relationships) + existing_relationships_without_comments: List[Relationship] = self.get_all_relationships_without_comments( + relationships + ) relationships.extend( parse_field_or_log_error( self.logger, package_dicts, - lambda x: self.parse_has_files(package_dicts=x, existing_relationships=existing_relationships_without_comments), + lambda x: self.parse_has_files( + package_dicts=x, existing_relationships=existing_relationships_without_comments + ), [], ) ) From ee95e603c9c774e696edd544131b801ee9bebaea Mon Sep 17 00:00:00 2001 From: Brandon Lum Date: Fri, 11 Aug 2023 16:34:21 -0400 Subject: [PATCH 322/354] fix additional lint errors in tests Signed-off-by: Brandon Lum --- tests/spdx/parser/all_formats/test_parse_from_file.py | 4 ++-- tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/spdx/parser/all_formats/test_parse_from_file.py b/tests/spdx/parser/all_formats/test_parse_from_file.py index 2b9bb2b45..7fad968f2 100644 --- a/tests/spdx/parser/all_formats/test_parse_from_file.py +++ b/tests/spdx/parser/all_formats/test_parse_from_file.py @@ -36,7 +36,7 @@ def test_parse_from_file_with_2_3_example(self, parser, format_name, extension): doc = parser.parse_from_file( os.path.join(os.path.dirname(__file__), f"../../data/SPDX{format_name}Example-v2.3.spdx{extension}") ) - assert type(doc) == Document + assert isinstance(doc, Document) assert len(doc.annotations) == 5 assert len(doc.files) == 5 assert len(doc.packages) == 4 @@ -48,7 +48,7 @@ def test_parse_json_with_2_2_example(self, parser, format_name, extension): doc = parser.parse_from_file( os.path.join(os.path.dirname(__file__), f"../../data/SPDX{format_name}Example-v2.2.spdx{extension}") ) - assert type(doc) == Document + assert isinstance(doc, Document) assert len(doc.annotations) == 5 assert len(doc.files) == 4 assert len(doc.packages) == 4 diff --git a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py index ce35e3611..6f98816ca 100644 --- a/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py +++ b/tests/spdx/parser/jsonlikedict/test_dict_parsing_functions.py @@ -34,7 +34,7 @@ def test_invalid_json_str_to_enum(invalid_json_str, expected_message): def test_parse_field_or_no_assertion(input_str, expected_type): resulting_value = parse_field_or_no_assertion(input_str, lambda x: x) - assert type(resulting_value) == expected_type + assert isinstance(resulting_value, expected_type) @pytest.mark.parametrize( @@ -43,4 +43,4 @@ def test_parse_field_or_no_assertion(input_str, expected_type): def test_parse_field_or_no_assertion_or_none(input_str, expected_type): resulting_value = parse_field_or_no_assertion_or_none(input_str, lambda x: x) - assert type(resulting_value) == expected_type + assert isinstance(resulting_value, expected_type) From 1ecc6f669da939d8b4f213f0a49cc0a78578c16b Mon Sep 17 00:00:00 2001 From: Brian DeHamer Date: Wed, 9 Aug 2023 11:30:55 -0700 Subject: [PATCH 323/354] expand url regex to allow for userinfo Signed-off-by: Brian DeHamer --- src/spdx_tools/spdx/validation/uri_validators.py | 3 ++- tests/spdx/validation/test_uri_validators.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/spdx_tools/spdx/validation/uri_validators.py b/src/spdx_tools/spdx/validation/uri_validators.py index d9c23f97a..d3a423732 100644 --- a/src/spdx_tools/spdx/validation/uri_validators.py +++ b/src/spdx_tools/spdx/validation/uri_validators.py @@ -9,7 +9,8 @@ url_pattern = ( "(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/|ssh:\\/\\/|git:\\/\\/|svn:\\/\\/|sftp:" - "\\/\\/|ftp:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+){0,100}\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?" + "\\/\\/|ftp:\\/\\/)?([\\w\\-.!~*'()%;:&=+$,]+@)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+){0,100}\\.[a-z]{2,5}" + "(:[0-9]{1,5})?(\\/.*)?" ) supported_download_repos: str = "(git|hg|svn|bzr)" git_pattern = "(git\\+git@[a-zA-Z0-9\\.\\-]+:[a-zA-Z0-9/\\\\.@\\-]+)" diff --git a/tests/spdx/validation/test_uri_validators.py b/tests/spdx/validation/test_uri_validators.py index ffe30084c..069cb1b36 100644 --- a/tests/spdx/validation/test_uri_validators.py +++ b/tests/spdx/validation/test_uri_validators.py @@ -34,6 +34,7 @@ def test_invalid_url(input_value): "git+https://git.myproject.org/MyProject.git", "git+http://git.myproject.org/MyProject", "git+ssh://git.myproject.org/MyProject.git", + "git+ssh://git@git.myproject.org/MyProject.git", "git+git://git.myproject.org/MyProject", "git+git@git.myproject.org:MyProject", "git://git.myproject.org/MyProject#src/somefile.c", From ca72624a269247aadc235262a6030098b931f105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 22 Aug 2023 15:17:57 +0200 Subject: [PATCH 324/354] instantiate get_spdx_licensing() in a singleton module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this getter takes quite some time and should be called as few times as possible Signed-off-by: Armin Tänzer --- examples/spdx2_document_from_scratch.py | 15 +++++++------ src/spdx_tools/common/spdx_licensing.py | 7 +++++++ .../parser/rdf/license_expression_parser.py | 5 +++-- .../license_expression_validator.py | 9 ++++---- .../writer/rdf/license_expression_writer.py | 13 +++--------- .../bump_from_spdx2/license_expression.py | 14 ++++--------- .../test_spdx2_document_from_scratch.py | 15 +++++++------ tests/spdx/fixtures.py | 17 +++++++-------- .../test_license_expression_parser.py | 6 +++--- tests/spdx/parser/rdf/test_file_parser.py | 6 +++--- .../rdf/test_license_expression_parser.py | 16 +++++++------- tests/spdx/parser/rdf/test_package_parser.py | 8 +++---- tests/spdx/parser/rdf/test_snippet_parser.py | 6 +++--- .../spdx/parser/tagvalue/test_file_parser.py | 6 +++--- .../parser/tagvalue/test_package_parser.py | 6 +++--- .../parser/tagvalue/test_snippet_parser.py | 4 ++-- .../test_license_expression_validator.py | 13 ++++++------ .../rdf/test_license_expression_writer.py | 8 +++---- .../bump/test_license_expression_bump.py | 21 ++++++++++--------- 19 files changed, 95 insertions(+), 100 deletions(-) create mode 100644 src/spdx_tools/common/spdx_licensing.py diff --git a/examples/spdx2_document_from_scratch.py b/examples/spdx2_document_from_scratch.py index e74ccf3a1..bc92175a8 100644 --- a/examples/spdx2_document_from_scratch.py +++ b/examples/spdx2_document_from_scratch.py @@ -5,8 +5,7 @@ from datetime import datetime from typing import List -from license_expression import get_spdx_licensing - +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.model import ( Actor, ActorType, @@ -65,9 +64,9 @@ Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), ], - license_concluded=get_spdx_licensing().parse("GPL-2.0-only OR MIT"), - license_info_from_files=[get_spdx_licensing().parse("GPL-2.0-only"), get_spdx_licensing().parse("MIT")], - license_declared=get_spdx_licensing().parse("GPL-2.0-only AND MIT"), + license_concluded=spdx_licensing.parse("GPL-2.0-only OR MIT"), + license_info_from_files=[spdx_licensing.parse("GPL-2.0-only"), spdx_licensing.parse("MIT")], + license_declared=spdx_licensing.parse("GPL-2.0-only AND MIT"), license_comment="license comment", copyright_text="Copyright 2022 Jane Doe", description="package description", @@ -100,8 +99,8 @@ Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), ], - license_concluded=get_spdx_licensing().parse("MIT"), - license_info_in_file=[get_spdx_licensing().parse("MIT")], + license_concluded=spdx_licensing.parse("MIT"), + license_info_in_file=[spdx_licensing.parse("MIT")], copyright_text="Copyright 2022 Jane Doe", ) file2 = File( @@ -110,7 +109,7 @@ checksums=[ Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2759"), ], - license_concluded=get_spdx_licensing().parse("GPL-2.0-only"), + license_concluded=spdx_licensing.parse("GPL-2.0-only"), ) # Assuming the package contains those two files, we create two CONTAINS relationships. diff --git a/src/spdx_tools/common/spdx_licensing.py b/src/spdx_tools/common/spdx_licensing.py new file mode 100644 index 000000000..a9a17e973 --- /dev/null +++ b/src/spdx_tools/common/spdx_licensing.py @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2023 spdx contributors +# +# SPDX-License-Identifier: Apache-2.0 +from license_expression import get_spdx_licensing + +# this getter takes quite long so we only call it once in this singleton module +spdx_licensing = get_spdx_licensing() diff --git a/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py b/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py index 64cc36755..2ae547232 100644 --- a/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/license_expression_parser.py @@ -2,10 +2,11 @@ # # SPDX-License-Identifier: Apache-2.0 from beartype.typing import Optional, Union -from license_expression import LicenseExpression, get_spdx_licensing +from license_expression import LicenseExpression from rdflib import RDF, Graph from rdflib.term import BNode, Identifier, Node, URIRef +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.parser.logger import Logger from spdx_tools.spdx.parser.rdf.graph_parsing_functions import get_value_from_graph, remove_prefix from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE @@ -19,7 +20,7 @@ def parse_license_expression( ) -> LicenseExpression: if not logger: logger = Logger() - spdx_licensing = get_spdx_licensing() + expression = "" if license_expression_node.startswith(LICENSE_NAMESPACE): expression = remove_prefix(license_expression_node, LICENSE_NAMESPACE) diff --git a/src/spdx_tools/spdx/validation/license_expression_validator.py b/src/spdx_tools/spdx/validation/license_expression_validator.py index bce5c9eb3..a59aec9fa 100644 --- a/src/spdx_tools/spdx/validation/license_expression_validator.py +++ b/src/spdx_tools/spdx/validation/license_expression_validator.py @@ -3,8 +3,9 @@ # SPDX-License-Identifier: Apache-2.0 from beartype.typing import List, Optional, Union -from license_expression import ExpressionError, ExpressionParseError, LicenseExpression, get_spdx_licensing +from license_expression import ExpressionError, ExpressionParseError, LicenseExpression +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.model import Document, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage @@ -40,7 +41,7 @@ def validate_license_expression( validation_messages = [] license_ref_ids: List[str] = [license_ref.license_id for license_ref in document.extracted_licensing_info] - for non_spdx_token in get_spdx_licensing().validate(license_expression).invalid_symbols: + for non_spdx_token in spdx_licensing.validate(license_expression).invalid_symbols: if non_spdx_token not in license_ref_ids: validation_messages.append( ValidationMessage( @@ -51,14 +52,14 @@ def validate_license_expression( ) try: - get_spdx_licensing().parse(str(license_expression), validate=True, strict=True) + spdx_licensing.parse(str(license_expression), validate=True, strict=True) except ExpressionParseError as err: # This error is raised when an exception symbol is used as a license symbol and vice versa. # So far, it only catches the first such error in the provided string. validation_messages.append(ValidationMessage(f"{err}. for license_expression: {license_expression}", context)) except ExpressionError: # This error is raised for invalid symbols within the license_expression, but it provides only a string of - # these. On the other hand, get_spdx_licensing().validate() gives an actual list of invalid symbols, so this is + # these. On the other hand, spdx_licensing.validate() gives an actual list of invalid symbols, so this is # handled above. pass diff --git a/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py b/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py index 1057f6efd..c8a76035a 100644 --- a/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py +++ b/src/spdx_tools/spdx/writer/rdf/license_expression_writer.py @@ -3,18 +3,11 @@ # SPDX-License-Identifier: Apache-2.0 from beartype.typing import List, Union from boolean import Expression -from license_expression import ( - AND, - OR, - ExpressionInfo, - LicenseExpression, - LicenseSymbol, - LicenseWithExceptionSymbol, - get_spdx_licensing, -) +from license_expression import AND, OR, ExpressionInfo, LicenseExpression, LicenseSymbol, LicenseWithExceptionSymbol from rdflib import RDF, BNode, Graph, URIRef from rdflib.term import Literal, Node +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone from spdx_tools.spdx.rdfschema.namespace import LICENSE_NAMESPACE, SPDX_NAMESPACE @@ -75,7 +68,7 @@ def add_license_expression_to_graph( def license_or_exception_is_on_spdx_licensing_list(license_symbol: LicenseSymbol) -> bool: - symbol_info: ExpressionInfo = get_spdx_licensing().validate(license_symbol) + symbol_info: ExpressionInfo = spdx_licensing.validate(license_symbol) return not symbol_info.errors diff --git a/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py b/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py index ddd04ecdd..de5f006d3 100644 --- a/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py +++ b/src/spdx_tools/spdx3/bump_from_spdx2/license_expression.py @@ -2,15 +2,9 @@ # # SPDX-License-Identifier: Apache-2.0 from beartype.typing import List, Union -from license_expression import ( - AND, - OR, - LicenseExpression, - LicenseSymbol, - LicenseWithExceptionSymbol, - get_spdx_licensing, -) +from license_expression import AND, OR, LicenseExpression, LicenseSymbol, LicenseWithExceptionSymbol +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx3.model.licensing import ( AnyLicenseInfo, ConjunctiveLicenseSet, @@ -61,7 +55,7 @@ def bump_license_expression( subject_addition=bump_license_exception(license_expression.exception_symbol, extracted_licensing_info), ) if isinstance(license_expression, LicenseSymbol): - if not get_spdx_licensing().validate(license_expression).invalid_symbols: + if not spdx_licensing.validate(license_expression).invalid_symbols: return ListedLicense(license_expression.key, license_expression.obj, "blank") else: for licensing_info in extracted_licensing_info: @@ -80,7 +74,7 @@ def bump_license_expression( def bump_license_exception( license_exception: LicenseSymbol, extracted_licensing_info: List[ExtractedLicensingInfo] ) -> LicenseAddition: - if not get_spdx_licensing().validate(license_exception).invalid_symbols: + if not spdx_licensing.validate(license_exception).invalid_symbols: return ListedLicenseException(license_exception.key, "", "") else: for licensing_info in extracted_licensing_info: diff --git a/tests/spdx/examples/test_spdx2_document_from_scratch.py b/tests/spdx/examples/test_spdx2_document_from_scratch.py index 538610bb6..7c3228d91 100644 --- a/tests/spdx/examples/test_spdx2_document_from_scratch.py +++ b/tests/spdx/examples/test_spdx2_document_from_scratch.py @@ -5,8 +5,7 @@ from datetime import datetime from typing import List -from license_expression import get_spdx_licensing - +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.model import ( Actor, ActorType, @@ -67,9 +66,9 @@ def test_spdx2_document_from_scratch(): Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), ], - license_concluded=get_spdx_licensing().parse("GPL-2.0-only OR MIT"), - license_info_from_files=[get_spdx_licensing().parse("GPL-2.0-only"), get_spdx_licensing().parse("MIT")], - license_declared=get_spdx_licensing().parse("GPL-2.0-only AND MIT"), + license_concluded=spdx_licensing.parse("GPL-2.0-only OR MIT"), + license_info_from_files=[spdx_licensing.parse("GPL-2.0-only"), spdx_licensing.parse("MIT")], + license_declared=spdx_licensing.parse("GPL-2.0-only AND MIT"), license_comment="license comment", copyright_text="Copyright 2022 Jane Doe", description="package description", @@ -102,8 +101,8 @@ def test_spdx2_document_from_scratch(): Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2758"), Checksum(ChecksumAlgorithm.MD5, "624c1abb3664f4b35547e7c73864ad24"), ], - license_concluded=get_spdx_licensing().parse("MIT"), - license_info_in_file=[get_spdx_licensing().parse("MIT")], + license_concluded=spdx_licensing.parse("MIT"), + license_info_in_file=[spdx_licensing.parse("MIT")], copyright_text="Copyright 2022 Jane Doe", ) file2 = File( @@ -112,7 +111,7 @@ def test_spdx2_document_from_scratch(): checksums=[ Checksum(ChecksumAlgorithm.SHA1, "d6a770ba38583ed4bb4525bd96e50461655d2759"), ], - license_concluded=get_spdx_licensing().parse("GPL-2.0-only"), + license_concluded=spdx_licensing.parse("GPL-2.0-only"), ) # Assuming the package contains those two files, we create two CONTAINS relationships. diff --git a/tests/spdx/fixtures.py b/tests/spdx/fixtures.py index f0d8f14b7..eebfb0f76 100644 --- a/tests/spdx/fixtures.py +++ b/tests/spdx/fixtures.py @@ -3,8 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 from datetime import datetime -from license_expression import get_spdx_licensing - +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID from spdx_tools.spdx.model import ( Actor, @@ -88,7 +87,7 @@ def file_fixture( spdx_id="SPDXRef-File", checksums=None, file_types=None, - license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"), + license_concluded=spdx_licensing.parse("MIT and GPL-2.0"), license_info_in_file=None, license_comment="licenseComment", copyright_text="copyrightText", @@ -100,7 +99,7 @@ def file_fixture( checksums = [checksum_fixture()] if checksums is None else checksums file_types = [FileType.TEXT] if file_types is None else file_types license_info_in_file = ( - [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()] + [spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()] if license_info_in_file is None else license_info_in_file ) @@ -135,9 +134,9 @@ def package_fixture( checksums=None, homepage="https://homepage.com", source_info="sourceInfo", - license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"), + license_concluded=spdx_licensing.parse("MIT and GPL-2.0"), license_info_from_files=None, - license_declared=get_spdx_licensing().parse("MIT and GPL-2.0"), + license_declared=spdx_licensing.parse("MIT and GPL-2.0"), license_comment="packageLicenseComment", copyright_text="packageCopyrightText", summary="packageSummary", @@ -152,7 +151,7 @@ def package_fixture( ) -> Package: checksums = [checksum_fixture()] if checksums is None else checksums license_info_from_files = ( - [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()] + [spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()] if license_info_from_files is None else license_info_from_files ) @@ -208,7 +207,7 @@ def snippet_fixture( file_spdx_id="SPDXRef-File", byte_range=(1, 2), line_range=(3, 4), - license_concluded=get_spdx_licensing().parse("MIT and GPL-2.0"), + license_concluded=spdx_licensing.parse("MIT and GPL-2.0"), license_info_in_snippet=None, license_comment="snippetLicenseComment", copyright_text="licenseCopyrightText", @@ -217,7 +216,7 @@ def snippet_fixture( attribution_texts=None, ) -> Snippet: license_info_in_snippet = ( - [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNone()] + [spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNone()] if license_info_in_snippet is None else license_info_in_snippet ) diff --git a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py index a1364d556..f2177692c 100644 --- a/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py +++ b/tests/spdx/parser/jsonlikedict/test_license_expression_parser.py @@ -4,8 +4,8 @@ from unittest import TestCase import pytest -from license_expression import get_spdx_licensing +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.model import SpdxNoAssertion, SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.jsonlikedict.license_expression_parser import LicenseExpressionParser @@ -14,8 +14,8 @@ @pytest.mark.parametrize( "license_expression_str, expected_license", [ - ("First License", get_spdx_licensing().parse("First License")), - ("Second License", get_spdx_licensing().parse("Second License")), + ("First License", spdx_licensing.parse("First License")), + ("Second License", spdx_licensing.parse("Second License")), ("NOASSERTION", SpdxNoAssertion()), ("NONE", SpdxNone()), ], diff --git a/tests/spdx/parser/rdf/test_file_parser.py b/tests/spdx/parser/rdf/test_file_parser.py index 7facfce98..2d99a5d0a 100644 --- a/tests/spdx/parser/rdf/test_file_parser.py +++ b/tests/spdx/parser/rdf/test_file_parser.py @@ -5,9 +5,9 @@ from unittest import TestCase import pytest -from license_expression import get_spdx_licensing from rdflib import RDF, BNode, Graph, URIRef +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.model import Checksum, ChecksumAlgorithm, FileType, SpdxNoAssertion from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.rdf.file_parser import parse_file @@ -29,10 +29,10 @@ def test_parse_file(): assert file.comment == "fileComment" assert file.copyright_text == "copyrightText" assert file.contributors == ["fileContributor"] - assert file.license_concluded == get_spdx_licensing().parse("MIT AND GPL-2.0") + assert file.license_concluded == spdx_licensing.parse("MIT AND GPL-2.0") TestCase().assertCountEqual( file.license_info_in_file, - [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()], + [spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()], ) assert file.license_comment == "licenseComment" assert file.notice == "fileNotice" diff --git a/tests/spdx/parser/rdf/test_license_expression_parser.py b/tests/spdx/parser/rdf/test_license_expression_parser.py index 5f3ada8c7..d9e7d5986 100644 --- a/tests/spdx/parser/rdf/test_license_expression_parser.py +++ b/tests/spdx/parser/rdf/test_license_expression_parser.py @@ -4,9 +4,9 @@ import os from unittest import TestCase -from license_expression import get_spdx_licensing from rdflib import RDF, Graph +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.parser.rdf import rdf_parser from spdx_tools.spdx.parser.rdf.license_expression_parser import parse_license_expression from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE @@ -19,7 +19,7 @@ def test_license_expression_parser(): license_expression = parse_license_expression(license_expression_node, graph, "https://some.namespace#") - assert license_expression == get_spdx_licensing().parse("GPL-2.0 AND MIT") + assert license_expression == spdx_licensing.parse("GPL-2.0 AND MIT") def test_license_expression_parser_with_coupled_licenses(): @@ -30,19 +30,19 @@ def test_license_expression_parser_with_coupled_licenses(): packages_by_spdx_id = {package.spdx_id: package for package in doc.packages} files_by_spdx_id = {file.spdx_id: file for file in doc.files} - assert packages_by_spdx_id["SPDXRef-Package"].license_declared == get_spdx_licensing().parse( + assert packages_by_spdx_id["SPDXRef-Package"].license_declared == spdx_licensing.parse( "LGPL-2.0-only AND LicenseRef-3" ) - assert packages_by_spdx_id["SPDXRef-Package"].license_concluded == get_spdx_licensing().parse( + assert packages_by_spdx_id["SPDXRef-Package"].license_concluded == spdx_licensing.parse( "LGPL-2.0-only OR LicenseRef-3" ) TestCase().assertCountEqual( packages_by_spdx_id["SPDXRef-Package"].license_info_from_files, [ - get_spdx_licensing().parse("GPL-2.0"), - get_spdx_licensing().parse("LicenseRef-1"), - get_spdx_licensing().parse("LicenseRef-2"), + spdx_licensing.parse("GPL-2.0"), + spdx_licensing.parse("LicenseRef-1"), + spdx_licensing.parse("LicenseRef-2"), ], ) - assert files_by_spdx_id["SPDXRef-JenaLib"].license_concluded == get_spdx_licensing().parse("LicenseRef-1") + assert files_by_spdx_id["SPDXRef-JenaLib"].license_concluded == spdx_licensing.parse("LicenseRef-1") diff --git a/tests/spdx/parser/rdf/test_package_parser.py b/tests/spdx/parser/rdf/test_package_parser.py index 814ceceee..df1907ad1 100644 --- a/tests/spdx/parser/rdf/test_package_parser.py +++ b/tests/spdx/parser/rdf/test_package_parser.py @@ -5,9 +5,9 @@ from unittest import TestCase import pytest -from license_expression import get_spdx_licensing from rdflib import RDF, BNode, Graph, Literal, URIRef +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.model import ( Actor, ActorType, @@ -41,11 +41,11 @@ def test_package_parser(): assert package.files_analyzed is True assert package.checksums == [Checksum(ChecksumAlgorithm.SHA1, "71c4025dd9897b364f3ebbb42c484ff43d00791c")] assert package.source_info == "sourceInfo" - assert package.license_concluded == get_spdx_licensing().parse("MIT AND GPL-2.0") - assert package.license_declared == get_spdx_licensing().parse("MIT AND GPL-2.0") + assert package.license_concluded == spdx_licensing.parse("MIT AND GPL-2.0") + assert package.license_declared == spdx_licensing.parse("MIT AND GPL-2.0") TestCase().assertCountEqual( package.license_info_from_files, - [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()], + [spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()], ) assert package.license_comment == "packageLicenseComment" assert package.copyright_text == "packageCopyrightText" diff --git a/tests/spdx/parser/rdf/test_snippet_parser.py b/tests/spdx/parser/rdf/test_snippet_parser.py index da2267221..e3256e4bd 100644 --- a/tests/spdx/parser/rdf/test_snippet_parser.py +++ b/tests/spdx/parser/rdf/test_snippet_parser.py @@ -5,9 +5,9 @@ from unittest import TestCase import pytest -from license_expression import get_spdx_licensing from rdflib import RDF, BNode, Graph, Literal, URIRef +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.model import SpdxNoAssertion from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.rdf.snippet_parser import parse_ranges, parse_snippet @@ -26,10 +26,10 @@ def test_parse_snippet(): assert snippet.file_spdx_id == "SPDXRef-File" assert snippet.byte_range == (1, 2) assert snippet.line_range == (3, 4) - assert snippet.license_concluded == get_spdx_licensing().parse("MIT AND GPL-2.0") + assert snippet.license_concluded == spdx_licensing.parse("MIT AND GPL-2.0") TestCase().assertCountEqual( snippet.license_info_in_snippet, - [get_spdx_licensing().parse("MIT"), get_spdx_licensing().parse("GPL-2.0"), SpdxNoAssertion()], + [spdx_licensing.parse("MIT"), spdx_licensing.parse("GPL-2.0"), SpdxNoAssertion()], ) assert snippet.license_comment == "snippetLicenseComment" assert snippet.copyright_text == "licenseCopyrightText" diff --git a/tests/spdx/parser/tagvalue/test_file_parser.py b/tests/spdx/parser/tagvalue/test_file_parser.py index 859516cbf..aedf197b5 100644 --- a/tests/spdx/parser/tagvalue/test_file_parser.py +++ b/tests/spdx/parser/tagvalue/test_file_parser.py @@ -2,8 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 import pytest -from license_expression import get_spdx_licensing +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.model import FileType, SpdxNoAssertion from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.tagvalue.parser import Parser @@ -39,8 +39,8 @@ def test_parse_file(): assert spdx_file.attribution_texts == [ "Acknowledgements that might be required to be communicated in some contexts." ] - assert spdx_file.license_info_in_file == [get_spdx_licensing().parse("Apache-2.0"), SpdxNoAssertion()] - assert spdx_file.license_concluded == get_spdx_licensing().parse("Apache-2.0") + assert spdx_file.license_info_in_file == [spdx_licensing.parse("Apache-2.0"), SpdxNoAssertion()] + assert spdx_file.license_concluded == spdx_licensing.parse("Apache-2.0") def test_parse_invalid_file(): diff --git a/tests/spdx/parser/tagvalue/test_package_parser.py b/tests/spdx/parser/tagvalue/test_package_parser.py index dbbeef415..e38351b48 100644 --- a/tests/spdx/parser/tagvalue/test_package_parser.py +++ b/tests/spdx/parser/tagvalue/test_package_parser.py @@ -5,8 +5,8 @@ from unittest import TestCase import pytest -from license_expression import get_spdx_licensing +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.constants import DOCUMENT_SPDX_ID from spdx_tools.spdx.model import ExternalPackageRef, ExternalPackageRefCategory, PackagePurpose, SpdxNone from spdx_tools.spdx.parser.error import SPDXParsingError @@ -57,9 +57,9 @@ def test_parse_package(): assert len(package.license_info_from_files) == 3 TestCase().assertCountEqual( package.license_info_from_files, - [get_spdx_licensing().parse("Apache-1.0"), get_spdx_licensing().parse("Apache-2.0"), SpdxNone()], + [spdx_licensing.parse("Apache-1.0"), spdx_licensing.parse("Apache-2.0"), SpdxNone()], ) - assert package.license_concluded == get_spdx_licensing().parse("LicenseRef-2.0 AND Apache-2.0") + assert package.license_concluded == spdx_licensing.parse("LicenseRef-2.0 AND Apache-2.0") assert package.files_analyzed is True assert package.comment == "Comment on the package." assert len(package.external_references) == 2 diff --git a/tests/spdx/parser/tagvalue/test_snippet_parser.py b/tests/spdx/parser/tagvalue/test_snippet_parser.py index 8bd82595c..79d5de670 100644 --- a/tests/spdx/parser/tagvalue/test_snippet_parser.py +++ b/tests/spdx/parser/tagvalue/test_snippet_parser.py @@ -4,8 +4,8 @@ from unittest import TestCase import pytest -from license_expression import get_spdx_licensing +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.model import SpdxNoAssertion from spdx_tools.spdx.parser.error import SPDXParsingError from spdx_tools.spdx.parser.tagvalue.parser import Parser @@ -41,7 +41,7 @@ def test_parse_snippet(): assert snippet.copyright_text == " Copyright 2008-2010 John Smith " assert snippet.license_comment == "Some lic comment." assert snippet.file_spdx_id == "SPDXRef-DoapSource" - assert snippet.license_concluded == get_spdx_licensing().parse("Apache-2.0") + assert snippet.license_concluded == spdx_licensing.parse("Apache-2.0") assert snippet.license_info_in_snippet == [SpdxNoAssertion()] assert snippet.byte_range[0] == 310 assert snippet.byte_range[1] == 420 diff --git a/tests/spdx/validation/test_license_expression_validator.py b/tests/spdx/validation/test_license_expression_validator.py index 03c0eddad..cb0ef0c66 100644 --- a/tests/spdx/validation/test_license_expression_validator.py +++ b/tests/spdx/validation/test_license_expression_validator.py @@ -6,8 +6,9 @@ from unittest import TestCase import pytest -from license_expression import LicenseExpression, get_spdx_licensing +from license_expression import LicenseExpression +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.model import Document, SpdxNoAssertion, SpdxNone from spdx_tools.spdx.validation.license_expression_validator import ( validate_license_expression, @@ -29,7 +30,7 @@ ) def test_valid_license_expression(expression_string): document: Document = document_fixture() - license_expression: LicenseExpression = get_spdx_licensing().parse(expression_string) + license_expression: LicenseExpression = spdx_licensing.parse(expression_string) validation_messages: List[ValidationMessage] = validate_license_expression( license_expression, document, parent_id="SPDXRef-File" ) @@ -51,8 +52,8 @@ def test_none_and_no_assertion(expression): [ [SpdxNone()], [SpdxNoAssertion()], - [get_spdx_licensing().parse("MIT and GPL-3.0-only"), get_spdx_licensing().parse(FIXTURE_LICENSE_ID)], - [SpdxNone(), get_spdx_licensing().parse("MIT"), SpdxNoAssertion()], + [spdx_licensing.parse("MIT and GPL-3.0-only"), spdx_licensing.parse(FIXTURE_LICENSE_ID)], + [SpdxNone(), spdx_licensing.parse("MIT"), SpdxNoAssertion()], ], ) def test_valid_license_expressions(expression_list): @@ -72,7 +73,7 @@ def test_valid_license_expressions(expression_list): ) def test_invalid_license_expression_with_unknown_symbols(expression_string, unknown_symbols): document: Document = document_fixture() - license_expression: LicenseExpression = get_spdx_licensing().parse(expression_string) + license_expression: LicenseExpression = spdx_licensing.parse(expression_string) parent_id = "SPDXRef-File" context = ValidationContext( parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expression @@ -125,7 +126,7 @@ def test_invalid_license_expression_with_unknown_symbols(expression_string, unkn ) def test_invalid_license_expression_with_invalid_exceptions(expression_string, expected_message): document: Document = document_fixture() - license_expression: LicenseExpression = get_spdx_licensing().parse(expression_string) + license_expression: LicenseExpression = spdx_licensing.parse(expression_string) parent_id = "SPDXRef-File" context = ValidationContext( parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expression diff --git a/tests/spdx/writer/rdf/test_license_expression_writer.py b/tests/spdx/writer/rdf/test_license_expression_writer.py index d77d08ffb..78fbec616 100644 --- a/tests/spdx/writer/rdf/test_license_expression_writer.py +++ b/tests/spdx/writer/rdf/test_license_expression_writer.py @@ -2,16 +2,16 @@ # # SPDX-License-Identifier: Apache-2.0 import pytest -from license_expression import get_spdx_licensing from rdflib import RDF, Graph, Literal, URIRef +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE from spdx_tools.spdx.writer.rdf.license_expression_writer import add_license_expression_to_graph def test_add_conjunctive_license_set_to_graph(): graph = Graph() - license_expression = get_spdx_licensing().parse("MIT AND GPL-2.0") + license_expression = spdx_licensing.parse("MIT AND GPL-2.0") add_license_expression_to_graph( license_expression, graph, URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, "https://namespace" @@ -25,7 +25,7 @@ def test_add_conjunctive_license_set_to_graph(): def test_add_disjunctive_license_set_to_graph(): graph = Graph() - license_expression = get_spdx_licensing().parse("MIT OR GPL-2.0") + license_expression = spdx_licensing.parse("MIT OR GPL-2.0") add_license_expression_to_graph( license_expression, graph, URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, "https://namespace" @@ -49,7 +49,7 @@ def test_add_disjunctive_license_set_to_graph(): ) def test_license_exception_to_graph(license_with_exception, expected_triple): graph = Graph() - license_expression = get_spdx_licensing().parse(license_with_exception) + license_expression = spdx_licensing.parse(license_with_exception) add_license_expression_to_graph( license_expression, graph, URIRef("parentNode"), SPDX_NAMESPACE.licenseConcluded, "https://namespace" diff --git a/tests/spdx3/bump/test_license_expression_bump.py b/tests/spdx3/bump/test_license_expression_bump.py index 6f3b8aa20..0f63299cf 100644 --- a/tests/spdx3/bump/test_license_expression_bump.py +++ b/tests/spdx3/bump/test_license_expression_bump.py @@ -2,8 +2,9 @@ # # SPDX-License-Identifier: Apache-2.0 import pytest -from license_expression import LicenseExpression, get_spdx_licensing +from license_expression import LicenseExpression +from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx3.bump_from_spdx2.license_expression import ( bump_license_expression, bump_license_expression_or_none_or_no_assertion, @@ -28,7 +29,7 @@ [ (SpdxNoAssertion(), NoAssertionLicense), (SpdxNone(), NoneLicense), - (get_spdx_licensing().parse("MIT"), ListedLicense), + (spdx_licensing.parse("MIT"), ListedLicense), ], ) def test_license_expression_or_none_or_no_assertion(element, expected_class): @@ -40,22 +41,22 @@ def test_license_expression_or_none_or_no_assertion(element, expected_class): @pytest.mark.parametrize( "license_expression, extracted_licensing_info, expected_element", [ - (get_spdx_licensing().parse("MIT"), [], ListedLicense("MIT", "MIT", "blank")), - (get_spdx_licensing().parse("LGPL-2.0"), [], ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "blank")), + (spdx_licensing.parse("MIT"), [], ListedLicense("MIT", "MIT", "blank")), + (spdx_licensing.parse("LGPL-2.0"), [], ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "blank")), ( - get_spdx_licensing().parse("LicenseRef-1"), + spdx_licensing.parse("LicenseRef-1"), [extracted_licensing_info_fixture()], CustomLicense("LicenseRef-1", "licenseName", "extractedText"), ), ( - get_spdx_licensing().parse("MIT AND LGPL-2.0"), + spdx_licensing.parse("MIT AND LGPL-2.0"), [], ConjunctiveLicenseSet( [ListedLicense("MIT", "MIT", "blank"), ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "blank")] ), ), ( - get_spdx_licensing().parse("LicenseRef-1 OR LGPL-2.0"), + spdx_licensing.parse("LicenseRef-1 OR LGPL-2.0"), [extracted_licensing_info_fixture()], DisjunctiveLicenseSet( [ @@ -65,7 +66,7 @@ def test_license_expression_or_none_or_no_assertion(element, expected_class): ), ), ( - get_spdx_licensing().parse("LGPL-2.0 WITH 389-exception"), + spdx_licensing.parse("LGPL-2.0 WITH 389-exception"), [], WithAdditionOperator( ListedLicense("LGPL-2.0-only", "LGPL-2.0-only", "blank"), @@ -73,7 +74,7 @@ def test_license_expression_or_none_or_no_assertion(element, expected_class): ), ), ( - get_spdx_licensing().parse("LicenseRef-1 WITH custom-exception"), + spdx_licensing.parse("LicenseRef-1 WITH custom-exception"), [ extracted_licensing_info_fixture(), extracted_licensing_info_fixture("custom-exception", "This is a custom exception", "exceptionName"), @@ -84,7 +85,7 @@ def test_license_expression_or_none_or_no_assertion(element, expected_class): ), ), ( - get_spdx_licensing().parse("MIT AND LicenseRef-1 WITH custom-exception"), + spdx_licensing.parse("MIT AND LicenseRef-1 WITH custom-exception"), [ extracted_licensing_info_fixture(), extracted_licensing_info_fixture("custom-exception", "This is a custom exception", "exceptionName"), From 85b480a30a543ba72788ad5c12229f801264bfd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Tue, 22 Aug 2023 17:52:01 +0200 Subject: [PATCH 325/354] [issue-744] implement validation of external license references MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- .../license_expression_validator.py | 32 ++++++++++++++- .../test_license_expression_validator.py | 39 ++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/spdx_tools/spdx/validation/license_expression_validator.py b/src/spdx_tools/spdx/validation/license_expression_validator.py index a59aec9fa..e463aa9b6 100644 --- a/src/spdx_tools/spdx/validation/license_expression_validator.py +++ b/src/spdx_tools/spdx/validation/license_expression_validator.py @@ -7,6 +7,7 @@ from spdx_tools.common.spdx_licensing import spdx_licensing from spdx_tools.spdx.model import Document, SpdxNoAssertion, SpdxNone +from spdx_tools.spdx.validation.spdx_id_validators import is_external_doc_ref_present_in_document from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage @@ -42,7 +43,36 @@ def validate_license_expression( license_ref_ids: List[str] = [license_ref.license_id for license_ref in document.extracted_licensing_info] for non_spdx_token in spdx_licensing.validate(license_expression).invalid_symbols: - if non_spdx_token not in license_ref_ids: + if ":" in non_spdx_token: + split_token: List[str] = non_spdx_token.split(":") + if len(split_token) != 2: + validation_messages.append( + ValidationMessage( + f"Too many colons in license reference: {non_spdx_token}. " + "A license reference must only contain a single colon to " + "separate an external document reference from the license reference.", + context, + ) + ) + else: + if not split_token[1].startswith("LicenseRef-"): + validation_messages.append( + ValidationMessage( + f'A license reference must start with "LicenseRef-", but is: {split_token[1]} ' + f"in external license reference {non_spdx_token}.", + context, + ) + ) + if not is_external_doc_ref_present_in_document(split_token[0], document): + validation_messages.append( + ValidationMessage( + f'Did not find the external document reference "{split_token[0]}" in the SPDX document. ' + f"From the external license reference {non_spdx_token}.", + context, + ) + ) + + elif non_spdx_token not in license_ref_ids: validation_messages.append( ValidationMessage( f"Unrecognized license reference: {non_spdx_token}. license_expression must only use IDs from the " diff --git a/tests/spdx/validation/test_license_expression_validator.py b/tests/spdx/validation/test_license_expression_validator.py index cb0ef0c66..e965f4803 100644 --- a/tests/spdx/validation/test_license_expression_validator.py +++ b/tests/spdx/validation/test_license_expression_validator.py @@ -15,9 +15,10 @@ validate_license_expressions, ) from spdx_tools.spdx.validation.validation_message import SpdxElementType, ValidationContext, ValidationMessage -from tests.spdx.fixtures import document_fixture, extracted_licensing_info_fixture +from tests.spdx.fixtures import document_fixture, external_document_ref_fixture, extracted_licensing_info_fixture FIXTURE_LICENSE_ID = extracted_licensing_info_fixture().license_id +EXTERNAL_DOCUMENT_ID = external_document_ref_fixture().document_ref_id @pytest.mark.parametrize( @@ -26,6 +27,7 @@ "MIT", FIXTURE_LICENSE_ID, f"GPL-2.0-only with GPL-CC-1.0 and {FIXTURE_LICENSE_ID} with 389-exception or Beerware", + f"{EXTERNAL_DOCUMENT_ID}:LicenseRef-007", ], ) def test_valid_license_expression(expression_string): @@ -136,3 +138,38 @@ def test_invalid_license_expression_with_invalid_exceptions(expression_string, e expected_messages = [ValidationMessage(expected_message, context)] assert validation_messages == expected_messages + + +@pytest.mark.parametrize( + "expression_string, expected_message", + [ + ( + f"{EXTERNAL_DOCUMENT_ID}:LicenseRef-007:4", + f"Too many colons in license reference: {EXTERNAL_DOCUMENT_ID}:LicenseRef-007:4. " + "A license reference must only contain a single colon to " + "separate an external document reference from the license reference.", + ), + ( + f"{EXTERNAL_DOCUMENT_ID}:unknown_license", + 'A license reference must start with "LicenseRef-", but is: unknown_license ' + f"in external license reference {EXTERNAL_DOCUMENT_ID}:unknown_license.", + ), + ( + "DocumentRef-unknown:LicenseRef-1", + 'Did not find the external document reference "DocumentRef-unknown" in the SPDX document. ' + "From the external license reference DocumentRef-unknown:LicenseRef-1.", + ), + ], +) +def test_invalid_license_expression_with_external_reference(expression_string, expected_message): + document: Document = document_fixture() + license_expression: LicenseExpression = spdx_licensing.parse(expression_string) + parent_id = "SPDXRef-File" + context = ValidationContext( + parent_id=parent_id, element_type=SpdxElementType.LICENSE_EXPRESSION, full_element=license_expression + ) + + validation_messages: List[ValidationMessage] = validate_license_expression(license_expression, document, parent_id) + expected_messages = [ValidationMessage(expected_message, context)] + + assert validation_messages == expected_messages From 777bd274dd06cb24342738df7da5ab285d652350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Armin=20T=C3=A4nzer?= Date: Thu, 24 Aug 2023 08:39:48 +0200 Subject: [PATCH 326/354] update changelog for 0.8.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Armin Tänzer --- CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8382307c..2fa67bbe8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## v0.8.1 (2023-08-24) + +### New features and changes + +* massive speed-up in the validation process of large SBOMs +* validation now detects and checks license references from external documents +* allow for userinfo in git+ssh download location +* more efficient relationship parsing in JSON/YAML/XML + +### Contributors + +This release was made possible by the following contributors. Thank you very much! + +* Brian DeHamer @bdehamer +* Brandon Lum @lumjjb +* Maximilian Huber @maxhbr +* Armin Tänzer @armintaenzertng + + ## v0.8.0 (2023-07-25) ### New features and changes From 44196efd14de18aa1363a6ffd6c8c332433e1056 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 7 Sep 2023 13:05:14 +0200 Subject: [PATCH 327/354] add `encoding` parameter for parsing files Signed-off-by: Christian Decker --- src/spdx_tools/spdx/parser/json/json_parser.py | 5 +++-- src/spdx_tools/spdx/parser/parse_anything.py | 14 ++++++++------ src/spdx_tools/spdx/parser/rdf/rdf_parser.py | 6 ++++-- .../spdx/parser/tagvalue/tagvalue_parser.py | 6 ++++-- src/spdx_tools/spdx/parser/xml/xml_parser.py | 6 ++++-- src/spdx_tools/spdx/parser/yaml/yaml_parser.py | 6 ++++-- .../spdx/data/SPDXJSONExample-UTF-16.spdx.json | Bin 0 -> 42164 bytes .../data/SPDXRdfExample-UTF-16.spdx.rdf.xml | Bin 0 -> 685454 bytes tests/spdx/data/SPDXTagExample-UTF-16.spdx | Bin 0 -> 36852 bytes tests/spdx/data/SPDXXMLExample-UTF-16.spdx.xml | Bin 0 -> 48912 bytes .../spdx/data/SPDXYAMLExample-UTF-16.spdx.yaml | Bin 0 -> 40556 bytes .../parser/all_formats/test_parse_from_file.py | 15 ++++++++++++++- 12 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 tests/spdx/data/SPDXJSONExample-UTF-16.spdx.json create mode 100644 tests/spdx/data/SPDXRdfExample-UTF-16.spdx.rdf.xml create mode 100644 tests/spdx/data/SPDXTagExample-UTF-16.spdx create mode 100644 tests/spdx/data/SPDXXMLExample-UTF-16.spdx.xml create mode 100644 tests/spdx/data/SPDXYAMLExample-UTF-16.spdx.yaml diff --git a/src/spdx_tools/spdx/parser/json/json_parser.py b/src/spdx_tools/spdx/parser/json/json_parser.py index 9ca35fd85..269e968a4 100644 --- a/src/spdx_tools/spdx/parser/json/json_parser.py +++ b/src/spdx_tools/spdx/parser/json/json_parser.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 import json +from typing import Optional from beartype.typing import Dict @@ -9,8 +10,8 @@ from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser -def parse_from_file(file_name: str) -> Document: - with open(file_name) as file: +def parse_from_file(file_name: str, encoding: Optional[str] = None) -> Document: + with open(file_name, encoding=encoding) as file: input_doc_as_dict: Dict = json.load(file) return JsonLikeDictParser().parse(input_doc_as_dict) diff --git a/src/spdx_tools/spdx/parser/parse_anything.py b/src/spdx_tools/spdx/parser/parse_anything.py index b91f76111..ae5e69568 100644 --- a/src/spdx_tools/spdx/parser/parse_anything.py +++ b/src/spdx_tools/spdx/parser/parse_anything.py @@ -9,6 +9,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from typing import Optional + from spdx_tools.spdx.formats import FileFormat, file_name_to_format from spdx_tools.spdx.parser.json import json_parser from spdx_tools.spdx.parser.rdf import rdf_parser @@ -17,15 +19,15 @@ from spdx_tools.spdx.parser.yaml import yaml_parser -def parse_file(file_name: str): +def parse_file(file_name: str, encoding: Optional[str] = None): input_format = file_name_to_format(file_name) if input_format == FileFormat.RDF_XML: - return rdf_parser.parse_from_file(file_name) + return rdf_parser.parse_from_file(file_name, encoding) elif input_format == FileFormat.TAG_VALUE: - return tagvalue_parser.parse_from_file(file_name) + return tagvalue_parser.parse_from_file(file_name, encoding) elif input_format == FileFormat.JSON: - return json_parser.parse_from_file(file_name) + return json_parser.parse_from_file(file_name, encoding) elif input_format == FileFormat.XML: - return xml_parser.parse_from_file(file_name) + return xml_parser.parse_from_file(file_name, encoding) elif input_format == FileFormat.YAML: - return yaml_parser.parse_from_file(file_name) + return yaml_parser.parse_from_file(file_name, encoding) diff --git a/src/spdx_tools/spdx/parser/rdf/rdf_parser.py b/src/spdx_tools/spdx/parser/rdf/rdf_parser.py index 3856f8d59..cfa7054d4 100644 --- a/src/spdx_tools/spdx/parser/rdf/rdf_parser.py +++ b/src/spdx_tools/spdx/parser/rdf/rdf_parser.py @@ -1,6 +1,8 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from typing import Optional + from beartype.typing import Any, Dict from rdflib import RDF, Graph @@ -22,9 +24,9 @@ from spdx_tools.spdx.rdfschema.namespace import SPDX_NAMESPACE -def parse_from_file(file_name: str) -> Document: +def parse_from_file(file_name: str, encoding: Optional[str] = None) -> Document: graph = Graph() - with open(file_name) as file: + with open(file_name, encoding=encoding) as file: graph.parse(file, format="xml") document: Document = translate_graph_to_document(graph) diff --git a/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py b/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py index c28596363..b2c9c9e56 100644 --- a/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py +++ b/src/spdx_tools/spdx/parser/tagvalue/tagvalue_parser.py @@ -1,13 +1,15 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from typing import Optional + from spdx_tools.spdx.model import Document from spdx_tools.spdx.parser.tagvalue.parser import Parser -def parse_from_file(file_name: str) -> Document: +def parse_from_file(file_name: str, encoding: Optional[str] = None) -> Document: parser = Parser() - with open(file_name) as file: + with open(file_name, encoding=encoding) as file: data = file.read() document: Document = parser.parse(data) return document diff --git a/src/spdx_tools/spdx/parser/xml/xml_parser.py b/src/spdx_tools/spdx/parser/xml/xml_parser.py index f0cd77025..4d18fdfd3 100644 --- a/src/spdx_tools/spdx/parser/xml/xml_parser.py +++ b/src/spdx_tools/spdx/parser/xml/xml_parser.py @@ -1,6 +1,8 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from typing import Optional + import xmltodict from beartype.typing import Any, Dict @@ -36,8 +38,8 @@ ] -def parse_from_file(file_name: str) -> Document: - with open(file_name) as file: +def parse_from_file(file_name: str, encoding: Optional[str] = None) -> Document: + with open(file_name, encoding=encoding) as file: parsed_xml: Dict = xmltodict.parse(file.read(), encoding="utf-8") input_doc_as_dict: Dict = _fix_list_like_fields(parsed_xml).get("Document") diff --git a/src/spdx_tools/spdx/parser/yaml/yaml_parser.py b/src/spdx_tools/spdx/parser/yaml/yaml_parser.py index 1a7349eb8..5a269e84d 100644 --- a/src/spdx_tools/spdx/parser/yaml/yaml_parser.py +++ b/src/spdx_tools/spdx/parser/yaml/yaml_parser.py @@ -1,6 +1,8 @@ # SPDX-FileCopyrightText: 2023 spdx contributors # # SPDX-License-Identifier: Apache-2.0 +from typing import Optional + import yaml from beartype.typing import Dict @@ -8,8 +10,8 @@ from spdx_tools.spdx.parser.jsonlikedict.json_like_dict_parser import JsonLikeDictParser -def parse_from_file(file_name: str) -> Document: - with open(file_name) as file: +def parse_from_file(file_name: str, encoding: Optional[str] = None) -> Document: + with open(file_name, encoding=encoding) as file: input_doc_as_dict: Dict = yaml.safe_load(file) return JsonLikeDictParser().parse(input_doc_as_dict) diff --git a/tests/spdx/data/SPDXJSONExample-UTF-16.spdx.json b/tests/spdx/data/SPDXJSONExample-UTF-16.spdx.json new file mode 100644 index 0000000000000000000000000000000000000000..570d67d3e2ea238e572047f46da8574146f82c8f GIT binary patch literal 42164 zcmeI5X>%M$a)#%#Bm5sG;18BI4DbL?IUHUP1SPC^833h~y$%@{DJ~(BOMs%dj`cs6 z<@c!0|-?kth>$9)E8od=Xo8_)`UE{Zn^6R>;zt=Y)d!y0k zMt{=pjL8Vu=DEHD!#lk*ud#ZI`FX5&>Tgf?jRoDN{>Gzg>g~E-SM)hX-4;H9Zc}Z? zdcD&BodU^={qKx#Trgj-x1kn{xGP9^b!A&{jy3w*GCNv;HTScj>&(gU&NVa%JlAjs zHD*M=%YyW>xPo_RdRut7GP)(+nb);1bmi*k-w*8(9PS>_?mq+*^n0bhox*|l1s7C! zsaD&gd-?_~W;M#3Mu2~~IvS0TLZ73 zjXpoS993b=!UM|)Zb;{d0ldROB(5x-qBgt zbZtZbuZw=y^=V7odqclmSLxz)M=sF4PA&z>lS6@pv08fmmtpoy?0hx24B8!ZR6 z5^fHM*ScH~(ow^+Ca8ch@qKCZyJFGCdPmc3N;8f%>sO+|`@(h43QdsV%jFLp?9W$< zKKAFU)#v%@^R?>p_3HDD>hsO&^R4RhZH@GmAbwYLIealIuO)2!8{rony)BKntrkF> z`iU7}1+c5{OP}|3FSgS&UC2pgQ6nDh?cm&3`bQhYQyEi0L z;lrdIN7G?DpgQ_%dJki_K%3qIvX8#C{L|0g0aRnn5exTRJcT7nZwe}5=YavchwnlU z=1Z=jYk$%;>?4>&yKsMMU-%R(y(*(yr(-Ly$@FD^Z?}RbMuZM~lHtS}(s(%T!2c`F zql+y@1V-ixR)LUtVeO3Fuomm01#_Y;ceNaxuvkOBR14;S{RUg~Vm}h;^EifQXwFIL z7<~v^=95j~5Lm&=n~JAw7mvn@XPLfc?T>b`V!Cb#Q}$*9y59zFLS77YmttKnB)L7P zaY-~qTA(a8md`&HuIBS|ecBOahqyoFE4hD?jHgZ*%QC>#Yh|pl=-^jkC8HvuAaU22I7~MqSctJi0UbPXD=+Rtt(u`TR)j#-snz-$Ln+UjI>lw0KzV!W-srLW_VUgFKgxMYS9$S>TOZ&o~Um=e_5{HDbS4d{gI#= zmwq1T_qF}r)^r^`6VOjHTEYf~#w8A4(b)KX#N!LX$Z{EJt;{dxd#{Z9@L-zgNqQLwcA!(5&e1iLeZWU=I%xsr**I!4dG+qQ>y($Z_x~t^Mu03MNYkqaw4$ zLhwm)I}m@Xah5bL{}}~{7>j<_bYc~5n`K*5z}P!6tT>>XoRD%1XrDB6cc{q z$B0{ufx~!&*`I&3^6_vGvkQ5?C=rP%gXY^71wMWpV!cUR@bM#$z|AB}iFL$+ewb*3 z(Joq)5uN~^=S7Gv!ZX5ePA}#|MiqvDn1RUiB198M$CV#Gim)$uF`|cvGCy|IFdP+r z%xJ-w`M6QS*+&Q0KG1r{ZE2tF;o{`z7^@UIC3!l~( zVr?zu;^VHpwElY+s*B>yCtRP_7g+iHw7x(_?bG@~@OmBBT; zjw0%M1u9Qm4a_rsC?cPlqak8`jhU9)gD$~$@a`vtM062v5MvOPg)br zlJBKXDAw|+TfVCGEU#3&R?hLo==WM*qIO`rtW>f>OdQS{7uGwf708-;Wrk`c=0B$v z3+fq+QCCFOsOw7K7c31``nZR>dS|S744k47seyW_Uhw4@-8D^K!(k;R`i1IXGb^j= z3Lt3kR#g#C3xvyhryaCrHGtY9S1Iw0v8d?4Mw@Oqif8;%7#i*!f0Wt36SQyCE7jq| zm-H2o#*C;lBkuH=a8mGHc(qUfxT%IEp9xNOL}Av7Uh0p`JQ)63a8euB=c33QLwWBA z2q}S2qCTXpK!iuW(Fl%>p<-}Izkh03wncHOaJn^+-P%v;NT}g5pHR8Ny&Jldx;*ej zJ?Q_a1suoHK4BVT+m%xg;N(rJ9y?r zks>7hI5n4yj_#RMhn3QH{%Z!-xK|@o=>HRc(+L0!2rTDNpx!M*lWnC5zn}@~<|0H;? z4>djy6y6cmhpAv{!n;tARb~2R|IB9bnyh8;muEFDqdH4}7_?vz+E5$6UTjkr^5jcm z16ESn6?S?6gIM_10^55Ie~@oso4-;o4`lz{BKgXCbGmxqq?l`PkE#nktMz!siMro} zVY&?6STTa3ou)lJXWx%_0FC7;d}1T-jm+_l<@dV&d%c1ZFLf8b)|_aJU!1gL&n5mb zkxAB0pA<*K_1t*vcss5bo6I9Mx0@GJh9=*2n0!6gys`!aJcbsGdhVKvEiDqKLsi_d z<`r_hF6rYlR88zou1TC+X>t78?WkZ}(frzq3g&PzDz{xZ`Jt;SnE!CqHa5mJrzfeb z=vKDYb+*)uQngB()nZT1rn>v|br@j7ke^*;_sMH93=Oro=TX&toO%o(Iq!<@eRL0p2yEInPE0tug-)l(h6k@<}Zd&gT{>>gD+)I#t5W{2aKj1{{BPmeUW!(|1&h`_d0DJGC1G(Wp819Mh3nx_6Y9B&-RK$_;^s` zrSR2Xl^~mwYaB#Eaa={@1`PP`Z}pCU%rES2Vn52fUfwGk8NKcp zXUPkkVZvU2cwzp6^1`a{#0e+p9B_AXo>)*1^(s@#172sTxs5fZ%%yj=V7F4{pPBvk8KeGz`$$&3tCA(jnK{F>E=b4?$H^90sCGTWeX)LrULa%S6^$H|e2;Ml#?w9~Mra#ns<1vt zu9AKukK~@QeAry)kFbYuQBEJfs1ccojZbA_~dS@kYlAZNc(`#t%P!Y+fM@R@*4`=Nf&Pc089?O&(!col1 zXPTscfhB7-ZpbgOMV`XcN>QtKLkcIK#q>ZP%=Kac!fJBQ@JK@^G2PG_>NP=gMbzcg zrFl{9hORu-i*KB>bWNu$ZR@qE7bi9GJ3PysX{{NPlb5=y--ZRAKELy%I6VrEy)5Xi z2+DQA&uLQY1x8@KrPsP3zol7R)y%Nvw*^1z7B}>X*7N)Cn`byHPJp^`3i@2pd^Xg> zmY_o?njU=G(j0FJV$Q?kkF%rJ^?pm&Z|k1h`o`H)+j?>Js(RwIEzZk&s?ULeO?~G? zEx&K=|AL3HsWH0r9p>onnKxk}!hd0c?ctQ(X=Z5}{74Y^<5^G8C%SMZ!SJ?5w z{;@^9y3q^L;W{H?D_14>`>+kb#$Z3l6&T8P{7v=evl_jNepx3>q-{$LR(0cxwKa8p&ZB2y8)|QW)y1gQqUTAFhIdf+He6eVfBa6p65oNJ`+5)C zfmKg>x4u60C$Eb&dMV7!=`PpoJkvdIRk8C-J>r#YHlJC)qa}WgPYy*!=JXxfW83~Z zz=<*UI0?|c`O!KZdO}^^;ks?{3%K6i*OKq6*>P@yPwC(!j_-Ow3iEnj*Xwn$pKuJC`g`G^t>gKk&=Vg5Uier>AoF&`PkR`xDNoc#|yU9lp(5Hklx zOh?DXEe{P@xTqW59g)ufYwx8E(Eg!=h>|$tvK#S&+uegmz10hO8gf8~l_Um4yX|TY z_PAHoH$DkEw|~zcG%7GT(wfwY{3p3>@@;YEFtFDd0ZSt5s&En6fyf&;SKLy1dM(?P zk?yH1F>BYSB#ttoL|@l2O-Lc~YRPpa!k-1VSLw;%N4(-14&p27Ttmi@DN>GgVlEA;MEybSKe2Y&Y5GjbezyjYv)D1ZV5jn&VxheRh4-ZJ;`G^pUNy#MvfXc zPG>s#$jh1oyg^ksTpSs)Xj*e|8bDc=!87!Jh1z)++F8hbAI7T;TP~a z+?#6q|3;933$$ZSOd0 zRzp$x*`AktOPFhIUe{{j{e_hXnF?&r=od65nyRJq_o6VFSLgfCJ?L9JMfi!<=-@bE zIY)?{Ftw*n%i2@N|K{3|-t%eJV^L%8=<49F&Px|=APY1L7Ps$B>yXhSqo~I9*gjX6gSP zKHZTs@cLS9`dDt-9?=Te@5w&dQ_+MSA46W*bUuzXVfbTn>d&%_1y63Z#do}XNnB6g zanGzEuph!sk*=JBIeRD?Q1Xlrxx=@p!H3fM=ppQpG1WvtCi-ajwE+eLeB}`v!AeiJk;kKWctm z?CVaY&$)Ma74Ac5x_8Rsyeqtl9(#F!htzW2xei5f7hiitwA`P~QC7H?n6uGttKz+% ziyr7hgBC$c#Irh%mNsnNZ+C@dC~iVW9;Mf@nQa?Z4g#-^8?Z`yB@XS{U!sU<))BHt zpVOK#P^@Uj4r|xm=PE+v72@eE*vQCU*l)o8`^0i*+5cE}X^^pRt3%EzN1pa7J@Cwi z#jXY79Q^jksQ8H|f!9k1_KNF?omtgXUD8_9TzOsA`%Qh{J)p;iuFsYi8HbzdeNK5a zo{V*=%(u?=_hsTk=)r`Q$nJ0q^&xD%FL*O6I#Pmpl9aPhR4lZ52mZiw;JFQWjpws(KN74($+pFl9-_TyeHeYc9xTU%%l40`dI9~I;+U!0B@C5Xx6P+&)!g*8~RK=0jtlfRHf@9@M?UsU!0S=$u{7Fv!aWn4CM?$BO&Q{^JJ_1TpsRBiFelVanY#Z z{bPIDzU%Bh75dnJ*1~PYcGQ|{@H&fZT(3GW7X2<}{tIJK31W z*BnUGhU|Rpt4+?qvF7bKuDt`_8XYpU+acyXNrUio4W3Z3tbG{2MIF-hE?$Zo;`wCQ zoA$YVEnQpPk=Z}?kMUbKGV^&YuFgISE@d2EDS3`sVt2KxM^jtlUBfA@<-!u<2ksPz zv!*M0#!k2M?pwbh8Dj5WWC^|M5m}b?%2H&8<#Tc2*~}>N`?=b^su81lhaK_V>K*R~ zw-&(G=AG@#?-y?bAH%EWtW8k2_gVQ)RS_D-o)Gculfp}6;qeXZCHeVzyV|jYzT6Y$ zvG=SjZmXZq%gSR|ozqyh(6Ye1ATI-J=-(zdz{6Bm~(l&=YU!)c1x2l>U)fBzLj2* z3-{!?A?xWShE>bnpR3;%4zAe4O@Ezh&TX?c8_{R>!f*CU?aSwgoU2mr1l%i;3Nwkl zg7ls3e=aq<-aE(2G;1{Eo2c&W>ooA#MlXHe1zq2^InADyfSX>A&LsxDu_9FIatA(H zTZ`)b9GTP~nt$pEs{i7MMAAF`R%o;boL*Jkl)k3TUgY6$md)fxnUU4#AsfBgRtSh8{)59w)4 zK#mj|^WIBd^O$GM75X2h51Bd7AL>I@d?s^#>|cx-)^Z9rcJW?k8~tQ^tlvFlQ+=;sFrM)3 z9VqSjinQ~yQ0nKNPxpKppLfQ5hE8Y<$PPa-k@3&s`S#4&C;2@r^SP&a`!tJu2K$^^ zc(!hNyr)sF>fSti5FeQlz7%bs3lzF97^v5#F@(KlP9G6IqpG^q35Z`Q_^FGIchxdoRPXuJO{^*_Ms2{G&csP0fWcm z`RX++!Pm({eJOD-@r;XnX8MYHO$b>(UlMF!hbOUveLhX@naCtF;jOMQTvm?}+qHTpx#Fk@uhodo@b#+- zlj=a=+{CzKzVJ5jg!{1OIYTWptzPwr(0xn(%d65mF%G$2>&AY2-$N|(RN8~gNwnqp zMwew_L*vsj{$>h)wYw?ezN{`>QGe`mAFdPCui0)uDXY8P)R{ zT01uOPeL*C&bI9JTWK&?-US6XlcJAHkA+^i$aFhwUYy%iWAuEvu^wr->a*3*_r#@G zlgJDOHI6F}-LWidR9}YoS+`&Id~T?(!3x7h9Byp@f~Tr-SI;E<*f$mFR4%J*?4Tm)Au#7yE|9qbM=6rE+ z*lw2T@o-mqf}OArBqfW|7|tGieJ)xfqBFexq4S4o3tj8GX*gxt9p}?y=1b`evNhxw z*Yti@*ojQfd040Ed3zdsoSz=~5SDrx{eKcHM64DO3}>aE#%r0DM~Ech?!T4){|DBr B5(NMN literal 0 HcmV?d00001 diff --git a/tests/spdx/data/SPDXRdfExample-UTF-16.spdx.rdf.xml b/tests/spdx/data/SPDXRdfExample-UTF-16.spdx.rdf.xml new file mode 100644 index 0000000000000000000000000000000000000000..c3760c7c8d2a1f0d0c6e05c22b24700f33d1b85b GIT binary patch literal 685454 zcmeF4dvhE|mfibbJHp=q=7e`K;UOvNF*A~86#?-fahD=#0+L3t;jksXW=13>lawg> z@zrhLUmYCY%&e^H>IOgovj_&!Ky_8-&HFg_ky)Al@BjX3^?dbU^=S3c>fY+w>c;9n ztp5FK=kVVztEa0ct7oeh@$HM%k8$5GtAAQuSp8-7GXDJ-S1-pue{*T|L$vicuBgS! zanHl}{b}6sn|NxfW!*h)_tlDjm*W3>@zZTzS$#PCyS#d5^=|a_Zv4A=*yF|M>2=Wi za`kOcdU2q9uIC5Q>bEhDao;~hOAmu9KgIa}8tvQ<3hu|r;y#?aA98&dBm8!d)+cY|^{4nw zvj1pxJ@_iBp2dAnR{MwFT#w&*_Tj+&ox@f?ihI6`vHTRzjCt%^~c~J-(3k^elLFeaJ3iTU5($~iND`jeGvEl zF*N3C{Kel_VyxGO-hO&R{k>@aQ9O}-zl=M6h<-1|{g>kD{}j*e#n|u0vwse|(ftR9 zcfE){N^V>TF88^)AKdzDjOfQ`;bqvIE%7XHtsQ+mmJ7v*L6cI4&>S@7li>36;Mvpo zURL%~$arV2_ zt+gFNE7M1ZGKFIFkhtM_Akm*Tf?S3k%98WT->_O&gwQ=I%X zZ0Fmc;rrm~Wo1#wS z2o8`{5sh-4cpj@DiYX=Mc6g?|UP`I_-S^`g(d*j&h#kop(Ji7rdR}6KWO{D-^5A!$ zuchW%w2dzT&2959qMcS}P5rOQHPgVS$C>i~hu{^t_Q$LL5mx`hfJ!yK^zK0FY?S!s?bo+5Nd*eQ$Uq%EiKMfJ|PShE8;;%=C-#`WJ zQN_r*La9&5X=qzVUrOk5aJIGz%dWldvCVz@*`%f?)l%+ArFYLd$s^@D=YU_Y2J1)8 zk~Yx?as?rfDs`j34B!2A^*=)nDHUtfe7o!U3U_FW9C>HZo}G}Wst8a*Eg|){wQL;RzT(#ZKq|b{J{=4SvA-#9h)rJP7wPF7QD9gc{Y;xC1P! z+usQtMqmFD-E09Bj zcGTxo)6r;lqgMS+RGN{3v75e;r_`l$kuPxs(p3${nEWE1ud8=l zaaCDf4*w^#ujAOH6Q1N#-0MhOsLHq=53QEZa24-MX5@(FY(-Fa!gshXyPej+Cs02% zL^w_EoKaKGkKyI;YCI=hc@j?(%W&nzn|4Y*gHB5{q-=*g*;;6i`fc=7+DTH4#Mf)7 zX7|QAh>nnBN*l139}2$KI*6yoQ!!p?^0JY&IarQvtgSx}?Uxv+_$4C&#Yk8zJn^jB z+12B(gX7NwkNP@1k9V&QpG_^vY>g+0h2U`;b)heUiFWU3)O;1D+2Gk+BfD^nOSkt!*<|p)pT5#zoJZPnH&<*2IJ5_DO3*cdCwJDbh@j zBxSK1cfsF!wS+18F{J%N)Ut>xN=n=g^0%&Uk)&njA9i!o3UqCN<= zVdpz5>;8+4wBNXGjvtqXBY{$9zKg%eIUX$3dF7^#NRh5aEGgTMlo_4JpFZ0$3Kokl zJEw(Pv_lMm&N@%PW1&lln8sAugSZW4#52om7j4trypX<(hlCO}8c)SfSuZ5cP$rTV zjvX^fDg=sgWHlNcbH$pg;V!N*^QoMxtVtQ=rt7RW2y?E?|U&e^sm$9 zI!cusY9CF{9u;Vpnuk0=T1LN2T5wi#*NL>&HK>)uh+Sy=$q?}nk3JhXYHj^)xZ+w2 zv8`s!rL9yD%rTx+4f#>r1KKhIBtvh$YpmHlt}Pp(+cKv#5_&wVXm~aF1sB^I`6e+y zi-L33fn<Ps{7g^3N)Kb* z#0pAnO~hX|F6%$?6LqSfl1Wha`tC5(t8=|F&XGkL=~FJoaLLN_<``Tpv($P~P}Ysi z7ggBc{qpg_`^_pJB_`)Qfn-*41*(XRh-vV)Pr{11=2;t%aeiFmTJExO_3ORjvXCB+ zO$%qd%r`Y|P+4_cB17et^eY=A3Q-Lmy;(NaR|B#Tui|yZ zQL5*fDJZKP=&U?*X<z5#s+ZPI+N^Zh=%iI>$<&ynV?DmA zZcSc-oS9eRH|n;cxvZsR_N(87*u*Pv?e*{!-day0UHm7lp&js0wE@;@skde0tJ{`_ z3Z*v(XqyXv)I4!`LyFuJOos)b?T<1sPbS&Rha`B_3+*%SJ~fEOVfGZqJww zrLMA(MYVowPWI5Bm~P3j&X0JSd30!390VVUEES=fd*Z7Y=|be5ljP2z+2{h^Q^*ef5`!zFHWu{I+vAkyLa$j>BJ7tn zFmiNJv!Yq$V+?3787bNBrqa5< zSZ2V|Jym6l8hJnMNt4!(Qz%u>mVj#Wqv}__`*o$XR7QCE(1dq2lSUy`NoAs0{x(LF zyCE%Q5FpI0N;l7O#7OaLyEWPp zEfXslvl(Fp5Rg&g_2as_Pn@rKfvCbLVM;q**1>~@Uj2r*5K=<#x)D*+W<)JlL0c-j@~vf`=@sPb67Bka zQ)5$>_12VV<^7%{SPo$7x4 z#hWwq46S;~nPm1pox8XP$Dd=Fa)s!noG&r=jy5XZsgkXY%JByy#NvpO znSmY49%=JE>xPmOte#V?pQq*Rh;aUSK2p|68C@$8WJ%P4 z?U!pNb#EDo&?8bPF>zj(;8|&7`~C+g1H3V?L4Y#h9t72)p z7khi=zQl=)sd7!h{HUZGtQm1d1HFL4jQr7bz2VGnwmgk$tnZ@LYmXj8l+vRhBNwcu zj9dIodp)C=`ZwQyyt&%@TSQm)LLM(TBtzQJt-xpjTq8ybRP478~7PTndkv_k&&Nlgq60^dhm9PO^JF-HDA6{ zb(9k6dN})WP$UhVk~d?syiex6q2rd|cgHG0Djv!T#3^K0TDJ}J@7nl%t52ox(b{}mGw*fPtK(||7__>t6)v8tq3lV1z57SK}!rC@vS9kYS&5f z@6nzf9KoKHGn#vrweuYB@&KCQgL<=Cw@uQPQ{DWus|r z$oZmBQ2xs?t?)3jpi*8b5jcC2mb+|RN40K7q47$R)CJHq;e@L}r4;Z8ZS?G20mxcD ziWX~5Vh1G;myN7v17j_h)@T_GuTIB|dxfnmxk z83(*}+yqaB#L$SW$L}krjy@Gq1cusO-d6Udy$_9c3)$dRAcQ zdu+9|2j7;BDYd;_Co4@^Dgkn=XYo&Kh*(qNY6d9&JVsn%WT{Q)sjI&{)#}T-aX2H+ zJrXkaSN&^RzwG0g(a_F$nf;Y-qL)=u^fT#4x6`^5ZwXmkeXAv8J;(}=_>8`+8>!G7 zE%bbtFruydqA6h6l64nCh^70oNUO(o;M_$>CH^lR&onR5Z}n&@(J}BRwRXL&+XjX8 z`G!a>7kq)~PHrrd2)L`(Hs8snMfZ&4vpNO3X$}y5WyK>kYt?3re2EV7AIQj>97cDjaj_Say2uti;eKTuLD{n+Y1Y5FrQ@yL|9%VnItbpN z#aZtZIvq^-5VF7@;%+d@kz>wR6Wc0^!IBaaWbK{@5PqRi?whvszM z6!1lKVrk;f{HSEd$cwiyWuNc;P99pN3#7*=`7AA?; zZ=0aGtv1i=SRG|!>DH|D=FId;lhN|IHQsH$OM4(TpVJ7;Y9qxH^wY0~bNT}-vG%*Q z@cA)*8auM?56{A%uj99a)#p)NXGd24-isYt?+v@QQg6RL^rZb>`@6y3iT&lY%j-As z`7iMdJH`q%m2bOcw(MHlCF2lBG=6cIZ|+pLTlRZC39U`hM%B~ z_6)anIyVtLy?Di14L=S-qplBhV*j_J*2Z{m47=LiUVRqdeG&g}$9?q3@ApF1pC9sb zFLu7Y87quY z&_v{-dQ4^!bp)7JX`96F5a$q4rNrs^MXcb(@^lApB$%2ymJ+Yl)dLibdA~FIlDFwa z0ra|L?b_M&9e>=ycYw;Rg_?tW2lDGpReO({p?8YAh(?Hr@hp-s@+63zDRM(-^O&FeX{0gt0kq7P^zO8f1A0gfWT8&+R}3)1m^KFdflJKoMu zvU=EWji{o84MQEZPAI_&&As`N5#wq#t>t&xYPF0c zqXR_%#yCZx^J8M>l;{&#DZU=dJJACiLJpQ5_qNw~%a%K!ORM?SqAKj@s;_Gt(hBm& zd>2vAl4q3E*)GJH`EhBbk2Otx7t9C!poi>P`oR36a9?}Axfd*jyX(kF_@?+yYZvR- z+WC#fMo+Z`J4*9?ZB#Wss-89GThh+O&=)J$*{FclcZAXjrJf` z%#nC+T})c)(VR^``Qa9RaxbKdC(#)mvfnnhf?MdpUT_*zvKC1XZpD?_7KsPH9;{qZ z9=f_oq@~`j4f@6!RmIqgfSjYSZngJf8wW)g((=#JiS!a{5l#ysqj ztJonmHOH^IH~GkO@U+x2ESqu3JJ3>wVPn?HEO= z_!ynm1X6p(kMHa|6dgMfau%exyocdP{__|oJ82^?Ry)k&6C;DC$vu0Kv`u!+WMuUS z;Cd@l#Xs=fv-iq#9dYvwd-AL94bEtf980>r+gZ%~806*3>?ZjSmG&QM9puWMg;w;B zPL{IlqhqO;IZ7d`xsj2PeN?SKkA@g^eoRDjXgNAk_KD5##y2rC+@?0%r&RATGV7YL zrhTKw+tXKQrGlq7yXlF#4KzsKvmPWZ#>b**#GC6@$-tR>CyX{z%ce%5su42AD@lfu z+UxiWI{W(TF=h{~)q6y}nT~nsjQO^$$GRLNsCRd0dv-k?1b@4yKT+kl7Ti_+XX)ud zruT9nZaH7jj!V^S-<|jBWIFYIGtP%(<(x3h*5nEz7V9{3FM5+bfcv+CS9k!b9sDit zlKSGfZ_`=hF|`MwgXo{$sXaPHvi01JHAjf;wkr&o9RusIKdoI;)+fXh4`{LW9P*r0 z#XyoNPp%wS@uVUR;9DITK8X9|Fv7W^xI$5dyx?MlGLSy>?bn20%Kpt zXcZ&zDKsOVa72Xv+YOxsC6X$nL!9w(+}GDaVP3AlwN|xb{f`k-bAF!Qy@uCXk4%0G z773Y^!H)SyFDXyyOj|cAqkYvs$`hv@@nkEWmFSPF87qbU%BwuD#ht2`FkUW{K^i^jWfc zIO;7cGRhg!rt4W>X(v+gnl9{GnN(u5M^}$zKK_}a`J3pgTnj;_k#FjNKh_cJOuu)m zc#Q4l*tV8(v~whx1L9ql+ru1<&ka2)O<#sYGM*Naz!J27LI^QGI2>~zhrZfA-6p-GCA72C8DaOP?q)qu)4XNP5!jzVm`ZV@2o4*yuiH}{iDul%Tr_U^>Qp% zkK9_z9cnB@(ZrPE{YUXP-i`mSgJU}Hw(px>t=@|Wkv2I0U1um?iQoPl>lAK} zYPjEoJ`y2cn24G@+WzM!adKQOnWTGses#Z%`fABlvN<$b>q3b|J{iXHZk&vIF?#+W zeloV5_~f+I--jK1u=+#%yfUJz*VZPwV=7Dfs5x;?cV7nNb*@CDENW}yoaugiP;=Ei z9hG9`$VmT_kh$J|se3B#IBIWrYvwRshi6r#;MSmRoN{rpI!!%9>t66D+v@hCpqdQ% zVWZ>I<2t&|)AmoI!sy|8y4gXPPe_$L3tAt@UVrr*7+L94?IuXSvFLmC8=AXoykjkHWIkM|hivBgP$mkUNt6o6%m#b6A9=1P&zLuuARr3jH zt>=_0KRGi_4d|p#bT8}Qc(QWGLbz7GodlX^PN!_Lry;pY@p`lXt`W(v=KvY3rKbwI zwTP&Sc0>=j;#RX3j~zS-`pY@(ywhuzSYjM5PIkvc#fm&i6H$H?c;8rLk) zSv*IaRT60%Qx>W!G#ascsLdA+SGIstXhk2>h3r_Nsz5~UM>$Qq|AtwOL1}xX)-OY% z{TLk?C78u%Jv%rxzO)52SL?F)4eQTmT^U4=eHPH%js$2PJgeUTL4&pK)bkck;;!*( z&$bc`?Kvu;7#Kh=)4R;nPjRpPrz{BnKYy-t-^-QzbuQsBy|QK?xe0$+v2whpG@~ob z+Or;lI;~@C;|wz`rFJAmN0S!ZB<9x~GJ3-dPoB=f_m&p;SMRtpC&97IRB85n99H8s zg^7~jE4IpbT}_*g?Y!0zN%j%I7UK0J$xn2dH383uCr{$6Vsw_+7~bYe`O^QIx*8qC zIrwAb(p+_kEal8w8Gp$(74-;z6g$ZGmR7CSxMCl~om4SZgG3i3A5)n;+>N_L8>1dFn8l$_P~TGb%{u%8Zb^=ylymyJW_q&iYiZTET8I7MDhj z?Q5Mj)p%l$SKCigEG)A&zz2M-bPA4834zD?R-fb#H#8P-kLUD$51#cjoRG_UB+0}h z6qWFIDptE1Pbe43HwL*fjnS=rT7KoJo}jxix|9OHml+?_)>>729k*@W@%Yl}Oik`X zf$f#{VVSk7QpF=y8zwSj`;zl|y%S~V0$fHzvb98UsuYTw;jJ=B;uIp2cE1#%cxeNo z#rTr^v~O+^J4c}`#@r)1XjdwYD*$>%9)rF%kHt$(c-!Z@wyWZL_yWGS6)7Zlp(79M zpv-HnZy8|yRmlY&J@A2R0MXpg)g`(77bVRz-`uDMhNKa^& zQKOSJ%BLrueuHmW)}T1Fe?}~$m$y=Op8SB5im!|VASYFB@7U4HJlaYM9NFeP)%Lm4 zQeBxTYX?L^bxlSi8^7;ht0$%!OT~6;E3EyW5e_S3r6;S)uxsHY+NOw%s0~i?W>}4( zwsxqn^t295>u-JkoXlFx;$C8l?ax6a*C4(C-9bDwJ!4DjziHbHr&M{p5H)ln9(+OX zoefp`s9E}T5VjU{X87!w%H=4d&kRgS~hNpfz4r|YE8j6vFn!}AaR z+;$#%7^D;Xvq~?RoWHrVT-mwT32O>SXq{>x=n4}*s9(~^DG}eTlkPQH@|sJ^&mC6 ze!H`5H|q;R^TdIEWYUXQsqcb9#EitS)Gk3SaH2e8&atd{06I^{Og>4GJe85c8=;IS zB|7{y&uUyxx!2~7^Xp47mYczweAgOYk%N#oX=e&hzmy?Tkt@3E5E`&IvyWOF+DbvWc;MuM7Hb*s;&I@YLl)om$qqi0Z*tgYSjRUz&aI1pbBA;pXi~Ep%nxt5!D1&Scwl@V zx5Kw+%}JeND9uk@@=VuRIH^z-E24f|h4d6nq~3=PQiYY(!CSNo3-oD(?W!B+Z2sIf zcVi~%w_9nGtujyfIa}xbog7CwgKr!A9CMVqqu*{chL&}8&xQ$cGUw#EU-$gIljAOD z;vEln!8gB)iNC@M(?09DOy`^S4wlCH3^6NtmTwO`>EE77D0)`Ty3;InyViwKJN_=` z)TN`I>8nq?QD$$6APMa}p%o;=4o5%7?&S26v*otYOU1s9HZoR08_iYn3G{;*k#f&w zYNNz4CwFF?RtuBIOsyM`#SlSd1kuxQd>~lHef8KhGOUpq!OX&J2evu$h`!2dj#rSj zdM0mbeG*psEpOR+W_Tr6@y$Y1tg=_RKRw!=xFrb?c@o7cl6R&^c4h8?WNqA`omG^# zu0O}EuX8<_ljSO=K8p3$GV?g5@tI6|dS#qArrkO`f5Xg(XjOhqEaqO5bL+64^W?~q z=)q4*&#+waN1P_Q?yUx^XI<9ymm_ghp0yLra+Vbo_%_~?!+VFRb_&X1MdU>}C$3rx zdR3mS=4jQG6`rj#r@l?05!iZWYVgSZ6)l!M)4%G!%5D6A!)1@TQjeI_ZfvS*>a5*$`5O7i0sEg9F-!MVe;of)o7y zcF#L2wX0prA?YpU9P#SOon_Ygd~hge?Pb-6yy6d--9HU05=>ycjp zS?kqtIV=C*5Y>~WWg|^o(OQU{k9MR{<6OpUy{b37*9uS9s*MwgPJQ{{#o?QLlRSw~ z9O<=)hL)$MyDs3*ZR-P^s z*#+>ie23|EjIZ3?iM*D`OIZUIbRP5A)=y_ItSp6jPZuQgck0o0@};JTP2 zJk2iBH!-Z_X=ht$^;v9E}V_8t2EpXKVr1e-IU4%6wr;j-EF?P03#U zBu-2^{>Ys(jkZBW{8+2=mI~kDnW&C}5qgLHW+08~MsSGuM{7DQfiil<%OC%_M)ZDm z&n{BTqdnV{ceJBXOwRg@({w%&(Hn7=-t3=#gTZKt^Q@Qs{))iHk zXc2=w2e9{YJtVP|Jn+e%z~c-QENwL=>ll41d$JKGgQK47QRbhOT+hwa?|wPrXzwPc z)*JT1@w0Z44xaXGo|c0SmaB4+c51{pzm!+hJSehqJ;Xj&6*n@So~}94$R6qpjX4JO z(64M_L$z(?X#}pRp>a$1@Z0Wu8CUY(?m02;^&mI|chB;9FXSPLkhBIVSKGJeov@;Y zlU%4-pl`VnqORGd-Who^BHi@dmVX>#$TEf_E_4RlQh0h#WO4L}M}0ZedC&6cD`QnOU{MIt{c#xqzia{j+^jQIWUS8JIU{B2Q8q0<~(bsb@yB{)BEwBYG<~$Wn-2 zw1-PM3jm(BR2jGY*_#s>kA`>=q;$oYtc%?xk9y)sFAn|B(XMx=^rzA2R#1@ZHn7RE znqX<{#i;QIy`BB>IA0Ci&w0A>NhbCFjY!<5lt78BU%3lD#5tC8xy%H;a!j=%$3l*e z;Irp~@l|}EQcn!1N1b(Z#Xm_05tY}sp`l)ZFF#kV`l?&xUY#bw=#I7*Y=4(;%kRq= zC6SkMOAxl6`;e!%w~;+~mlt-|c@<-_$M*aiTA*xJc2d8)t_XvupP5H&MJFpk(YSsn zJMZaK%Q4MgO|_ti6Pbb|)3tE(<#biVQ^WRyTctN@x!}1fTVB>{(ER%`dZfn8(@{^! zfKyMR&9)XvUb9|aIU?hpKZy(;#J<1t`!Cl!NNXhq&!JE2_kD);au?mX-^=}_^9{6n zA%*j^8@Aow{z|j2JqSVu^*r|E-b6N*TPY*fL@}2jodC^G_t_1+L3BC(5gDNSWhSI0{Y^T~P&d+YR6dr~*@6oUI=aHPB-S9T~#Hx>Oc{=Qvwa1cIO zQJPl$_A@Py+Mnk$Ry%Q;+oj<=*xkc8m|2E8lRTfXViw7>fLW8n9y2bSK9|<{!s+p7 zP&DOZj@L__&sd$N8LMrPe2lKW=piw@{;foG;+s41|F6R=fZo=i!b!F2^wv11PJW&q z%~Y0JbH;zQ9J&!4dNiOgF($L7XOlPWI5y>qM$J4E>+m0j&TzK$4^abf#&X#B%prv)svjt*|FvE5C2 zzwkz`HFw_DT-YaJbC1Srsg5VV>v#gbezIV$wD;5|JTI}QZVS|B|F4>g z`Ym&l1eJE#F)>srMUL&qphI%N%4nKh>ButU>&8 zsI``yHZ+g2iu}$`FZSB&az*@w$Yb+7-X&bczq5Wixv!b#^An4e|IhEN3HPWH$ZJqD z;Cx{38sc@^<@=1@$DP&dy%UQsyg40YeZ28%@H_J-pyE}uPiC$t&^q${c-ku?z3RNw zp4182;H?+D7HjFLP_rk3XQP*_P^JyNQ$p|5`7(FYId}Dne!Yu9H178gRM(W3l^@1O z=v@Q99WI$^d|D^LovcmM+Y-5!-Vtr`P zrs-{STavWLduEDn#A(`vf%AFLMI_#SCoQNgkP{wwi_JRdUi?m+5KvKG>g{;%Mde2H zP`)>Wy>V^cF3Ha}j~nYM2egs@&uLTbP5mYh7LqoT6k|_V23!<3uzT4P@tF2CPP^xf zAKvkS5^)-QgMZrDgWUb>oJ@RSatEksEVln#B6GM@a-QGMPa{^fff$7Mn9olmuHW&m zcT<_KFl>h@)4Awa9@v4aLSTipKch#{i~Vco8}Q-$G~ymV6jNz$Dd7NU$=XACwerms zMVN}e+6u+_X~ZRlI*tNsy+@Gtr93~4_*qni^EBd~x5I}|`?@mvkhgdKV;sPv5nE|@ zMc#>g5^~VJQx!(Or}EarJ?(XU_D>*YJmzXQ$wXbaKHXRAU3^N0T5s?9dpQA^ zHwSw*a5rp%c_rD!x%P8DF20I7((!BmZgBei1l}@A$WvsLflw*x?T3DT0xxePou9z# z`8u+na<8w9?7W7{a^C49``M!PsXB_WHr>UBc+kryGQn?d&xd)Fi*75)P zILR{<+Qm|}va~ACocvon0hhT6_MlIR5g(98oaIw!cS9rlqhfBzyG=Q_EKgX{JdZVB zRcrR~;<(S8-Kfved;6!c?gpl! z8|NpYqJ5feVvadym#m9;kkYd()i0hWtJDmZFvI5($==e#_RnxR{Tc>^8jI|lx;s&Y zYE0)Rq7pSo2OPJHW9KKLa=LWx?x^|~s7$5p{6ti8UGIIn6mM#5Id1O^mYtu7iiTz+ z_iBFTd)`K8*@b$f>ruD!80M;rjV`sGPC~pY&6!+qB<3$X@dkPN!UyQE*qA>6X61 z5*kO!%ADJ1#L+0%oxytjvNGh{sRx>k5*hU>PAR3%eW_`TBJ%^SdYjU7PB0~Z@Jb4H zk*VpvdKeY86#>?f?yTzfft@uFWox$~&Zc>JxVk4P?2R2hJ5!nJQ{!^=Uv$o|2T?Ah z=dw<&8N}ofIaJC;HA|00*6LiMayYDGSKQjwvS+#z~a-o)Cl2LrD}Q6eA_ zhIw66P6XzWmTSwnt5<*be#nmKc1HVDvu;hRDbd%rc^)Yzh;r`d`FWt)arOD(K4#;Y zCXlz@6WbQeH=sJUoH?M;`0wdFP)_h<-WWUp!^lt3YQ-Md#rb)hc)%&I;ZxzjBlKf_ z5AyT#IOSL2sC?1+d7S6xaZ(k*>*mgpoS>=qsN4OVtT)6;AoKZonDZw%>;`9l3S?&; zf$|h$qbI>P;z_-uK#XJGMr5P&2+z;MB%UP4APXQiCh9yt53|f>b`N<{uV?jISHIzb zw#klF_g2jgKl+><;HlM^g=R(qlMtVujS zj}rcK;(#y{t<|Y5(q7dWl2@QAe6!b5mdY83RJ@gMYnGThsev13KAJgKqsDU?n@r)I>SbjBYQadd6cf-pPw!H z{h{XN`^;HcLzCFEhZ!r^?RX!SNF8m^3UgJ~6d`E74}EZbuxyPLUFbDBh1OH0_!N;dC$T);kxpJDg#;Uk!Z7`JGL6 z%@va8Jf!mmuew7&HD8e$s%NadNV?V20P$ZL!#^@vq<@QjS-LeEb_A-7m|8p?Qf zQvSZDM>X$}9JoH!g67hY<$PTgT|SL_ukVLd2;GJ9?dV$sKDjd;p9H7dS{j^RFC*DU zz1t(LC1xDN7_|=~a>&&U)4$cN!4+l%(VCh=%l3+_TdQePT&dYvBIl(ikCnSVYQL8I zv5N-LtEkTe&)T`fXaF-LfU>QI8`=VAdRLwI-J^4?<48` zG%pP;aCV-ay*x-jJ1YJrq>IKTwR@vJ|6BA!Hhd*|xV!;R+R?Nvled%cJXK3=z;gX4IHOp*pHqFZx*HN_eF*Yp{}~YK<`7w5YB;p6r6pV{ zHP`JOL>x+W_4xI+?Ex)KYgn$SCDk>ez$tK>&l`uFKH50y_NPt&T}FGYOQvsLhj@m{ z-t*Yg82r$FcFH-h!YL`2&w<;l@WleCXx$ACaRn`#I{USJUiFM+PnlM&BB8#pGv zpWTLDf3`~(2Ppz!pWRPDXz|+&-=;hgTazL+8&+La;-Tv)`%S8Hr~cK zrQPh%c3-&|octxUM{CqLS?vAc-v@F2#`~-5@slez0`Wf_e!CLu7T$~BK8*VGJE3_O zPV0Hje8sAXp{ZKeQZG>sUr_J=a4^V&{jKpN^>>_$@=pBwWAKvS zuEc+Kv;HCMpJ;vmFxvb}<5A{%DRHKx4DHQm6I!0eKM;fcX+C*VL!s?*FEMi2`dKm> z&7Z)@?}s+X=<$a{QOa?@kMC6B|0Vp?{~T&vc@OVsLl3hwuAIDxe*YRz?}Wg8ajX%yAvFK6#9mQ z=Pb`X`!l@-D_-0}V(72wCEg!wx5Su|#u_U;9)ISz&OL;9Qu1+Itts1BuCXbL<(_3M z$8BjIw^VA;>Cp7|1`kzox1{l0)3=X>w$++a7R$A^d}XmuIclETtD0PETx(jG;zAGGD7OnMl_hwuVP=-&}$xK42pjGOFasu3ac1Yx6qC`m!j=ULl#ie=5-HLn8-)SHu6c{ z{>UBJfBS~Ry06S=+8M^(!*LR85(78}cg!x_BLgHGWYkzxW=K1$&*M4Pg-K4t@|r`} zx-reo^S-}um$4$jGP4oa)FX7j`+C=@R^F~8B9+XHoJUx{XsOQf+tKkY85V1M$%*QI zS}oUX`Ky6`^QXP1TxF2+x4!#ANRL${DLZzZ)M&{IHS4KNC+)Vi!@k|7$Ej)3*;TbR zrKZ=us`q5Sx1>&*L(LxD9G?c~Q`H`atbPj3gagb3)O~@YT2s`X@y<7oLm!?L2rFHZ zR-$3l#V&;;bt?Tfs5iyEgF%B{hL-nEy!Y9)%qjjHlGIx*KEa+khTpJco}nFC@AUeX z+wLLH2XF5Hxj&1H`pe;y^+MO9^0XIrx)Xls%hjjx+s&w|V7Yv9$A0{D%Tp(3+avgM zJnIfhj?ulP&;3yMojMOa?-3`<``o|psax^4d{P5wD@VI=74*UPP|Jg6`yqCs$FG1B z)aD+Aw5VcmO}o^~SAessa_}?}$of6QmscNU`>T_Wm3;5j|&bB;gHS5b5(OxxUU}~1=+O!^BAKs>X9ub_71+Rh6 z(mS7;*;Yhpj{!oXd0@F#NcL74>>RfHUEGC6Q3ceK_{i~UHcJ);Flc|ANe zL)BpwxiAJioLcg#7f?wanutcT@3yGp;U)8b#0O6gZJ?Cl@$_&IBgI~8+d^Jm@xWWT zXfrWLYvs0f;ulsF;iVMaITldu7RiDQ$T(Mn5&?oANaE>8eriE8*W8!dk<#HRk|Aax zyOl;zp`}g<)kxLxL*hKK8W9%~1m|=2+;N14%uBu_VYC7rMqA7A663-XbcgSuZ)&{O z{`Dg?pT-in7+3el>bE{vrptT&)d_`n?1$MN~&pvNBv^GV&Izp+ScB>@8SnbOz4YYv-G08O!DQZw732;4rjM|zN0G1! z3w<71FOH&P)EuN;NQ=Av5}IkhQI8n;fnGj;3yFiTT$7!{QCAzR)67u59AUI0in@PB zrAQ-vS51Rkt-YXm-s+%fagF82pj~4?4?x$JSEdV{2i0H2XG)^AzK`QuO9C2dTE8E( zm=?@oQ;(k8CkZuqS~lUc36D3HIv9Es{a}#ZR!UsS{hEX+vRpV&dib;qbOAJzbvnm^ ztH}pxBlVF7BR<15dZ&l94bU~Cq?$t|g_f&5)QbU;%w=7b?}tvsDb!A+C#}rOmhnUf zAqz$aWpm?Hr1K)8DCC~wz#drr;8VcV1|Ap>po$R@CtRZ+N1H8O9#3th%MnDQ9peYq zty)suGI0m3KN@5JeKqDDPt1Meu}K+UPP81>NVfjten`Au-| zr}#`7(kAO@S6HMT_4XTf@xw3@QJF}tQ5&6v*tQnwk8!@G4bKJYL)+e9X+1u<`sp@_ z8AX}V4~uy^a03kYw_rh{sGeXSbnG%YcoJIrb&Scnv<@%jIiU`^Uk&st()%$+#5~4s z)I6vp$I7{wvA%~;^O^hkAGVIEHr zOM#{Af|8tS>B!8OaT2l1vzQ)6{wS_F!h=&OrIt!CrOeiQnlEm04ioy8k={wzC{<fVl zG50CoqC7#!#W&@?v9%;x+Vm|yv3zugsyN7TFz}6Ugm1=3d9JkUv^n}$ZmIl?xiVy3 zbJx03jPA^am*O3yZsTFS~P-LG{I2%Z?|)J_uWI z^rC2V9A&|)v=B5WEjxK&?=H#zZiLQbU2eT%iT}ix?nQlg2H_;QU|#lTm(acAoMUVC z>|mHl{UU0b#KpH`9Y1r7cZT0?h6UUle&^d8@!P$_Z*zq+R&Xuu+K+qh#pkCn8|$aC z#V_Jn?z$2GuSP$o~XlohAE0cEuRZPLUc|Rz@J`^M0ich?)_H_fxduvA$SMboTy*h_ZkBmRY_Nk7R zYgFWgTn_*IOAd^Ct%r_aag_@u!@rRIaY`gT- zlUl}{NdbP+8C%X$h^uv#e7+tle;~X{gk`r=`1*0oPL(|G-GQYrBF#mPF$&IN?aGwk zzWuhMv8*1*W3}?NOzFp{iI48l;(MWpcvZ5iW3crj>dAmuncktFyj_uo{U2yww`=XR z?&3Ys7Ay}8#tp4L+KT2Ge9T$05eOhH8O}^<)MnY zsUWzQDUP+MsJwsn=UE-({@ z{O2vU7rR>b_{`|9jX?cPd%b+RY~gq#Q`W1Sf+dk@R`(UD$r5F?LXI)E!2Pjz)02r@ zWv#B3bmHfDmB>`pACA$3kV6RVIx_YQwmZhaPOxYB7RMvRGmOP2Q~ntCk4*}Vz(}-C zy5^Q;jjTZcDTolsxUt)wP8(|#)6+VAuv;KDD{BW$bh9e4M9 z3H?YD73&BaxcXhl0vtm2a1xEPw0q-lJD!WkyVKA1D3gA*Gi>V5)YKYI%PAw%Ha9}8 z3#ZoQNXmYuMX-6?S|4eQEgr4+dJfeBk$2W)JjNeGLa&48idLTt+*Y*?Ui3JJ)n+6q z4M1a6)hl^a`d?e0v&YgV@d?VoUxSf!#a`3~U)v&7gU+QPhK@*#OM zFN3q{JJ^}-D83_OO#FwWh`bWhlmY4QC7uFV(}JzK&d7SQmsQ#Wpt&HnWk^Pny0>}m zTxw~KO1RRartdp5|4)v|rmWS9XBc_XSmw*NNHn;viR@Q8-J^-s_Iig9AI^xDctWsV zvrG63?d4$nFOg7nUw8v%BL`(7%u4sD;hJ^sZPf%FiMik7jlehq+AS}Mz)VfzG8#(` zO-;ZReoMU67}a|G9+^BY^Futh{Cwq}R7?|efWEdGs3_5xz7i=NLkTmrUk6m#?|KZ{ z*J13l%eMLm3th?EHp2Ed?RAf){q+6ED}PSQcFV^neW8Ww=vqds zJ?wTgl1~a(u^m}NTQ~8Hup@;zZS0T2Z;#kkWgn^o%DccT5QEAu^W<0pHGs4o_^Z|( zhY4XcPt?zW%_X=jk2Zzlll0W?J{2bnK@oz?`4)+=BSAv@C^On zPI0AP#k4!<8M7i)si=nI-l$fK=Z#BBoXr0q%jZmeH+1kZP{p?v!B2Jkh z%u}>%ZqQ?vjR-&Mb08(Ll4@Hmb@;KRGY>OGS^9)FV#{yH36{+7udjO?47e=~#!7Nr zMkQ?C^YP%J#%f&|`=5-(deOwCXaNs4HG0(@K|^#>XNoAsg2t>%Kvn9yP^Ijdv80A= z8*9~;P+BwD1X!*}N*>~z zza=W)tXKIkY=Pfe4HP|&Xswa`RVBm#^zEF1->Gj<@0LvD;W5u?mfD4TQ*`uJwxidM__7k+u9eh#J5(p3saFwK zY(@4_k8wKNvn4Vnyt6Sc=OcVat_#n+M*e{n{6vyq7jx+5lXwBI@v+d1^xHRl94{u~ z*GS&uqwlTnbW7#u!Qr^DYx=hS*}qwv?Bf-irmjd^Yilr%a{dH9o(+jjC|rEBarNgJ>@x&wJ=ySuxgK48{!p>k6ki)e1ubd4rtt>0gVG6dB+G& zC?{NN; zcP_*8DN5@0^_~%4fL2-Q&Y1`DOR`L^V?D^)`w>ekru0nweaCRroCQbWU0Z&TM2#di1SI#1eFO< zQ5(y*#G_h|$N{Al>$DSn?;~U>)%`bEqX||t3tLB<*&77}Cuc(IdT8tW@NJ5kxT3w#S&4#7umhnIbsr*Y{$|fE{09Cd^^9C? zZdHx3fL_pAyipmkxAAe$2C>a0TFkCq_SlT0*4dtpo4Qt;WrJ8Yo*|JPE0b@4GoZJk zBh{WX`yi`?FZJ74@KAPF&O{MQ@kAdXO7z?we?3a$_3`5Hwlh*ov{u*(pEEXvuUdP7 zE-@DTPsw{#G0<@GO6&mKLwBb$CwTOFc!G*2Eh|19ujZkxb`C~$ZD(0fUC-j+@l_pH z6h<3Zs%!hx5j}KaI~s@le7jOcI;h-FG~`Nz(ms10E@MPdEfg_2%-PI(Y=Ca<1efs% z2tS87HN7QjAdfkER6#m9{NUt`(&x?5a*iL0Lze9Fxb6Ji68vzy1NPc7lKs$L6Dx}U^=jd@w%rTYb1R1|@!>9#D zF>9uIOy}hEH;o$^J7;^;o9F16=DGR&V_m5W=p9f#qV}p90cJ~#|qvzTSP+SA^Xc<1`3@`jhF7z#@hx`4vP@#vcO7d|{h;e)6 z0p7&!Ph$qQmuF(be>=2C%Nm_l zWf=t7jd3d4)LOo|9Ef)Wo)1rJClYH3dJf7w8>px?gV>X&q&wmr=dhzy%zQ<5tg3z zt$4$ErY+C2`pP+_$=lIosZM(da1tHOJK32QL`Zt&!O%Iq%LkTC(X&o+*-sDG;EeY+ z5l!61j&J&_&4;bM)JUdtZeyOUL+g4Zl~$5{`tT0e6u6kNnD6at+|jHit*fni`+LeE1^+CYk$sOf3~jY6>gstpGUOJH(G6kFH~Jf*q61Zc7{3m+2aioo#OB~zVez5 zBZBAcsefr!b)0*H2ik8^UKRc7Q9=~zT_@p4qP=s>9EouXt*SLc$RQ5e3X(eMFZkB3 znCN3IdR6n8XjXAbVwJQz^Uan^@B}I1d7ODZ3h9bU<0VLg7NF&0R5Q+OUpICO$BR@S zY>8CzB{>rfk8+hAT$Y78BEYt%rH;N33y6ERh3Q?e6|I8{dM?jKaP~RYeQ8rh?)W!h ziB^@{Z(Cb?t9LZ2p7xjMyba3u8R*9ox*r0u#Awt@A1A9sMD2VwhQao?xIdFPR| zXo;zw10Qs@lsvrRJnh4RjuT&+6Xhy7+M(v6Ol(@BV+%lLq8MFKz9NsMzDo`|#+&kG z{$6-6esd&egYhvvd6|>T*N$l4a`OZV@FJ>#;F0u=DjvxpBLeb;r%()D_h@R7P!=Ta zgIT4YamB*=Vx*I#m9>LRqO#Nj*F1#l-o>e3(-`|nb6%3^$!tm{dcu5%&UW>Rvaqq{ z82L^ccK&`t?7TkMj-qtEi*K#b>bfzvr(?Eq#e?D~bGFA<$)u-qbtIU3^V73pf%0AW z`KU(sdv6A5V(X{NxL}$pbfw(yv~ES3G>!oK{2ObktdJ4bqsNyJQ|Iaq`si^@lsght zjIqx0KxkXpF`nJN%5%`t!kw^- zpTg%o4qa8X#W9O~QGX31u{6F39clSWM1U;G6eQE~tufiHy_Ibub3xeyvAcAAH(F9e zNF=WP$ja(PNeTT@muJi`qFUMaetrLGT`p}F-4_*(4|a!jHOyq#dZm}NX?`+7#d(s7 zR)QuEdi)Ysk_*m=sr%9w+*TzDj#F<{l;Y?c>GsE!cHXm!K8G|q?5&OwRXxzGL;ASP z2=&}{lz=N}vfJ%(N$;^(ANqblS)g)1Ap-C95h=Zh))^Bx#EK~9c+o%JH)c%A;WOT& zvW3pEIzA(<9$m{aVERI%dOEMHgkD^|NAr69qf_EDo;&vH{muRMXcT-cMZILf%kWem6xIV|6`P zGOTsMw1ZgEWxWk-ixN%dXKNMTMeDSnXkA(g-?@hE^r&hx8)8+rua!cwKt_jTTx*fv z(5OXeV#vJAtov<@H_k5bLiX@WR`r8Cw#<5u8v9Li0t6{nK+5YVN|LT3Rn1>$%^b4s z@edlo4)`IDi1z2Y&k|RXHarzb!8%DYd#sM=iRg~C@tV<<&rc1R>Yr>)JByYvf_14s zQpP9mkDrs4P`54LsWaO3TbiQAc!up`V_=B+yQEj{L0;;0jx$HyJ#bU~0vDy+c%ayoQ970{tAM$G%>8(}^|g%D zwMCFXwa72x+ElF#3qT{7M-XSTqEBoAHjqn#ZseYdvgCyn#gY#)n$z;iVzqL5RQgm*Q}P*`1yS%|a11JplU#R<1^?&rA$VnUbakvx=NRL}CVf9f%+uqRlBj6PcmQT5FKrTM?V91Dbj6)eoQpeq$48z0sQM z8cQ7)9*xV6;Z9qX_>WsuX{3knZfrS51L?STjd!jsZ)DE5xtO?adEkriR>CYqRt2VF6Zk!^ujXA6q5hNj zW?J?